"""Seed reference data: TechnologyClasses I–IV, Requirements, CertificationLevels.

Run from project root (after init_db): `python migrations/seed_data.py`
Idempotent: clears and re-inserts the three reference tables.
Thresholds transcribed from §С.6; certification boundaries per §С.4.6 2D logic.
"""

from __future__ import annotations

import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from sqlmodel import Session, create_engine, delete, select  # noqa: E402

from models import (  # noqa: E402
    CertificationLevels,
    Companies,
    Requirements,
    TechnologyClasses,
)

DB_PATH = PROJECT_ROOT / "fmcg.db"

# Класи технологій ШТУ (§С.4.2–4.5)
CLASSES: list[tuple[str, str, str]] = [
    ("I", "IoT-моніторинг та холодний ланцюг",
     "Температурний контроль, RFID/NFC-ідентифікація, цифровий журнал температур."),
    ("II", "ШІ-управління запасами та прогнозування",
     "ML-прогнозування попиту, валідація моделей, резервні процедури."),
    ("III", "Трасування і блокчейн",
     "GS1 EPCIS, незмінні реєстри, смарт-контракти, відкликання продукції."),
    ("IV", "Автономні системи і роботизація",
     "AMR, роботизоване комплектування, функціональна безпека, енергоефективність."),
]

# (code, class_code, threshold, operator, mandatory, criticality, deadline_days, recommendation)
# criticality >= 3 ⇒ критична невідповідність (темп. журнал Класу I / безпека Класу IV, §С.5.4)
REQUIREMENTS: list[tuple[str, str, str, str, bool, int, int, str]] = [
    # --- Клас I (§С.6.1) ---
    ("I.1", "I", "5", "<=", True, 3, 30, "Зчитування температурних сенсорів не рідше 1 разу на 5 хв."),
    ("I.2", "I", "0.5", "<=", True, 3, 30, "Допустиме відхилення сенсора не більше ±0,5°C."),
    ("I.3", "I", "95", ">=", True, 2, 90, "Покриття RFID/NFC не менше 95% товарних одиниць."),
    ("I.4", "I", "10", "<=", True, 3, 30, "Автоматичне оповіщення про порушення режиму не більше 10 хв."),
    ("I.5", "I", "2", ">=", True, 2, 90, "Не менше 2 незалежних каналів передачі даних із резервуванням."),
    ("I.6", "I", "36", ">=", True, 3, 30, "Зберігання незмінного журналу температур не менше 36 місяців."),
    ("I.7", "I", "yes", "yes-no", False, 1, 90, "Звітність про температурний профіль партії (піддон/коробка)."),
    # --- Клас II (§С.6.2) ---
    ("II.1", "II", "18", ">=", True, 2, 90, "Навчальна вибірка ML-моделі не менше 18 місяців даних."),
    ("II.2", "II", "85", ">=", True, 2, 90, "Точність прогнозу попиту (4 тижні) не менше 85%."),
    ("II.3", "II", "8", "<=", True, 2, 90, "MAE моделі не більше 8% від середньомісячного обороту."),
    ("II.4", "II", "yes", "yes-no", False, 1, 90, "Перевалідація моделей не рідше 1 разу на місяць."),
    ("II.5", "II", "yes", "yes-no", False, 1, 90, "Щоквартальний аудит пояснюваності рішень ШІ."),
    ("II.6", "II", "2", "<=", True, 2, 90, "Час перемикання на резервну процедуру не більше 2 год."),
    ("II.7", "II", "yes", "yes-no", True, 2, 90, "Обробка персональних даних згідно №2297-VI та GDPR."),
    # --- Клас III (§С.6.3) ---
    ("III.1", "III", "yes", "yes-no", True, 2, 90, "Ідентифікація подій за стандартом GS1 EPCIS 2.0."),
    ("III.2", "III", "3", ">=", True, 2, 90, "Глибина трасування не менше 3 ланок ланцюга."),
    ("III.3", "III", "yes", "yes-no", True, 2, 90, "Криптографічний хеш кожного запису реєстру."),
    ("III.4", "III", "99.9", ">=", True, 2, 90, "Доступність реєстру не менше 99,9% часу на рік."),
    ("III.5", "III", "yes", "yes-no", False, 1, 90, "Незалежний аудит смарт-контрактів не рідше 1 разу на рік."),
    ("III.6", "III", "1", "<=", True, 2, 90, "Час блокування партій при відкликанні не більше 1 год."),
    ("III.7", "III", "yes", "yes-no", False, 1, 90, "Захист комерційної таємниці через блокчейн-дозвіл."),
    # --- Клас IV (§С.6.4) ---
    ("IV.1", "IV", "99.5", ">=", True, 2, 90, "Точність роботизованого комплектування не менше 99,5%."),
    ("IV.2", "IV", "2000", ">=", True, 2, 90, "MTBF роботизованого модуля не менше 2000 годин."),
    ("IV.3", "IV", "yes", "yes-no", True, 3, 30, "Відповідність ISO 10218-1/2 та ISO 13849-1 (PL d)."),
    ("IV.4", "IV", "30", "<=", True, 3, 30, "Час відновлення після відмови не більше 30 хв."),
    ("IV.5", "IV", "80", ">=", False, 1, 90, "Частка відкритих стандартів в архітектурі від 80%."),
    ("IV.6", "IV", "500", ">=", True, 2, 90, "Функціональне тестування не менше 500 операційних циклів."),
    ("IV.7", "IV", "0.5", "<=", False, 1, 90, "Питомі витрати енергії не більше 0,5 кВт·год на 100 операцій."),
]

