"""AI-powered interactions using the Claude CLI."""

import json
import logging
import subprocess

from pydantic import BaseModel, Field

logger = logging.getLogger(__name__)


class NoteTitle(BaseModel):
    """Schema for a generated note title."""

    title: str = Field(min_length=1)


def claude_structured_output[T: BaseModel](prompt: str, model_class: type[T]) -> T:
    """
    Call the Claude CLI with a prompt and return structured output.

    Parameters
    ----------
    prompt : str
        The full prompt text to send to Claude.
    model_class : type[T]
        The Pydantic model class for the JSON schema and response parsing.

    Returns
    -------
    T
        Parsed structured output as an instance of ``model_class``.

    Raises
    ------
    subprocess.CalledProcessError
        If the Claude CLI process exits with a non-zero status.
    """
    schema = json.dumps(model_class.model_json_schema())
    try:
        result = subprocess.run(
            [
                "claude",
                "-p",
                prompt,
                "--output-format",
                "json",
                "--json-schema",
                schema,
                "--model",
                "haiku",
            ],
            capture_output=True,
            text=True,
            check=True,
        )
    except subprocess.CalledProcessError as e:
        logger.info("claude process failed with exit code %d", e.returncode)
        logger.info("claude stdout: %s", e.stdout)
        logger.info("claude stderr: %s", e.stderr)
        raise

    response = json.loads(result.stdout)

    return model_class(**response["structured_output"])


def generate_title(content: str) -> NoteTitle:
    """
    Generate a short, descriptive title for a note using Claude.

    Parameters
    ----------
    content : str
        The note body to generate a title for.

    Returns
    -------
    NoteTitle
        The generated title wrapped in a ``NoteTitle`` model.

    Raises
    ------
    subprocess.CalledProcessError
        If the Claude CLI process exits with a non-zero status.
    """
    prompt = (
        f"Generate a short, descriptive title for the following note.\n\n{content}"
    )
    return claude_structured_output(prompt, NoteTitle)
