"""Command-line interface for notulist, built with Typer."""

import logging
import os
from pathlib import Path
from typing import Annotated, Optional

import typer
from rich.logging import RichHandler
from rich.progress import Progress

from rich.console import Console

from notulist.config import AppSettings
from notulist.doctor import check_claude_cli, check_editor, check_repository
from notulist.editor import launch_editor
from notulist.notes import record_note
from notulist.organize import organize as organize_notes
from notulist.projects import projects_app
from notulist.prompts import ensure_default_prompts

FORMAT = "%(message)s"

logging.basicConfig(
    level="NOTSET",
    format=FORMAT,
    datefmt="[%X]",
    handlers=[RichHandler()],
)

app = typer.Typer()
app.add_typer(projects_app, name="projects")
logger = logging.getLogger(__name__)


@app.command()
def init(
    force: Annotated[
        bool,
        typer.Option("-f", "--force", help="Overwrite existing prompt files"),
    ] = False,
):
    """Initialize a new notes repository in the current directory."""
    base_directory = Path(os.getcwd())

    inbox_directory = base_directory / "today"
    daily_journal_directory = base_directory / "journal" / "daily"
    monthly_journal_directory = base_directory / "journal" / "monthly"
    projects_directory = base_directory / "projects"
    archive_directory = base_directory / "archive"

    with Progress() as progress:
        init_task = progress.add_task("Creating repository structure...", total=3)

        inbox_directory.mkdir(parents=True, exist_ok=True)
        daily_journal_directory.mkdir(parents=True, exist_ok=True)
        monthly_journal_directory.mkdir(parents=True, exist_ok=True)
        projects_directory.mkdir(parents=True, exist_ok=True)
        archive_directory.mkdir(parents=True, exist_ok=True)

        progress.update(init_task, advance=1)

        (inbox_directory / ".gitkeep").touch()
        (daily_journal_directory / ".gitkeep").touch()
        (monthly_journal_directory / ".gitkeep").touch()
        (projects_directory / ".gitkeep").touch()
        (archive_directory / ".gitkeep").touch()

        progress.update(init_task, advance=1)

        skipped = ensure_default_prompts(force=force)
        for filename in skipped:
            logger.warning(
                "Prompt file '%s' already exists, skipping."
                " Use --force to overwrite.",
                filename,
            )

        progress.update(init_task, advance=1)

    settings = AppSettings()
    settings.repository = str(base_directory)
    settings.save()

    logger.info(
        "Done initializing the repository. Use `notulist note` to create your first note!",
        extra={"markup": True},
    )


@app.command()
def note(
    message: Annotated[
        Optional[str], typer.Option("-m", "--message", help="Note content")
    ] = None,
    title: Annotated[
        Optional[str],
        typer.Option(
            "-t", "--title", help="Note title (generated by AI if not provided)"
        ),
    ] = None,
):
    """Create a new note in the today folder."""
    if message is not None:
        content = message
    else:
        content = launch_editor()

        if not content:
            logger.warning("Empty note, aborting.")
            raise typer.Exit(2)

    note_path = record_note(content, title=title)
    print(note_path)


@app.command()
def organize():
    """Organize today's notes: generate summaries and archive into projects."""
    settings = AppSettings()
    repository = Path(settings.repository)
    ensure_default_prompts()
    organize_notes(repository)


@app.command()
def doctor():
    """Check that the notulist environment is correctly set up."""
    console = Console()
    settings = AppSettings()
    all_ok = True

    checks: list[tuple[str, bool]] = [
        ("claude CLI on PATH", check_claude_cli()),
        ("Repository initialized", check_repository(settings.repository)),
        ("Editor available", check_editor(settings.editor)),
    ]

    for label, passed in checks:
        if passed:
            console.print(f"[green]\u2713[/green] {label}")
        else:
            console.print(f"[red]\u2717[/red] {label}")
            all_ok = False

    if not all_ok:
        raise typer.Exit(1)
