"""Projects command - list and manage projects."""

import json
from pathlib import Path
from typing import Annotated, Optional

import httpx
import typer

from nogic.config import Config
from nogic.api import NogicClient
from nogic.api.client import get_directory_hash
from nogic import ui

projects_app = typer.Typer(no_args_is_help=True, rich_markup_mode="rich")


def _require_auth() -> Config:
    config = Config.load()
    if not config.api_key:
        ui.error("Not logged in.")
        ui.dim("Run `nogic login` to authenticate.")
        raise typer.Exit(1)
    return config


@projects_app.command("current")
def current_project(
    directory: Annotated[Path, typer.Argument(help="Path to the project directory.")] = Path("."),
    output_format: Annotated[Optional[str], typer.Option("--format", help="Output format: text or json.")] = None,
):
    """Show the current project mapping for a directory."""
    directory = directory.resolve()
    config = Config.load(directory)
    json_mode = output_format == "json"

    if not config.project_id:
        if json_mode:
            typer.echo(json.dumps({"error": "No project mapping found.", "directory": str(directory)}))
        else:
            ui.error("No project mapping found.")
            ui.dim("Run `nogic init` to initialize this directory.")
        raise typer.Exit(1)

    if json_mode:
        typer.echo(
            json.dumps(
                {
                    "directory": str(directory),
                    "project_id": config.project_id,
                    "project_name": config.project_name,
                }
            )
        )
        return

    ui.banner("nogic projects current")
    ui.kv("Directory", str(directory))
    ui.kv("Project ID", config.project_id)
    ui.kv("Project Name", config.project_name or "(not set)")


@projects_app.command("list")
def list_projects(
    verbose: Annotated[bool, typer.Option("--verbose", "-v", help="Show detailed info.")] = False,
):
    """List your projects."""
    config = _require_auth()

    client = NogicClient(config)
    try:
        with ui.status_spinner("Fetching projects..."):
            projects_list = client.list_projects()

        if not projects_list:
            ui.info("No projects found.")
            ui.dim("Create one with: nogic init")
            return

        ui.banner("nogic projects", f"{len(projects_list)} project(s)")
        for p in projects_list:
            marker = " [green]*[/]" if p.id == config.project_id else ""
            ui.console.print(f"  [bold]{p.name}[/] [dim]({p.id[:8]}...)[/]{marker}")
            if verbose:
                if p.directory_hash:
                    ui.dim(f"    Hash: {p.directory_hash[:16]}...")
                if p.created_at:
                    ui.dim(f"    Created: {p.created_at}")

        if config.project_id:
            ui.console.print()
            ui.dim("  * = current project")

    except httpx.HTTPStatusError as e:
        ui.error(f"Error ({e.response.status_code})")
        raise typer.Exit(1)
    finally:
        client.close()


@projects_app.command("use")
def use_project(
    project_id: Annotated[str, typer.Argument(help="Project ID (prefix match).")],
):
    """Set the current project by ID."""
    cwd = Path.cwd()
    config = _require_auth()

    client = NogicClient(config)
    try:
        with ui.status_spinner("Fetching projects..."):
            projects_list = client.list_projects()
        matched = [p for p in projects_list if p.id.startswith(project_id)]

        if not matched:
            ui.error(f"No project found matching: {project_id}")
            raise typer.Exit(1)
        if len(matched) > 1:
            ui.error(f"Multiple projects match '{project_id}':")
            for p in matched:
                ui.console.print(f"  {p.name} ({p.id})")
            raise typer.Exit(1)

        config.project_id = matched[0].id
        config.project_name = matched[0].name
        config._save_project_mapping(cwd)
        ui.success(f"Now using project: {matched[0].name}")

    except httpx.HTTPStatusError as e:
        ui.error(f"Error ({e.response.status_code})")
        raise typer.Exit(1)
    finally:
        client.close()


@projects_app.command("create")
def create_project(
    name: Annotated[str, typer.Argument(help="Project name.")],
    use: Annotated[bool, typer.Option("--use", help="Set as current project.")] = False,
    link: Annotated[bool, typer.Option("--link", help="Link to current directory.")] = False,
):
    """Create a new project."""
    cwd = Path.cwd()
    config = _require_auth()

    dir_hash = get_directory_hash(str(cwd)) if link else None

    client = NogicClient(config)
    try:
        with ui.status_spinner("Creating project..."):
            project = client.create_project(name, dir_hash)

        ui.success(f"Created project: {project.name}")
        ui.kv("Project ID", project.id)
        if link:
            ui.kv("Linked to", str(cwd))

        if use or link:
            config.project_id = project.id
            config.project_name = project.name
            if link:
                config.directory_hash = dir_hash
            config._save_project_mapping(cwd)
            ui.dim("Set as current project.")

    except httpx.HTTPStatusError as e:
        if e.response.status_code == 409:
            data = e.response.json()
            ui.error("A project already exists for this directory.")
            ui.kv("Project", f"{data.get('project_name')} ({data.get('project_id')[:8]}...)", indent=4)
            ui.dim("  Use 'nogic init' to reuse the existing project.")
        else:
            ui.error(f"Error ({e.response.status_code})")
        raise typer.Exit(1)
    finally:
        client.close()