COMPANIES: list[tuple[str, str]] = [
    ("ТОВ «Логістика Плюс»", "12345678"),
    ("АТ «Агрохолдинг Україна»", "87654321"),
]

# Межі рівнів сертифікації (§С.4.6) — двовимірна логіка.
# (level, name, class_min_index, overall_min_index, class_scope, critical_threshold)
LEVELS: list[tuple[int, str, float, float, str, int]] = [
    (1, "Рівень 1 — початковий рівень ШТУ", 0.75, 0.70, "I,II", 3),
    (2, "Рівень 2 — середній рівень ШТУ", 0.80, 0.82, "ALL", 3),
    (3, "Рівень 3 — високий рівень ШТУ", 0.95, 0.95, "ALL", 3),
]


def seed() -> None:
    engine = create_engine(f"sqlite:///{DB_PATH}")
    with Session(engine) as s:
        # Idempotent reset of reference tables (not Companies — preserve user data).
        s.exec(delete(Requirements))
        s.exec(delete(CertificationLevels))
        s.exec(delete(TechnologyClasses))
        s.commit()

        # Seed demo companies only when none exist.
        existing = s.exec(select(Companies)).first()
        if existing is None:
            for cname, edrpou in COMPANIES:
                s.add(Companies(name=cname, edrpou=edrpou))
            s.commit()

        for code, name, desc in CLASSES:
            s.add(TechnologyClasses(code=code, name=name, description=desc))
        s.commit()

        class_id = {
            c.code: c.id for c in s.exec(select(TechnologyClasses)).all()
        }
        for code, ccode, threshold, op, mand, crit, dl, rec in REQUIREMENTS:
            s.add(Requirements(
                code=code, class_id=class_id[ccode], threshold=threshold,
                operator=op, mandatory=mand, criticality=crit,
                deadline_days=dl, recommendation=rec,
            ))
        for level, lname, class_min, overall_min, scope, crit_thr in LEVELS:
            s.add(CertificationLevels(
                level=level, name=lname, class_min_index=class_min,
                overall_min_index=overall_min, class_scope=scope,
                critical_threshold=crit_thr,
            ))
        s.commit()

        n_req = len(s.exec(select(Requirements)).all())
        n_comp = len(s.exec(select(Companies)).all())
        print(f"Seeded: {len(CLASSES)} classes, {n_req} requirements, {len(LEVELS)} levels, {n_comp} companies")


if __name__ == "__main__":
    seed()
