"""Web pages workflows backed by SDK ingestion APIs."""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Any, Callable
from urllib.parse import urlparse

from worai.core.ingest import DEFAULT_INGEST_LOADER, resolve_ingest_settings
from worai.core.url_sources.file import load_urls_from_file
from worai.core.url_sources.sheets import is_spreadsheet_source
from worai.errors import UsageError


@dataclass
class WebPagesClassifyTypesOptions:
    source: str
    output_csv: str
    sheet_name: str | None = None
    service_account: str | None = None
    ingest_source: str | None = None
    ingest_loader: str | None = None
    ingest_passthrough_when_html: bool | None = None
    ingest_timeout_ms: int | None = None
    ingest_retry_attempts: int | None = None
    ingest_retry_backoff_ms: int | None = None
    playwright_wait_until: str | None = None
    url_regex: str | None = None
    agent_cli: str | None = None
    agent_timeout_sec: float = 120.0
    max_markdown_chars: int = 24000


def _infer_source_mode(source: str, sheet_name: str | None) -> str:
    if is_spreadsheet_source(source):
        return "sheets"
    path = Path(source)
    if path.exists():
        suffix = path.suffix.lower()
        if suffix in {".xml", ".gz"}:
            return "sitemap"
        if suffix == ".json":
            return "local"
        return "urls"
    parsed = urlparse(source)
    if parsed.scheme in {"http", "https", "file"}:
        return "sitemap"
    if sheet_name:
        return "sheets"
    raise UsageError(
        "Cannot infer ingest source from SOURCE. Pass --ingest-source explicitly "
        "(urls|sitemap|sheets|local)."
    )


def _normalize_loader(value: str) -> str:
    if value == "auto":
        return DEFAULT_INGEST_LOADER
    return value


def _build_source_bundle(options: WebPagesClassifyTypesOptions) -> dict[str, object]:
    resolved = resolve_ingest_settings(
        context="web_pages_classify_types",
        new_source=options.ingest_source,
        new_loader=options.ingest_loader,
        new_passthrough_when_html=options.ingest_passthrough_when_html,
    )
    source_name = (
        _infer_source_mode(options.source, options.sheet_name)
        if resolved.source == "auto"
        else resolved.source
    )
    loader_name = _normalize_loader(resolved.loader)
    bundle: dict[str, object] = {
        "INGEST_SOURCE": source_name,
        "INGEST_LOADER": loader_name,
        "INGEST_PASSTHROUGH_WHEN_HTML": resolved.passthrough_when_html,
    }
    if options.url_regex:
        bundle["URL_REGEX"] = options.url_regex
    if options.ingest_timeout_ms is not None:
        bundle["INGEST_TIMEOUT_MS"] = options.ingest_timeout_ms
    if options.ingest_retry_attempts is not None:
        bundle["INGEST_RETRY_ATTEMPTS"] = options.ingest_retry_attempts
    if options.ingest_retry_backoff_ms is not None:
        bundle["INGEST_RETRY_BACKOFF_MS"] = options.ingest_retry_backoff_ms
    if options.playwright_wait_until:
        bundle["PLAYWRIGHT_WAIT_UNTIL"] = options.playwright_wait_until

    if source_name == "urls":
        path = Path(options.source)
        if path.exists():
            bundle["URLS"] = load_urls_from_file(path)
        elif urlparse(options.source).scheme in {"http", "https"}:
            bundle["URLS"] = [options.source]
        else:
            raise UsageError(
                "INGEST_SOURCE=urls requires a local URL list file or an explicit page URL."
            )
        return bundle

    if source_name == "sitemap":
        bundle["SITEMAP_URL"] = options.source
        return bundle

    if source_name == "sheets":
        if not options.sheet_name:
            raise UsageError("--sheet-name is required for sheets source.")
        if not options.service_account:
            raise UsageError(
                "SHEETS_SERVICE_ACCOUNT is required for sheets source. "
                "Set --service-account (or profiles.<name>.oauth.service_account)."
            )
        bundle["SHEETS_URL"] = options.source
        bundle["SHEETS_NAME"] = options.sheet_name
        bundle["SHEETS_SERVICE_ACCOUNT"] = options.service_account
        return bundle

    if source_name == "local":
        bundle["INGEST_LOCAL_FILE"] = options.source
        return bundle

    raise UsageError(f"Unsupported ingest source: {source_name}")


def run_classify_types(
    options: WebPagesClassifyTypesOptions,
    *,
    on_progress: Callable[[dict[str, Any]], None] | None = None,
):
    try:
        from wordlift_sdk.ingestion import create_type_classification_csv_from_ingestion
    except Exception as exc:  # pragma: no cover - depends on installed SDK
        raise UsageError(
            "create_type_classification_csv_from_ingestion requires wordlift-sdk>=6.9.0."
        ) from exc

    source_bundle = _build_source_bundle(options)
    return create_type_classification_csv_from_ingestion(
        source_bundle=source_bundle,
        output_csv=options.output_csv,
        agent_cli=options.agent_cli,
        agent_timeout_sec=options.agent_timeout_sec,
        max_markdown_chars=options.max_markdown_chars,
        on_progress=on_progress,
    )
