from __future__ import annotations

import json

from cadis import _cli


def test_lookup_json_passthrough(monkeypatch, capsys):
    payload = {
        "engine": "cadis",
        "version": "0.2.0",
        "execution": {"lookup_status": "ok"},
        "state": {"world": {"status": "ok"}},
        "result": {
            "country": {"name": "Taiwan"},
            "admin_hierarchy": [
                {"name": "臺北市"},
                {"name": "信義區"},
            ],
        },
    }
    monkeypatch.setattr(_cli, "api_lookup", lambda lat, lon: payload)

    code = _cli.main(["lookup", "25.0330", "121.5654", "--json"])
    out = capsys.readouterr().out

    assert code == 0
    assert json.loads(out) == payload


def test_lookup_failed_human(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "failed"},
            "state": {"world": {"classification": "country", "iso2": "TW"}, "dataset": {"status": "missing", "iso2": "TW"}},
        },
    )
    monkeypatch.setattr(_cli, "api_info", lambda: {"supported_iso2": ["JP", "TW"]})
    monkeypatch.setattr("builtins.input", lambda prompt: "n")

    code = _cli.main(["lookup", "25.0330", "121.5654"])
    out = capsys.readouterr().out

    assert code == 1
    assert "Region: Taiwan" in out
    assert "Action:" not in out


def test_lookup_partial_human(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "partial"},
            "result": {"country": {"name": "Taiwan"}, "admin_hierarchy": [{"name": "臺北市"}]},
        },
    )

    code = _cli.main(["lookup", "25.0330", "121.5654"])
    out = capsys.readouterr().out

    assert code == 0
    assert out.strip() == "Region: Taiwan / 臺北市"


def test_lookup_failed_missing_prompts_and_reinstalls(monkeypatch, capsys):
    responses = iter(
        [
            {
                "execution": {"lookup_status": "failed"},
                "state": {"dataset": {"status": "missing", "iso2": "TW"}},
            },
            {
                "execution": {"lookup_status": "ok"},
                "result": {"country": {"name": "Taiwan"}, "admin_hierarchy": [{"name": "臺北市"}]},
            },
        ]
    )
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: next(responses),
    )
    monkeypatch.setattr(_cli, "api_info", lambda: {"supported_iso2": ["JP", "TW"]})
    monkeypatch.setattr(_cli, "api_reinstall", lambda iso2, **kwargs: {"bootstrap_status": "ready"})
    monkeypatch.setattr("builtins.input", lambda prompt: "y")

    code = _cli.main(["lookup", "25.0330", "121.5654"])
    out = capsys.readouterr().out

    assert code == 0
    assert "Region: Taiwan" in out
    assert "Action:" not in out
    assert "Region: Taiwan / 臺北市" in out


def test_lookup_failed_boundary_no_action(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "failed"},
            "state": {"world": {"classification": "open_sea"}},
        },
    )

    code = _cli.main(["lookup", "0", "-160"])
    out = capsys.readouterr().out

    assert code == 1
    assert out.strip() == "Region: Open Sea"


def test_lookup_failed_boundary_uses_world_name(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "failed"},
            "state": {"world": {"classification": "open_sea", "name": "North Pacific Ocean"}},
        },
    )

    code = _cli.main(["lookup", "25.980103337049524", "143.83473058077158"])
    out = capsys.readouterr().out

    assert code == 1
    assert out.strip() == "Region: North Pacific Ocean"


def test_lookup_succeeded_human_summary(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "ok"},
            "result": {
                "country": {"name": "Taiwan"},
                "admin_hierarchy": [{"name": "臺北市"}, {"name": "信義區"}],
            },
        },
    )

    code = _cli.main(["lookup", "25.0330", "121.5654"])
    out = capsys.readouterr().out

    assert code == 0
    assert out.strip() == "Region: Taiwan / 臺北市 / 信義區"


def test_lookup_succeeded_human_summary_offshore(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "ok"},
            "result": {
                "country": {"name": "Italy"},
                "admin_hierarchy": [],
                "source": "offshore",
            },
        },
    )

    code = _cli.main(["lookup", "45.37715878782282", "12.430538889410919"])
    out = capsys.readouterr().out

    assert code == 0
    assert out.strip() == "Region: Italy / Offshore"


