"""Tests for browser profile detection — mock filesystem, verify parsing."""

from __future__ import annotations

import json
import sqlite3
from pathlib import Path

import pytest

from proxym.virt.browser_profiles import (
    AppDataSync,
    BrowserProfile,
    detect_all_profiles,
    detect_chrome_profiles,
    detect_chromium_profiles,
    detect_firefox_profiles,
    generate_app_data_sync,
)


@pytest.fixture
def firefox_home(tmp_path, monkeypatch):
    """Create a fake Firefox profile structure."""
    ff_dir = tmp_path / ".mozilla" / "firefox"
    ff_dir.mkdir(parents=True)

    # Create profiles.ini
    ini = ff_dir / "profiles.ini"
    ini.write_text(
        "[General]\n"
        "StartWithLastProfile=1\n\n"
        "[Profile0]\n"
        "Name=default-release\n"
        "IsRelative=1\n"
        "Path=abc123.default-release\n"
        "Default=1\n\n"
        "[Profile1]\n"
        "Name=work\n"
        "IsRelative=1\n"
        "Path=def456.work\n"
    )

    # Create profile directories
    p1 = ff_dir / "abc123.default-release"
    p1.mkdir()
    (p1 / "prefs.js").write_text("user_pref('browser.startup.homepage', 'about:home');")

    # Create cookies.sqlite with test data
    cookies_db = p1 / "cookies.sqlite"
    conn = sqlite3.connect(str(cookies_db))
    conn.execute(
        "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, host TEXT, name TEXT, value TEXT)"
    )
    conn.execute("INSERT INTO moz_cookies VALUES (1, '.anthropic.com', 'session', 'abc')")
    conn.execute("INSERT INTO moz_cookies VALUES (2, '.github.com', 'user', 'xyz')")
    conn.commit()
    conn.close()

    p2 = ff_dir / "def456.work"
    p2.mkdir()
    (p2 / "prefs.js").write_text("// empty")

    monkeypatch.setattr(Path, "home", lambda: tmp_path)
    return tmp_path


@pytest.fixture
def chrome_home(tmp_path, monkeypatch):
    """Create a fake Chrome profile structure."""
    chrome_dir = tmp_path / ".config" / "google-chrome"
    chrome_dir.mkdir(parents=True)

    # Create Local State
    local_state = chrome_dir / "Local State"
    local_state.write_text(json.dumps({
        "profile": {
            "info_cache": {
                "Default": {"name": "Personal"},
                "Profile 1": {"name": "Work"},
            }
        }
    }))

    # Create profile directories
    default_dir = chrome_dir / "Default"
    default_dir.mkdir()

    # Create Cookies with test data
    cookies_file = default_dir / "Cookies"
    conn = sqlite3.connect(str(cookies_file))
    conn.execute(
        "CREATE TABLE cookies (host_key TEXT, name TEXT, value TEXT)"
    )
    conn.execute("INSERT INTO cookies VALUES ('.openrouter.ai', 'session', 'abc')")
    conn.execute("INSERT INTO cookies VALUES ('.windsurf.ai', 'token', 'xyz')")
    conn.commit()
    conn.close()

    p1_dir = chrome_dir / "Profile 1"
    p1_dir.mkdir()

    monkeypatch.setattr(Path, "home", lambda: tmp_path)
    return tmp_path


# ── Firefox Detection ────────────────────────────────────────

class TestFirefoxDetection:
    def test_detects_profiles(self, firefox_home):
        profiles = detect_firefox_profiles()
        assert len(profiles) == 2
        names = {p.name for p in profiles}
        assert "default-release" in names
        assert "work" in names

    def test_profile_has_correct_browser(self, firefox_home):
        profiles = detect_firefox_profiles()
        for p in profiles:
            assert p.browser == "firefox"

    def test_detects_sessions(self, firefox_home):
        profiles = detect_firefox_profiles()
        default_profile = next(p for p in profiles if p.name == "default-release")
        assert default_profile.has_sessions is True

    def test_detects_account_domains(self, firefox_home):
        profiles = detect_firefox_profiles()
        default_profile = next(p for p in profiles if p.name == "default-release")
        assert "anthropic.com" in default_profile.accounts_detected
        assert "github.com" in default_profile.accounts_detected

    def test_no_sessions_for_empty_profile(self, firefox_home):
        profiles = detect_firefox_profiles()
        work_profile = next(p for p in profiles if p.name == "work")
        assert work_profile.has_sessions is False

    def test_returns_empty_when_no_firefox(self, tmp_path, monkeypatch):
        monkeypatch.setattr(Path, "home", lambda: tmp_path)
        assert detect_firefox_profiles() == []

    def test_size_is_positive(self, firefox_home):
        profiles = detect_firefox_profiles()
        default_profile = next(p for p in profiles if p.name == "default-release")
        assert default_profile.size_mb > 0


