"""Tests for utility functions: fallgruppe mapping, KW/date utils, validators."""

from datetime import date

import pytest

from app.utils.fallgruppe_map import map_modul_to_fallgruppe
from app.utils.kw_utils import date_to_jahr, date_to_kw, parse_german_date
from app.utils.validators import (
    normalize_icd_hauptgruppe,
    split_icd_codes,
    validate_icd,
    validate_kvnr,
)


# ── Fallgruppe mapping ─────────────────────────────────────────────


class TestFallgruppeMapping:
    def test_map_exact_matches(self):
        assert map_modul_to_fallgruppe("Zweitmeinung Onkologie") == "onko"
        assert map_modul_to_fallgruppe("Zweitmeinung Kardiologie") == "kardio"
        assert map_modul_to_fallgruppe("Zweitmeinung Intensiv") == "intensiv"
        assert map_modul_to_fallgruppe("Zweitmeinung Gallenblase") == "galle"
        assert map_modul_to_fallgruppe("Zweitmeinung Schilddrüse") == "sd"

    def test_map_with_whitespace(self):
        assert map_modul_to_fallgruppe(" Zweitmeinung Onkologie ") == "onko"

    def test_map_begutachtung_onko(self):
        assert map_modul_to_fallgruppe("Begutachtung Onkologie") == "onko"

    def test_map_begutachtung_herz(self):
        assert map_modul_to_fallgruppe("Begutachtung Herz") == "kardio"

    def test_map_unknown_raises(self):
        with pytest.raises(ValueError, match="Cannot map module"):
            map_modul_to_fallgruppe("Unknown Module")


# ── KW / Date utils ────────────────────────────────────────────────


class TestKWUtils:
    def test_date_to_kw(self):
        # 2026-02-24 is a Tuesday in KW 9
        assert date_to_kw(date(2026, 2, 24)) == 9

    def test_date_to_jahr_boundary(self):
        # 2025-12-31 is a Wednesday — ISO week 1 of 2026
        assert date_to_kw(date(2025, 12, 31)) == 1
        assert date_to_jahr(date(2025, 12, 31)) == 2026


class TestParseGermanDate:
    def test_parse_german_date_ddmmyy(self):
        assert parse_german_date("02.02.26") == date(2026, 2, 2)

    def test_parse_german_date_ddmmyyyy(self):
        assert parse_german_date("28.04.1960") == date(1960, 4, 28)

    def test_parse_german_date_with_time(self):
        assert parse_german_date("02.02.26, 08:50") == date(2026, 2, 2)

    def test_parse_german_date_bad_year(self):
        with pytest.raises(ValueError, match="Year out of range"):
            parse_german_date("29.08.0196")

    def test_parse_german_date_empty(self):
        with pytest.raises(ValueError, match="Empty date string"):
            parse_german_date("")


# ── Validators ──────────────────────────────────────────────────────


class TestValidateICD:
    def test_validate_icd_valid(self):
        assert validate_icd("C50.1") == "C50.1"
        assert validate_icd("c50") == "C50"

    def test_validate_icd_invalid(self):
        with pytest.raises(ValueError, match="Invalid ICD code format"):
            validate_icd("XYZ")
        with pytest.raises(ValueError, match="Empty ICD code"):
            validate_icd("")


class TestSplitICDCodes:
    def test_split_icd_codes_comma(self):
        assert split_icd_codes("C50.1, C79.5") == ["C50.1", "C79.5"]

    def test_split_icd_codes_semicolon(self):
        assert split_icd_codes("C50.1;C79.5") == ["C50.1", "C79.5"]

    def test_split_icd_codes_empty(self):
        assert split_icd_codes("") == []


class TestNormalizeHauptgruppe:
    def test_normalize_hauptgruppe(self):
        assert normalize_icd_hauptgruppe("C50.1") == "C50"


class TestValidateKVNR:
    def test_validate_kvnr_valid(self):
        assert validate_kvnr("D410126355") == "D410126355"

    def test_validate_kvnr_invalid(self):
        with pytest.raises(ValueError, match="Invalid KVNR format"):
            validate_kvnr("123456789")
