import os
import time
from pathlib import Path

import pytest

from comuniitaliani import Comuni
from comuniitaliani import loader
from comuniitaliani.exceptions import ComuneNotFoundError


@pytest.fixture()
def sample_csv(tmp_path: Path) -> Path:
    fixture = Path(__file__).parent / "fixtures" / "comuni_sample.csv"
    target = tmp_path / "comuni.csv"
    target.write_bytes(fixture.read_bytes())
    return target


def test_cerca_comune_is_case_and_accent_insensitive(sample_csv: Path) -> None:
    comuni = Comuni(csv_file=str(sample_csv), allow_download=False)

    result = comuni.cerca_comune("AGLIE")

    assert result["nome"] == "Agliè"
    assert result["sigla_provincia"] == "TO"
    assert result["regione"] == "Piemonte"


def test_comuni_per_provincia_returns_sorted_list(sample_csv: Path) -> None:
    comuni = Comuni(csv_file=str(sample_csv), allow_download=False)

    torino = comuni.comuni_per_provincia("to")
    lazio = comuni.comuni_per_provincia("RM")

    assert [item["nome"] for item in torino] == ["Agliè"]
    assert [item["nome"] for item in lazio] == ["Roma"]


def test_cerca_per_codice_catastale_not_found(sample_csv: Path) -> None:
    comuni = Comuni(csv_file=str(sample_csv), allow_download=False)

    with pytest.raises(ComuneNotFoundError):
        comuni.cerca_per_codice_catastale("ZZZZ")


def test_offline_mode_does_not_hit_network(monkeypatch: pytest.MonkeyPatch, sample_csv: Path) -> None:
    def _fail(*args, **kwargs):
        raise AssertionError("Non dovrebbe essere effettuata alcuna richiesta HTTP in modalità offline.")

    monkeypatch.setattr(loader.requests, "head", _fail)
    monkeypatch.setattr(loader.requests, "get", _fail)

    comuni = Comuni(csv_file=str(sample_csv), allow_download=False)
    assert comuni.cerca_comune("Agliè")["nome"] == "Agliè"


def test_download_triggers_when_remote_newer(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    local_csv = tmp_path / "comuni.csv"
    # Vecchio contenuto
    local_csv.write_text(
        "denominazione_in_italiano;sigla_automobilistica;denominazione_regione;denominazione_dell'unità_territoriale_sovracomunale_(valida_a_fini_statistici);codice_catastale_del_comune\n"
        "Vecchio;VC;Piemonte;Vercelli;Z999\n",
        encoding="latin1",
    )
    # Imposta una mtime vecchia
    old_time = time.time() - 10_000
    os.utime(local_csv, (old_time, old_time))

    new_csv_body = (
        "denominazione_in_italiano;sigla_automobilistica;denominazione_regione;denominazione_dell'unità_territoriale_sovracomunale_(valida_a_fini_statistici);codice_catastale_del_comune\n"
        "Nuovo;RM;Lazio;Roma;H501\n"
    ).encode("latin1")

    class _FakeHeadResponse:
        headers = {"Last-Modified": "Wed, 01 Jan 2099 00:00:00 GMT"}

        @staticmethod
        def raise_for_status():
            return None

    class _FakeGetResponse:
        def __init__(self, payload: bytes):
            self.payload = payload

        @staticmethod
        def raise_for_status():
            return None

        def iter_content(self, chunk_size: int):
            yield self.payload

    monkeypatch.setattr(loader.requests, "head", lambda *_, **__: _FakeHeadResponse())
    monkeypatch.setattr(loader.requests, "get", lambda *_, **__: _FakeGetResponse(new_csv_body))

    comuni = Comuni(csv_file=str(local_csv), allow_download=True)
    assert comuni.cerca_comune("Nuovo")["sigla_provincia"] == "RM"
