#!/usr/bin/env python3
"""
Reset local Windsurf auth/quota/switcher cache safely.

The script:
1. Quits Windsurf and windsurf-account-manager if they are running.
2. Backs up the current globalStorage files.
3. Removes Windsurf auth, plan, quota, and account-switcher cache entries.
4. Syncs the cleaned DB to state.vscdb.backup and validates integrity.
"""

from __future__ import annotations

import datetime as dt
import os
import shutil
import sqlite3
import subprocess
import sys
import time
from pathlib import Path


HOME = Path.home()
GLOBAL_STORAGE = HOME / "Library/Application Support/Windsurf/User/globalStorage"
STATE_DB = GLOBAL_STORAGE / "state.vscdb"
STATE_DB_BACKUP = GLOBAL_STORAGE / "state.vscdb.backup"
STORAGE_JSON = GLOBAL_STORAGE / "storage.json"

DELETE_SQL = """
DELETE FROM ItemTable
WHERE
    key IN (
        'windsurfAuthStatus',
        'windsurf.settings.cachedPlanInfo',
        'codeium.windsurf-windsurf_auth',
        'windsurf-tools.windsurf-switcher',
        'aixiaoxin123.windsurf-account-manager'
    )
    OR key LIKE 'secret://%codeium.windsurf%windsurf_auth%'
    OR key LIKE 'windsurf_auth-%'
    OR key LIKE '%windsurf_auth%';
"""


def run(command: list[str], check: bool = False) -> subprocess.CompletedProcess[str]:
    return subprocess.run(command, text=True, capture_output=True, check=check)


def quit_app(app_name: str) -> None:
    result = run(["osascript", "-e", f'tell application "{app_name}" to quit'])
    if result.returncode == 0:
        print(f"Requested quit: {app_name}")
    else:
        print(f"Quit request skipped or failed for {app_name}: {result.stderr.strip()}")


def is_running(process_name: str) -> bool:
    result = run(["pgrep", "-x", process_name])
    return result.returncode == 0


def wait_for_exit(process_names: list[str], timeout_seconds: int = 8) -> None:
    deadline = time.time() + timeout_seconds
    while time.time() < deadline:
        running = [name for name in process_names if is_running(name)]
        if not running:
            return
        time.sleep(0.5)

    still_running = [name for name in process_names if is_running(name)]
    if still_running:
        raise RuntimeError(
            "These processes are still running: "
            + ", ".join(still_running)
            + ". Please quit them manually and rerun this script."
        )


def ensure_files_exist() -> None:
    if not GLOBAL_STORAGE.exists():
        raise FileNotFoundError(f"Missing globalStorage directory: {GLOBAL_STORAGE}")
    if not STATE_DB.exists():
        raise FileNotFoundError(f"Missing Windsurf state DB: {STATE_DB}")


def make_backup() -> Path:
    timestamp = dt.datetime.now().strftime("%Y%m%d-%H%M%S")
    backup_dir = GLOBAL_STORAGE / f"reset-backup-{timestamp}"
    backup_dir.mkdir(parents=True, exist_ok=False)

    for source in (STATE_DB, STATE_DB_BACKUP, STORAGE_JSON):
        if source.exists():
            shutil.copy2(source, backup_dir / source.name)

    print(f"Backup created: {backup_dir}")
    return backup_dir


def reset_state_db() -> int:
    with sqlite3.connect(STATE_DB) as conn:
        conn.execute("BEGIN")
        conn.execute(DELETE_SQL)
        deleted = conn.execute("SELECT changes()").fetchone()[0]
        conn.commit()

    shutil.copy2(STATE_DB, STATE_DB_BACKUP)
    print(f"Deleted cache rows: {deleted}")
    return int(deleted)


def validate_db() -> None:
    with sqlite3.connect(STATE_DB) as conn:
        result = conn.execute("PRAGMA integrity_check").fetchone()[0]

    if result != "ok":
        raise RuntimeError(f"SQLite integrity check failed: {result}")

    print("SQLite integrity check: ok")


def main() -> int:
    try:
        ensure_files_exist()

        quit_app("Windsurf")
        quit_app("windsurf-account-manager")
        wait_for_exit(["Windsurf", "windsurf-account-manager"])

        backup_dir = make_backup()
        reset_state_db()
        validate_db()

        print("")
        print("Done. Reopen Windsurf and sign in again.")
        print(f"Restore path if needed: {backup_dir}")
        return 0
    except Exception as exc:
        print(f"Error: {exc}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
