"""CLI for structured data generation."""

from __future__ import annotations

import json
from pathlib import Path

import typer

from worai.structured_data import (
    CreateRequest,
    CreateWorkflow,
    GenerateRequest,
    GenerateWorkflow,
    resolve_api_key_from_context,
)
from worai.errors import UsageError

app = typer.Typer(add_completion=False, no_args_is_help=True)
DEFAULT_BASE_URL = "https://api.wordlift.io"


@app.command("create")
def create(
    ctx: typer.Context,
    url: str = typer.Argument(..., help="Target page URL."),
    target_type_arg: str | None = typer.Argument(
        None, help="Schema.org type to generate (e.g., Review)."
    ),
    target_type: str | None = typer.Option(
        None, "--type", help="Schema.org type to generate (e.g., Review)."
    ),
    output_dir: Path = typer.Option(Path("."), "--output-dir", help="Output directory."),
    base_name: str = typer.Option("structured-data", "--base-name", help="Base output filename."),
    jsonld_path: Path | None = typer.Option(
        None, "--jsonld", help="Write JSON-LD to this file path."
    ),
    yarrml_path: Path | None = typer.Option(
        None, "--yarrml", help="Write YARRRML to this file path."
    ),
    debug: bool = typer.Option(False, "--debug", help="Write agent prompt/response to disk."),
    headed: bool = typer.Option(False, "--headed", help="Run the browser with a visible UI."),
    timeout_ms: int = typer.Option(30000, "--timeout-ms", help="Timeout (ms) for page loads."),
    max_retries: int = typer.Option(
        2, "--max-retries", help="Max retries for agent refinement when required props are missing."
    ),
    quality_check: bool = typer.Option(
        True,
        "--quality-check/--no-quality-check",
        help="Use agent-based quality scoring to decide retries.",
    ),
    max_xhtml_chars: int = typer.Option(
        40000, "--max-xhtml-chars", help="Max characters to keep in cleaned XHTML."
    ),
    max_text_node_chars: int = typer.Option(
        400, "--max-text-node-chars", help="Max characters per text node in cleaned XHTML."
    ),
    max_nesting_depth: int = typer.Option(
        2, "--max-nesting-depth", help="Max depth for related types in the schema guide."
    ),
    verbose: bool = typer.Option(
        True, "--verbose/--no-verbose", help="Emit progress logs to stderr."
    ),
    validate: bool = typer.Option(
        False, "--validate", help="Validate JSON-LD output with SHACL shapes."
    ),
    wait_until: str = typer.Option(
        "networkidle",
        "--wait-until",
        help="Playwright wait strategy.",
    ),
) -> None:
    if target_type is None:
        target_type = target_type_arg
    if not target_type:
        raise UsageError("Schema.org type is required. Pass it as an argument or via --type.")
    api_key = resolve_api_key_from_context(ctx.obj.get("config") if ctx.obj else None)

    def log(message: str) -> None:
        if verbose:
            typer.echo(message, err=True)

    request = CreateRequest(
        url=url,
        target_type=target_type,
        output_dir=output_dir,
        base_name=base_name,
        jsonld_path=jsonld_path,
        yarrml_path=yarrml_path,
        api_key=api_key,
        base_url=DEFAULT_BASE_URL,
        debug=debug,
        headed=headed,
        timeout_ms=timeout_ms,
        max_retries=max_retries,
        quality_check=quality_check,
        max_xhtml_chars=max_xhtml_chars,
        max_text_node_chars=max_text_node_chars,
        max_nesting_depth=max_nesting_depth,
        verbose=verbose,
        validate=validate,
        wait_until=wait_until,
    )
    result = CreateWorkflow().run(request, log)
    typer.echo(json.dumps(result.__dict__, indent=2))


@app.command("generate")
def generate(
    ctx: typer.Context,
    input_value: str = typer.Argument(..., metavar="INPUT", help="Sitemap URL/path or page URL."),
    yarrrml_path: Path = typer.Option(..., "--yarrrml", help="Path to YARRRML mapping file."),
    regex: str = typer.Option(".*", "--regex", help="Regex to filter URLs (matches full URL)."),
    output_dir: Path = typer.Option(Path("."), "--output-dir", help="Output directory."),
    output_format: str = typer.Option(
        "ttl", "--format", help="Output format: ttl, jsonld, rdf, nt, nq."
    ),
    concurrency: str = typer.Option(
        "auto", "--concurrency", help="Worker count or 'auto' to adapt to responses."
    ),
    headed: bool = typer.Option(False, "--headed", help="Run the browser with a visible UI."),
    timeout_ms: int = typer.Option(30000, "--timeout-ms", help="Timeout (ms) for page loads."),
    wait_until: str = typer.Option("networkidle", "--wait-until", help="Playwright wait strategy."),
    max_xhtml_chars: int = typer.Option(
        40000, "--max-xhtml-chars", help="Max characters to keep in cleaned XHTML."
    ),
    max_text_node_chars: int = typer.Option(
        400, "--max-text-node-chars", help="Max characters per text node in cleaned XHTML."
    ),
    max_pages: int | None = typer.Option(None, "--max-pages", help="Max pages to process."),
    verbose: bool = typer.Option(True, "--verbose/--no-verbose", help="Emit progress logs to stderr."),
) -> None:
    api_key = resolve_api_key_from_context(ctx.obj.get("config") if ctx.obj else None)

    def log(message: str) -> None:
        if verbose:
            typer.echo(message, err=True)

    request = GenerateRequest(
        input_value=input_value,
        yarrrml_path=yarrrml_path,
        regex=regex,
        output_dir=output_dir,
        output_format=output_format,
        concurrency=concurrency,
        api_key=api_key,
        base_url=DEFAULT_BASE_URL,
        headed=headed,
        timeout_ms=timeout_ms,
        wait_until=wait_until,
        max_xhtml_chars=max_xhtml_chars,
        max_text_node_chars=max_text_node_chars,
        max_pages=max_pages,
        verbose=verbose,
    )
    summary = GenerateWorkflow().run(request, log)
    typer.echo(json.dumps(summary, indent=2))
