"""Integration tests for external editor GUI functionality."""
import pytest
import time
import sys
import os
import tempfile
import subprocess
from pathlib import Path

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

from src import api_hook_client


def get_vscode_processes():
    try:
        result = subprocess.run(
            ["powershell", "-Command", "Get-Process Code* -ErrorAction SilentlyContinue | Format-Table -AutoSize"],
            capture_output=True, text=True, timeout=5
        )
        return result.stdout
    except:
        return ""


@pytest.fixture
def test_external_editor_config():
    return {
        "ai": {"provider": "gemini", "model": "gemini-2.5-flash-lite"},
        "projects": {"paths": [], "active": ""},
        "paths": {"logs_dir": "logs", "scripts_dir": "scripts"},
        "tools": {
            "text_editors": {
                "vscode": {
                    "path": "C:\\apps\\Microsoft VS Code\\Code.exe",
                    "diff_args": ["--new-window", "--diff"]
                }
            },
            "default_editor": {"default_editor": "vscode"}
        }
    }


@pytest.mark.integration
@pytest.mark.timeout(120)
def test_vscode_launches_with_diff_view(live_gui):
    """Test that clicking external editor button launches VSCode."""
    proc, _ = live_gui
    client = api_hook_client.ApiHookClient()

    if not client.wait_for_server(timeout=15):
        pytest.skip("GUI server not available")

    subprocess.run(
        ["powershell", "-Command", "Stop-Process -Name 'Code*' -Force -ErrorAction SilentlyContinue"],
        timeout=10
    )
    time.sleep(1)

    before = get_vscode_processes()
    print(f"\n=== VSCODE LAUNCH TEST ===")
    print(f"VSCode before:\n{before if before.strip() else 'not running'}")

    with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False, encoding='utf-8') as f:
        f.write('HELLO_WORLD = "original"\n')
        f.write('def main():\n')
        f.write('    pass\n')
        test_file = f.name

    sample_patch = f"""--- a/{Path(test_file).name}
+++ b/{Path(test_file).name}
@@ -1,2 +1,3 @@
 HELLO_WORLD = "original"
-HELLO_WORLD = "modified"
+HELLO_WORLD = "changed"
+NEW_LINE = "added"
 def main():
     pass"""

    client.push_event("show_patch_modal", {
        "patch_text": sample_patch,
        "file_paths": [test_file]
    })

    time.sleep(2)

    state = client.get_gui_state()
    print(f"Patch modal visible: {state.get('_show_patch_modal')}")

    print("Clicking 'Open in External Editor' button...")
    result = client.click("btn_open_external_editor")
    print(f"Click API result: {result}")

    time.sleep(1)
    state_after = client.get_gui_state()
    error_msg = state_after.get("_patch_error_message", "")
    print(f"Error message: '{error_msg}'")

    print("Waiting 5 seconds for VSCode to launch...")
    time.sleep(5)

    after = get_vscode_processes()
    print(f"VSCode after:\n{after if after.strip() else 'not running'}")

    client.push_event("hide_patch_modal", {})
    time.sleep(1)

    os.unlink(test_file)


@pytest.mark.integration
@pytest.mark.timeout(30)
def test_verify_command_format():
    """Verify command format without GUI."""
    from src.external_editor import ExternalEditorLauncher, ExternalEditorConfig, TextEditorConfig

    config = ExternalEditorConfig(
        editors={
            "vscode": TextEditorConfig(
                name="vscode",
                path="C:\\apps\\Microsoft VS Code\\Code.exe",
                diff_args=["--new-window", "--diff"]
            )
        },
        default_editor="vscode"
    )
    launcher = ExternalEditorLauncher(config)

    with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False, encoding="utf-8") as f:
        f.write("original\n")
        orig = f.name

    with tempfile.NamedTemporaryFile(mode="w", suffix="_modified.txt", delete=False, encoding="utf-8") as f:
        f.write("modified\n")
        mod = f.name

    try:
        cmd = launcher.build_diff_command(
            launcher.config.editors["vscode"],
            orig,
            mod
        )
        print(f"\nCommand: {cmd}")
        assert "--diff" in cmd
        assert "--new-window" in cmd
        assert "Code.exe" in cmd[0]
        print("Format: CORRECT")
    finally:
        os.unlink(orig)
        os.unlink(mod)


