"""Factory reset for Cohort -- wipe all runtime data back to clean defaults.

Removes user-specific settings, cached state, databases, briefings,
and intel data so the project is back to a freshly-cloned baseline.

Usage::

    cohort reset              # interactive confirmation
    cohort reset --yes        # skip confirmation
    cohort reset --dry-run    # show what would be deleted

Programmatic::

    from cohort.reset import factory_reset
    result = factory_reset(data_dir="data")
"""

from __future__ import annotations

import json
import shutil
from pathlib import Path
from typing import Any

# =====================================================================
# Default settings (what a fresh install looks like)
# =====================================================================

DEFAULT_SETTINGS: dict[str, Any] = {
    "api_key": "",
    "api_provider": "anthropic",
    "api_model": "",
    "api_endpoint": "",
    "agents_root": "",
    "execution_backend": "api",
    "response_timeout": 300,
}

DEFAULT_CONTENT_CONFIG: dict[str, Any] = {
    "feeds": [],
    "topic": "",
    "check_interval_minutes": 60,
    "max_articles_per_feed": 10,
    "interest_keywords": [],
}

DEFAULT_HEALTH_STATE: dict[str, Any] = {
    "target_status": {},
    "last_alerts": {},
    "last_checks": {},
    "paused": False,
    "last_updated": "",
}

# =====================================================================
# Core reset logic
# =====================================================================

def _collect_targets(data_dir: Path) -> list[dict[str, str]]:
    """Collect all runtime artifacts that should be cleaned.

    Returns a list of dicts with 'path', 'action', and 'description' keys.
    Actions: 'reset' (overwrite with default), 'delete' (remove entirely).
    """
    targets: list[dict[str, str]] = []

    # --- Files to reset to defaults ---
    settings_path = data_dir / "settings.json"
    if settings_path.exists():
        targets.append({
            "path": str(settings_path),
            "action": "reset",
            "description": "Settings (api_key, api_provider, execution_backend, etc.)",
        })

    content_config = data_dir / "content_config.json"
    if content_config.exists():
        targets.append({
            "path": str(content_config),
            "action": "reset",
            "description": "Content pipeline config (RSS feeds, keywords)",
        })

    health_state = data_dir / "services" / "health_monitor" / "state.json"
    if health_state.exists():
        targets.append({
            "path": str(health_state),
            "action": "reset",
            "description": "Health monitor state (check timestamps)",
        })

    # --- Files/directories to delete entirely ---
    delete_patterns: list[tuple[str, str]] = [
        # Databases
        ("cohort.db", "SQLite database"),
        ("benchmark.db", "Benchmark database"),
        # Generated data
        ("briefings", "Executive briefing reports"),
        ("reports", "Generated reports"),
        ("tech_intel", "Cached intelligence articles"),
        ("briefing_rotation.json", "Briefing rotation state"),
        # Health monitor logs
        ("services/health_monitor/logs", "Health monitor logs"),
        ("services/health_monitor/service_registry.json", "Service registry"),
    ]

    for rel_path, desc in delete_patterns:
        full_path = data_dir / rel_path
        if full_path.exists():
            kind = "directory" if full_path.is_dir() else "file"
            targets.append({
                "path": str(full_path),
                "action": "delete",
                "description": f"{desc} ({kind})",
            })

    # Demo artifacts in project root (above data_dir)
    project_root = data_dir.parent
    demo_files = [
        "demo_agents.json",
        "demo_conversation.jsonl",
        "demo_conversation_channels.json",
        "scored_demo.jsonl",
        "scored_demo_channels.json",
        "scored_demo_agents.json",
    ]
    demo_dirs = ["demo_data", "scored_demo_data"]

    for name in demo_files:
        p = project_root / name
        if p.exists():
            targets.append({
                "path": str(p),
                "action": "delete",
                "description": f"Demo artifact: {name}",
            })

    for name in demo_dirs:
        p = project_root / name
        if p.exists():
            targets.append({
                "path": str(p),
                "action": "delete",
                "description": f"Demo directory: {name}/",
            })

    return targets


