"""Sync command - one-time full sync to backend."""

from pathlib import Path
from typing import Annotated, Optional

import typer

from nogic.config import Config, is_dev_mode, get_api_url
from nogic.ignore import build_ignore_matcher
from nogic.watcher import SyncService
from nogic import telemetry, ui


def sync(
    directory: Annotated[Path, typer.Argument(help="Path to the directory to sync.")] = Path("."),
    ignore: Annotated[Optional[list[str]], typer.Option("--ignore", help="Patterns to ignore.")] = None,
    format: Annotated[Optional[str], typer.Option("--format", help="Output format: text or json.")] = None,
):
    """One-time sync of a directory to backend."""
    directory = directory.resolve()
    nogic_dir = directory / ".nogic"
    ignore = ignore or []
    json_mode = format == "json"

    if not nogic_dir.exists():
        ui.error("Not a Nogic project.")
        ui.dim("Run `nogic init` to initialize your project.")
        raise typer.Exit(1)

    config = Config.load(directory)

    if not config.api_key:
        ui.error("Not logged in.")
        ui.dim("Run `nogic login` to authenticate.")
        raise typer.Exit(1)

    if not config.project_id:
        ui.error("No project configured.")
        ui.dim("Run `nogic init` to initialize your project.")
        raise typer.Exit(1)

    if not json_mode:
        if is_dev_mode():
            ui.dev_banner(get_api_url())
        ui.banner("nogic sync", str(directory))
        ui.kv("Project", f"{config.project_id[:8]}...")

    log_fn = (lambda msg: None) if json_mode else (lambda msg: ui.dim(f"  {msg}"))
    sync_service = SyncService(config, directory, log=log_fn, json_mode=json_mode)

    try:
        sync_service.initial_scan(directory, build_ignore_matcher(directory, extra_patterns=ignore))
        telemetry.capture("cli_sync", {"status": "success"})
    except KeyboardInterrupt:
        if not json_mode:
            ui.console.print()
            ui.dim("Interrupted. Cleaning up...")
        try:
            sync_service.client.clear_staging(config.project_id)
        except Exception:
            pass
        telemetry.capture("cli_sync", {"status": "interrupted"})
        raise typer.Exit(1)
    except Exception as e:
        telemetry.capture("cli_sync", {"status": "error", "error": str(e)})
        raise
    finally:
        sync_service.close()

    if not json_mode:
        ui.console.print()
        ui.success("Done.")