@pytest.mark.integration
@pytest.mark.timeout(120)
def test_patch_modal_shows_with_configured_editor(live_gui, monkeypatch):
    """Test that when external editor is configured, the patch modal shows properly."""
    proc, _ = live_gui
    client = api_hook_client.ApiHookClient()

    if not client.wait_for_server(timeout=15):
        pytest.skip("GUI server not available")

    monkeypatch.setattr('src.app_controller.AppController.load_config', lambda: test_external_editor_config())

    sample_patch = """--- a/test.py
+++ b/test.py
@@ -1,2 +1,3 @@
 HELLO_WORLD = "original"
-HELLO_WORLD = "modified"
+HELLO_WORLD = "changed"
+NEW_LINE = "added"
 def main():
     pass"""

    client.push_event("show_patch_modal", {
        "patch_text": sample_patch,
        "file_paths": ["test.py"]
    })

    time.sleep(2)

    state = client.get_gui_state()
    assert state.get("_show_patch_modal") == True

    print("\n=== PATCH MODAL TEST ===")
    print("Patch modal visible with external editor config")
    print("===================")

    client.push_event("hide_patch_modal", {})
    time.sleep(1)


@pytest.mark.integration
@pytest.mark.timeout(120)
def test_button_click_is_received(live_gui, monkeypatch):
    """Test that btn_open_external_editor button click is received."""
    proc, _ = live_gui
    client = api_hook_client.ApiHookClient()

    if not client.wait_for_server(timeout=15):
        pytest.skip("GUI server not available")

    monkeypatch.setattr('src.app_controller.AppController.load_config', lambda: test_external_editor_config())

    sample_patch = """--- a/test.py
+++ b/test.py
@@ -1,2 +1,3 @@
 HELLO_WORLD = "original"
-HELLO_WORLD = "modified"
+HELLO_WORLD = "changed"
 def main():
     pass"""

    client.push_event("show_patch_modal", {
        "patch_text": sample_patch,
        "file_paths": ["test.py"]
    })

    time.sleep(2)

    state = client.get_gui_state()
    assert state.get("_show_patch_modal") == True

    print("\n=== BUTTON CLICK TEST ===")
    print("Sending client.click('btn_open_external_editor')...")

    client.click("btn_open_external_editor")

    time.sleep(2)

    state = client.get_gui_state()
    error = state.get("_patch_error_message", "")
    print(f"Error after click: '{error}'")
    print("Button click sent.")
    print("===================")

    client.push_event("hide_patch_modal", {})
    time.sleep(1)


@pytest.mark.integration
@pytest.mark.timeout(30)
def test_verify_vscode_command_format():
    """Direct verification of VSCode command format."""
    from src.external_editor import ExternalEditorLauncher, ExternalEditorConfig, TextEditorConfig

    config = ExternalEditorConfig(
        editors={
            "vscode": TextEditorConfig(
                name="vscode",
                path="C:\\apps\\Microsoft VS Code\\Code.exe",
                diff_args=["--new-window", "--diff"]
            )
        },
        default_editor="vscode"
    )
    launcher = ExternalEditorLauncher(config)

    with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False, encoding="utf-8") as f:
        f.write("original\n")
        orig = f.name

    with tempfile.NamedTemporaryFile(mode="w", suffix="_modified.txt", delete=False, encoding="utf-8") as f:
        f.write("modified\n")
        mod = f.name

    try:
        cmd = launcher.build_diff_command(
            launcher.config.editors["vscode"],
            orig,
            mod
        )
        print(f"\n=== COMMAND FORMAT ===")
        print(f"Launches: {cmd[0]}")
        print(f"Args: {cmd[1:]}")
        assert "--diff" in cmd
        assert "--new-window" in cmd
        assert "Code.exe" in cmd[0]
        print("Format: CORRECT")
        print("==================")
    finally:
        os.unlink(orig)
        os.unlink(mod)


if __name__ == "__main__":
    pytest.main([__file__, "-v", "-s"])