def factory_reset(
    data_dir: str | Path = "data",
    dry_run: bool = False,
) -> dict[str, Any]:
    """Reset Cohort to factory defaults.

    Args:
        data_dir: Path to the data directory (default: "data").
        dry_run: If True, report what would be done without changing anything.

    Returns:
        Dict with 'reset' (list of reset files), 'deleted' (list of deleted
        paths), and 'skipped' (list of paths that didn't exist).
    """
    data_path = Path(data_dir)
    targets = _collect_targets(data_path)

    result: dict[str, Any] = {
        "reset": [],
        "deleted": [],
        "errors": [],
        "dry_run": dry_run,
    }

    if not targets:
        return result

    for target in targets:
        path = Path(target["path"])
        action = target["action"]

        if dry_run:
            if action == "reset":
                result["reset"].append(target["path"])
            else:
                result["deleted"].append(target["path"])
            continue

        try:
            if action == "reset":
                _reset_file(path, data_path)
                result["reset"].append(target["path"])
            elif action == "delete":
                if path.is_dir():
                    shutil.rmtree(path)
                else:
                    path.unlink()
                result["deleted"].append(target["path"])
        except OSError as exc:
            result["errors"].append({"path": target["path"], "error": str(exc)})

    return result


def _reset_file(path: Path, data_dir: Path) -> None:
    """Overwrite a config file with its factory default."""
    defaults = {
        data_dir / "settings.json": DEFAULT_SETTINGS,
        data_dir / "content_config.json": DEFAULT_CONTENT_CONFIG,
        data_dir / "services" / "health_monitor" / "state.json": DEFAULT_HEALTH_STATE,
    }

    default_content = defaults.get(path)
    if default_content is not None:
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(json.dumps(default_content, indent=2) + "\n", encoding="utf-8")
    else:
        # Unknown file -- just delete it
        path.unlink(missing_ok=True)


# =====================================================================
# CLI entry point
# =====================================================================

def run_reset(yes: bool = False, dry_run: bool = False) -> int:
    """Run the factory reset from the CLI.

    Returns exit code: 0 = success, 1 = cancelled, 2 = errors.
    """
    data_dir = Path("data")

    targets = _collect_targets(data_dir)
    if not targets:
        print("[OK] Already clean -- nothing to reset.")
        return 0

    # Show what will happen
    print()
    print("  Cohort Factory Reset")
    print("  " + "=" * 40)
    print()

    reset_targets = [t for t in targets if t["action"] == "reset"]
    delete_targets = [t for t in targets if t["action"] == "delete"]

    if reset_targets:
        print("  Will reset to defaults:")
        for t in reset_targets:
            print(f"    [-] {t['description']}")
        print()

    if delete_targets:
        print("  Will delete:")
        for t in delete_targets:
            print(f"    [x] {t['description']}")
        print()

    if dry_run:
        print("  (dry run -- no changes made)")
        return 0

    # Confirm
    if not yes:
        try:
            answer = input("  Proceed? (yes/no): ").strip().lower()
        except (EOFError, KeyboardInterrupt):
            print("\n  Cancelled.")
            return 1
        if answer not in ("yes", "y"):
            print("  Cancelled.")
            return 1

    result = factory_reset(data_dir=data_dir, dry_run=False)

    # Report
    print()
    for path in result["reset"]:
        print(f"  [OK] Reset: {path}")
    for path in result["deleted"]:
        print(f"  [OK] Deleted: {path}")
    for err in result["errors"]:
        print(f"  [X] Error: {err['path']} -- {err['error']}")

    total = len(result["reset"]) + len(result["deleted"])
    print()
    print(f"  [OK] Factory reset complete. {total} item(s) cleaned.")

    if result["errors"]:
        print(f"  [!] {len(result['errors'])} error(s) occurred.")
        return 2

    return 0
