from __future__ import annotations

from pathlib import Path

import click
import pytest
from typer.testing import CliRunner

from worai.commands import (
    canonicalize_duplicate_pages as canonicalize_cmd,
    dedupe as dedupe_cmd,
    delete_entities_from_csv as delete_cmd,
    dil_import as dil_import_cmd,
    find_missing_names as find_missing_cmd,
    find_url_by_type as find_url_cmd,
    list_entities_outside_dataset as list_outside_cmd,
    patch as patch_cmd,
    seocheck as seocheck_cmd,
)
from worai.errors import UsageError


def test_seocheck_builds_argv_and_exits(monkeypatch: pytest.MonkeyPatch) -> None:
    seen: dict[str, object] = {}

    def _stub(argv: list[str]) -> int:
        seen["argv"] = argv
        return 7

    monkeypatch.setattr(seocheck_cmd.seocheck_cli, "run", _stub)
    with pytest.raises(click.exceptions.Exit) as exc:
        seocheck_cmd.run(
            sitemap_url="https://example.com/sitemap.xml",
            max_urls=2,
            output="out.json",
            output_summary="sum.json",
            save_html=True,
            no_report_ui=True,
            checks="status,canonical",
            disable_checks="ttfb",
            recheck_failed=True,
            recheck_from="report.json",
        )
    assert exc.value.exit_code == 7
    argv = seen["argv"]
    assert isinstance(argv, list)
    assert "--max-urls" in argv
    assert "--save-html" in argv
    assert "--recheck-failed" in argv


def test_find_missing_names_success_and_empty(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(find_missing_cmd, "find_run", lambda _p: ["https://example.com/a"])
    result = CliRunner().invoke(find_missing_cmd.app, ["data.ttl"])
    assert result.exit_code == 0
    assert "Found URLs for 1" in result.output

    monkeypatch.setattr(find_missing_cmd, "find_run", lambda _p: [])
    result = CliRunner().invoke(find_missing_cmd.app, ["data.ttl"])
    assert result.exit_code == 0
    assert "No schema:CollectionPage entities" in result.output


def test_find_missing_names_error_paths(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(find_missing_cmd, "find_run", lambda _p: (_ for _ in ()).throw(FileNotFoundError()))
    result = CliRunner().invoke(find_missing_cmd.app, ["missing.ttl"])
    assert result.exit_code == 1
    assert "was not found" in result.output

    monkeypatch.setattr(find_missing_cmd, "find_run", lambda _p: (_ for _ in ()).throw(RuntimeError("boom")))
    result = CliRunner().invoke(find_missing_cmd.app, ["bad.ttl"])
    assert result.exit_code == 1
    assert "An error occurred while parsing the file" in result.output


def test_find_url_by_type_paths(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(find_url_cmd, "resolve_types", lambda _types: [])
    result = CliRunner().invoke(find_url_cmd.app, ["x.ttl", "schema:Thing"])
    assert result.exit_code == 1
    assert "No valid schema types" in result.output

    monkeypatch.setattr(find_url_cmd, "resolve_types", lambda _types: ["Thing"])
    monkeypatch.setattr(find_url_cmd, "find_urls", lambda _opts: [("s1", "u1")])
    result = CliRunner().invoke(find_url_cmd.app, ["x.ttl", "schema:Thing"])
    assert result.exit_code == 0
    assert "u1" in result.output

    result = CliRunner().invoke(find_url_cmd.app, ["--show-id", "x.ttl", "schema:Thing"])
    assert result.exit_code == 0
    assert "s1" in result.output


def test_find_url_by_type_error_paths(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setattr(find_url_cmd, "resolve_types", lambda _types: ["Thing"])
    monkeypatch.setattr(find_url_cmd, "find_urls", lambda _opts: (_ for _ in ()).throw(FileNotFoundError()))
    result = CliRunner().invoke(find_url_cmd.app, ["missing.ttl", "schema:Thing"])
    assert result.exit_code == 1
    assert "File not found" in result.output

    monkeypatch.setattr(find_url_cmd, "find_urls", lambda _opts: (_ for _ in ()).throw(RuntimeError("boom")))
    result = CliRunner().invoke(find_url_cmd.app, ["bad.ttl", "schema:Thing"])
    assert result.exit_code == 1
    assert "Error parsing graph file" in result.output


def test_dil_import_verify_csv_and_run(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    csv_path = tmp_path / "dils.csv"
    csv_path.write_text("source_url,target_url,target_anchor_text,target_position\ns,t,a,1\n", encoding="utf-8")
    seen: dict[str, object] = {}
    monkeypatch.setattr(dil_import_cmd, "import_run", lambda options: seen.setdefault("options", options))
    result = CliRunner().invoke(dil_import_cmd.app, ["wl_1", str(csv_path)])
    assert result.exit_code == 0
    assert seen["options"].api_key == "wl_1"


def test_dil_import_verify_csv_errors(tmp_path: Path) -> None:
    with pytest.raises(Exception):
        dil_import_cmd.verify_csv(str(tmp_path / "missing.csv"))

    txt_path = tmp_path / "x.txt"
    txt_path.write_text("x", encoding="utf-8")
    with pytest.raises(Exception):
        dil_import_cmd.verify_csv(str(txt_path))


def test_sdk_key_wrappers_use_profile_loader(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    csv_path = tmp_path / "in.csv"
    csv_path.write_text("iri\nx\n", encoding="utf-8")

    monkeypatch.setattr(canonicalize_cmd, "resolve_profile_api_key", lambda _ctx: ("wl", "default", Path("w.toml")))
    monkeypatch.setattr(dedupe_cmd, "resolve_profile_api_key", lambda _ctx: ("wl", "default", Path("w.toml")))
    monkeypatch.setattr(delete_cmd, "resolve_profile_api_key", lambda _ctx: ("wl", "default", Path("w.toml")))
    monkeypatch.setattr(list_outside_cmd, "resolve_profile_api_key", lambda _ctx: ("wl", "default", Path("w.toml")))
    monkeypatch.setattr(patch_cmd, "resolve_profile_api_key", lambda _ctx: ("wl", "default", Path("w.toml")))

    monkeypatch.setattr(canonicalize_cmd, "canonicalize_run", lambda _opts: None)
    monkeypatch.setattr(dedupe_cmd, "dedupe_run", lambda _opts: None)
    monkeypatch.setattr(delete_cmd, "delete_entities", lambda _opts: None)
    monkeypatch.setattr(list_outside_cmd, "run", lambda _opts: None)
    monkeypatch.setattr(patch_cmd, "patch_run", lambda _opts: None)

    canonicalize_cmd.run(None, "in.csv", "out.csv", None, None, "e", 10, "28d", "clicks")
    dedupe_cmd.run(None, "e", False, 0.0, True)
    delete_cmd.run(None, str(csv_path), 10)
    list_outside_cmd.main(None, None, "e", "b", 0, "q")
    patch_cmd.run(None, "f.ttl", False, False, False, None, 1, 1)


def test_sdk_key_wrappers_raise_without_key(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    monkeypatch.setattr(canonicalize_cmd, "resolve_profile_api_key", lambda _ctx: (None, "default", Path("w.toml")))
    with pytest.raises(UsageError):
        canonicalize_cmd.run(None, "in.csv", "out.csv", None, None, "e", 10, "28d", "clicks")