# ── Chrome Detection ─────────────────────────────────────────

class TestChromeDetection:
    def test_detects_profiles(self, chrome_home):
        profiles = detect_chrome_profiles()
        assert len(profiles) == 2
        names = {p.name for p in profiles}
        assert "Personal" in names
        assert "Work" in names

    def test_profile_has_correct_browser(self, chrome_home):
        profiles = detect_chrome_profiles()
        for p in profiles:
            assert p.browser == "chrome"

    def test_detects_sessions_and_accounts(self, chrome_home):
        profiles = detect_chrome_profiles()
        personal = next(p for p in profiles if p.name == "Personal")
        assert personal.has_sessions is True
        assert "openrouter.ai" in personal.accounts_detected
        assert "windsurf.ai" in personal.accounts_detected

    def test_returns_empty_when_no_chrome(self, tmp_path, monkeypatch):
        monkeypatch.setattr(Path, "home", lambda: tmp_path)
        assert detect_chrome_profiles() == []


# ── detect_all_profiles ──────────────────────────────────────

class TestDetectAll:
    def test_combines_firefox_and_chrome(self, firefox_home, chrome_home, monkeypatch):
        # Both fixtures use the same monkeypatch, but last one wins.
        # Use firefox_home which has both structures since chrome_home
        # was set up on a different tmp_path. Test individually instead.
        profiles = detect_all_profiles()
        browsers = {p.browser for p in profiles}
        # At least the one matching the patched home should appear
        assert len(profiles) >= 1


# ── BrowserProfile Serialization ─────────────────────────────

class TestBrowserProfileSerialization:
    def test_to_dict(self):
        p = BrowserProfile(
            browser="firefox",
            name="default",
            path=Path("/home/user/.mozilla/firefox/abc"),
            size_mb=42.5,
            has_sessions=True,
            accounts_detected=["anthropic.com", "github.com"],
        )
        d = p.to_dict()
        assert d["browser"] == "firefox"
        assert d["size_mb"] == 42.5
        assert d["has_sessions"] is True
        assert "anthropic.com" in d["accounts_detected"]


# ── AppDataSync Generation ───────────────────────────────────

class TestAppDataSync:
    def test_firefox_sync_without_passwords(self):
        p = BrowserProfile(browser="firefox", name="default",
                           path=Path("/home/user/.mozilla/firefox/abc"))
        sync = generate_app_data_sync(p, with_passwords=False)
        assert sync.browser == "firefox"
        assert "key4.db" not in sync.include
        assert "logins.json" not in sync.include
        assert "cookies.sqlite" in sync.include
        assert sync.target == "/home/dev/.mozilla/firefox/cloned-profile"

    def test_firefox_sync_with_passwords(self):
        p = BrowserProfile(browser="firefox", name="default",
                           path=Path("/home/user/.mozilla/firefox/abc"))
        sync = generate_app_data_sync(p, with_passwords=True)
        assert "key4.db" in sync.include
        assert "logins.json" in sync.include

    def test_chrome_sync_without_passwords(self):
        p = BrowserProfile(browser="chrome", name="Default",
                           path=Path("/home/user/.config/google-chrome/Default"))
        sync = generate_app_data_sync(p, with_passwords=False)
        assert sync.browser == "chrome"
        assert "Login Data" not in sync.include
        assert "Cookies" in sync.include
        assert "google-chrome" in sync.target

    def test_chrome_sync_with_passwords(self):
        p = BrowserProfile(browser="chrome", name="Default",
                           path=Path("/home/user/.config/google-chrome/Default"))
        sync = generate_app_data_sync(p, with_passwords=True)
        assert "Login Data" in sync.include

    def test_chromium_target_dir(self):
        p = BrowserProfile(browser="chromium", name="Default",
                           path=Path("/home/user/.config/chromium/Default"))
        sync = generate_app_data_sync(p, with_passwords=False)
        assert "chromium" in sync.target
