from pathlib import Path

from shared_claude_state import SharedClaudeState


def test_sync_shared_links_preserves_auth_and_shares_user_state(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "avi" / "CLAUDE_HOME"
    shared_home.mkdir()
    account_home.mkdir(parents=True)

    (account_home / ".credentials.json").write_text("account-token", encoding="utf-8")
    (account_home / "claude.json").write_text("account-identity", encoding="utf-8")
    (account_home / "account_identity.json").write_text("identity", encoding="utf-8")
    (account_home / ".last-cleanup").write_text("account-cleanup", encoding="utf-8")
    (account_home / "history.jsonl").write_text(
        '{"session_id":"account","ts":2}\n', encoding="utf-8"
    )
    (shared_home / "history.jsonl").write_text(
        '{"session_id":"shared","ts":1}\n', encoding="utf-8"
    )
    (shared_home / "settings.json").write_text("settings", encoding="utf-8")
    (shared_home / ".last-cleanup").write_text("shared-cleanup", encoding="utf-8")
    (shared_home / "skills").mkdir()

    SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    for name in ("history.jsonl", "settings.json", "skills"):
        entry = account_home / name
        assert entry.is_symlink()
        assert entry.resolve() == (shared_home / name).resolve()
    assert (shared_home / "history.jsonl").read_text(encoding="utf-8").splitlines() == [
        '{"session_id":"shared","ts":1}',
        '{"session_id":"account","ts":2}',
    ]
    for name in (
        ".credentials.json",
        ".last-cleanup",
        "claude.json",
        "account_identity.json",
    ):
        assert not (account_home / name).is_symlink()


def test_sync_all_shared_links_uses_claude_home_directory(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    shared_home.mkdir()
    (shared_home / "agents").mkdir()
    for slug in ("avi", "multideal"):
        (accounts_dir / slug / "CLAUDE_HOME").mkdir(parents=True)

    SharedClaudeState(shared_home, accounts_dir).sync_all_shared_links()

    for slug in ("avi", "multideal"):
        link = accounts_dir / slug / "CLAUDE_HOME" / "agents"
        assert link.is_symlink()
        assert link.resolve() == (shared_home / "agents").resolve()


def test_sync_all_shared_links_ignores_staged_accounts(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    staged_home = accounts_dir / ".avi.staged-123" / "CLAUDE_HOME"
    shared_home.mkdir()
    staged_home.mkdir(parents=True)
    (shared_home / "settings.json").write_text("settings", encoding="utf-8")

    SharedClaudeState(shared_home, accounts_dir).sync_all_shared_links()

    assert not (staged_home / "settings.json").exists()


def test_sync_shared_links_resolves_divergent_installation_id(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync" / "CLAUDE_HOME"
    shared_home.mkdir()
    account_home.mkdir(parents=True)
    (shared_home / "installation_id").write_text("shared-id", encoding="utf-8")
    (account_home / "installation_id").write_text("account-id", encoding="utf-8")

    SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    entry = account_home / "installation_id"
    assert entry.is_symlink()
    assert entry.resolve() == (shared_home / "installation_id").resolve()
    assert (shared_home / "installation_id").read_text(encoding="utf-8") == "shared-id"


def test_sync_shared_links_unshares_per_account_backoff(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync" / "CLAUDE_HOME"
    shared_home.mkdir()
    account_home.mkdir(parents=True)
    (shared_home / "usage-backoff.json").write_text("other-account", encoding="utf-8")
    (account_home / "usage-backoff.json").symlink_to(shared_home / "usage-backoff.json")

    SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    entry = account_home / "usage-backoff.json"
    assert not entry.is_symlink()
    assert entry.read_text(encoding="utf-8") == "other-account"


def test_sync_shared_links_keeps_daemon_runtime_state_per_account(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync2" / "CLAUDE_HOME"
    shared_home.mkdir()
    account_home.mkdir(parents=True)
    for name in ("daemon.lock", "daemon.status.json"):
        (shared_home / name).write_text("other-account", encoding="utf-8")
        (account_home / name).write_text("current-account", encoding="utf-8")

    SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    for name in ("daemon.lock", "daemon.status.json"):
        entry = account_home / name
        assert not entry.is_symlink()
        assert entry.read_text(encoding="utf-8") == "current-account"
        assert (shared_home / name).read_text(encoding="utf-8") == "other-account"


def test_sync_shared_links_unshares_per_account_update_result(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync" / "CLAUDE_HOME"
    shared_home.mkdir()
    account_home.mkdir(parents=True)
    (shared_home / ".last-update-result.json").write_text("other-account", encoding="utf-8")
    (account_home / ".last-update-result.json").write_text("current-account", encoding="utf-8")

    SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    entry = account_home / ".last-update-result.json"
    assert not entry.is_symlink()
    assert entry.read_text(encoding="utf-8") == "current-account"


def test_sync_shared_links_shares_projects_despite_duplicate_transcripts(
    tmp_path: Path,
) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync2" / "CLAUDE_HOME"
    slug = "-home-user-Projects-overdeck"
    (shared_home / "projects" / slug).mkdir(parents=True)
    (account_home / "projects" / slug).mkdir(parents=True)

    (shared_home / "projects" / slug / "abc.jsonl").write_text(
        '{"n":1}\n{"n":2}\n', encoding="utf-8"
    )
    (account_home / "projects" / slug / "abc.jsonl").write_text('{"n":1}\n', encoding="utf-8")
    (account_home / "projects" / slug / "def.jsonl").write_text('{"n":9}\n', encoding="utf-8")

    conflicts = SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    assert conflicts == []
    assert (account_home / "projects").is_symlink()
    assert (account_home / "projects").resolve() == (shared_home / "projects").resolve()
    assert (shared_home / "projects" / slug / "abc.jsonl").read_text(
        encoding="utf-8"
    ) == '{"n":1}\n{"n":2}\n'
    assert (shared_home / "projects" / slug / "def.jsonl").exists()


def test_sync_shared_links_keeps_the_account_copy_when_it_is_the_longer_one(
    tmp_path: Path,
) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync2" / "CLAUDE_HOME"
    (shared_home / "projects").mkdir(parents=True)
    (account_home / "projects").mkdir(parents=True)
    (shared_home / "projects" / "abc.jsonl").write_text('{"n":1}\n', encoding="utf-8")
    (account_home / "projects" / "abc.jsonl").write_text(
        '{"n":1}\n{"n":2}\n', encoding="utf-8"
    )

    conflicts = SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    assert conflicts == []
    assert (shared_home / "projects" / "abc.jsonl").read_text(
        encoding="utf-8"
    ) == '{"n":1}\n{"n":2}\n'


def test_sync_shared_links_reports_a_genuinely_divergent_transcript(tmp_path: Path) -> None:
    shared_home = tmp_path / ".claude"
    accounts_dir = tmp_path / ".local/state/overdeck/systray/runtime" / "claude-accounts"
    account_home = accounts_dir / "zync2" / "CLAUDE_HOME"
    (shared_home / "projects").mkdir(parents=True)
    (account_home / "projects").mkdir(parents=True)
    (shared_home / "projects" / "abc.jsonl").write_text('{"n":1}\n', encoding="utf-8")
    (account_home / "projects" / "abc.jsonl").write_text('{"n":7}\n', encoding="utf-8")

    conflicts = SharedClaudeState(shared_home, accounts_dir).sync_shared_links(account_home)

    assert conflicts
    assert (account_home / "projects" / "abc.jsonl").read_text(
        encoding="utf-8"
    ) == '{"n":7}\n'