def test_lookup_failed_missing_unsupported_country_no_prompt(monkeypatch, capsys):
    monkeypatch.setattr(
        _cli,
        "api_lookup",
        lambda lat, lon: {
            "execution": {"lookup_status": "failed"},
            "state": {
                "world": {"classification": "country", "iso2": "PH"},
                "dataset": {"status": "missing", "iso2": "PH"},
            },
        },
    )
    monkeypatch.setattr(_cli, "api_info", lambda: {"supported_iso2": ["JP", "TW"]})

    code = _cli.main(["lookup", "17.106990241317487", "121.4721253884319"])
    out = capsys.readouterr().out

    assert code == 1
    assert "Region: Philippines" in out
    assert "Administrative dataset for this region is not supported in this version." in out


def test_info_human_hides_schema_version(monkeypatch, capsys):
    payload = {
        "schema_version": "1",
        "version": "0.2.0",
        "supported_iso2": ["JP", "TW"],
        "installed_iso2": ["TW"],
    }
    monkeypatch.setattr(_cli, "api_info", lambda: payload)

    code = _cli.main(["info"])
    out = capsys.readouterr().out

    assert code == 0
    assert "Cadis 0.2.0" in out
    assert "Supported:" in out
    assert "- JP (Japan)" in out
    assert "- TW (Taiwan)" in out
    assert "Installed:" in out


def test_info_json_passthrough(monkeypatch, capsys):
    payload = {
        "schema_version": "1",
        "version": "0.2.0",
        "supported_iso2": ["JP", "TW"],
        "installed_iso2": ["TW"],
    }
    monkeypatch.setattr(_cli, "api_info", lambda: payload)

    code = _cli.main(["info", "--json"])
    out = capsys.readouterr().out

    assert code == 0
    assert json.loads(out) == payload


def test_prepare_downloads_to_explicit_output_dir(monkeypatch, capsys, tmp_path):
    output_dir = tmp_path / "tw-dataset"
    calls: dict[str, object] = {}

    def _bootstrap(**kwargs):
        calls.update(kwargs)
        return {
            "bootstrap_status": "ready",
            "dataset": {
                "country_iso2": "TW",
                "dataset_version": "v1.0.3",
                "dataset_dir": str(output_dir / "TW" / "tw.admin" / "v1.0.3"),
            },
        }

    monkeypatch.setattr(_cli, "api_bootstrap", _bootstrap)

    code = _cli.main(
        [
            "prepare",
            "--iso2",
            "TW",
            "--dataset-version",
            "v1.0.3",
            "--output-dir",
            str(output_dir),
        ]
    )
    out = capsys.readouterr().out

    assert code == 0
    assert calls["iso2"] == "TW"
    assert calls["cache_dir"] == str(output_dir)
    assert calls["dataset_version"] == "v1.0.3"
    assert calls["update_to_latest"] is False
    assert "download_progress" in calls
    assert f"Prepared dataset for TW under cache root {output_dir}" in out
    assert f"Dataset dir: {output_dir / 'TW' / 'tw.admin' / 'v1.0.3'}" in out
    assert "Dataset version: v1.0.3" in out


def test_prepare_uses_latest_when_dataset_version_omitted(monkeypatch, capsys, tmp_path):
    output_dir = tmp_path / "tw-latest"
    calls: dict[str, object] = {}

    def _bootstrap(**kwargs):
        calls.update(kwargs)
        return {
            "bootstrap_status": "ready",
            "dataset": {
                "country_iso2": "TW",
                "dataset_version": "v9.9.9",
                "dataset_dir": str(output_dir / "TW" / "tw.admin" / "v9.9.9"),
            },
        }

    monkeypatch.setattr(_cli, "api_bootstrap", _bootstrap)

    code = _cli.main(
        [
            "prepare",
            "--iso2",
            "TW",
            "--output-dir",
            str(output_dir),
        ]
    )

    assert code == 0
    assert calls["dataset_version"] is None
    assert calls["update_to_latest"] is True


def test_prepare_reports_failure(monkeypatch, capsys, tmp_path):
    output_dir = tmp_path / "tw-dataset"
    monkeypatch.setattr(
        _cli,
        "api_bootstrap",
        lambda **kwargs: {
            "bootstrap_status": "failed",
            "state": {"dataset": {"detail_code": "bad_release"}},
        },
    )

    code = _cli.main(
        [
            "prepare",
            "--iso2",
            "TW",
            "--output-dir",
            str(output_dir),
        ]
    )
    out = capsys.readouterr().out

    assert code == 1
    assert "Prepare failed: bad_release" in out
