import base64
import json

import anthropic

from config import ANTHROPIC_API_KEY, AI_SCAN_MOCK_MODE

NAMEPLATE_JSON_SCHEMA = {
    "type": "object",
    "properties": {
        "gyarto": {
            "type": ["string", "null"],
            "description": "A gyártó cég neve az adattábláról."
        },
        "tipus": {
            "type": ["string", "null"],
            "description": "A konkrét típus/modell megnevezése (pl. 'ECH 15'), NEM az általános géptípus-kategória."
        },
        "gyari_szam": {
            "type": ["string", "null"],
            "description": "A gyártó saját sorozat-/gyári száma (Serial No. / Ser.-No. / Serien-Nr. / S/N)."
        },
        "teherbiras_kg": {
            "type": ["number", "null"],
            "description": "A névleges teherbírás kilogrammban. Ha a táblán tonnában (t) szerepel, szorozd meg 1000-rel."
        },
        "gyartas_datum": {
            "type": ["string", "null"],
            "description": "A gyártás/üzembe helyezés dátuma ISO formátumban (ÉÉÉÉ-HH-NN), KIZÁRÓLAG ha a nap is egyértelműen olvasható."
        },
        "gyartas_datum_nyers_szoveg": {
            "type": ["string", "null"],
            "description": "Ha csak év vagy év+hónap olvasható (a nap nem), írd ide a nyers szöveget változtatás nélkül, és a gyartas_datum legyen null."
        },
        "leltari_szam": {
            "type": ["string", "null"],
            "description": "Egy, a gyártói gyári számtól ELKÜLÖNÜLŐ, az üzemeltető/tulajdonos által felragasztott belső azonosító/leltári címke, HA van ilyen látható a képen."
        },
        "egyeb_megjegyzes": {
            "type": ["string", "null"],
            "description": "Minden egyéb hasznos, a fenti mezőkbe nem illő adat (feszültség, tömeg, emelési magasság, teljesítmény stb.) rövid, egysoros összefoglalóban."
        }
    },
    "required": [
        "gyarto", "tipus", "gyari_szam", "teherbiras_kg",
        "gyartas_datum", "gyartas_datum_nyers_szoveg",
        "leltari_szam", "egyeb_megjegyzes"
    ],
    "additionalProperties": False
}

NAMEPLATE_SYSTEM_PROMPT = """A feladatod egy emelőgép/ipari berendezés GYÁRTÓI ADATTÁBLÁJÁNAK (rating plate/nameplate) elolvasása egy fotóról, és a rajta szereplő adatok strukturált kinyerése.

FONTOS SZABÁLYOK:
1. A gépeken gyakran több matrica/címke is található a gyártói adattábla mellett: hatósági felülvizsgálati matricák, "Nem megfelelő" jelzések, "Next Inspection" évkerekek, belső leltári/eszköz-azonosító címkék. Ezeket NE keverd össze a gyártói adattáblával - kizárólag a gyártó eredeti adattábláját olvasd (jellemzően fém vagy műanyag tábla, rajta a gyártó cégneve, címe, típus és gyári szám).
2. Ha egy belső, az üzemeltető/tulajdonos által felragasztott azonosító címkét (pl. leltári szám, vonalkód) is látsz, ami ELKÜLÖNÜL a gyártó saját gyári számától, azt a leltari_szam mezőbe írd.
3. A teherbírást MINDIG kilogrammban add vissza. Ha a táblán tonnában (t) van feltüntetve, szorozd meg 1000-rel.
4. A gyártási dátumot csak akkor add vissza teljes dátumként (ÉÉÉÉ-HH-NN), ha a nap is egyértelműen olvasható. Ha csak év vagy év+hónap szerepel, azt a gyartas_datum_nyers_szoveg mezőbe írd nyers szövegként, a gyartas_datum-ot hagyd null-on.
5. Ha egy mező nem olvasható egyértelműen, vagy nem szerepel a táblán, add vissza null értékkel - SOHA ne találj ki vagy tippelj adatot.
6. A tábla felirata bármilyen nyelven lehet (magyar, angol, német, koreai, kínai stb.) - a mezők jelentését a táblán szereplő szó pozíciója/kontextusa alapján azonosítsd (pl. "Serial No.", "Ser.-No.", "Serien-Nr." mind gyári szám)."""


class AiElemzesHiba(Exception):
    """Az AI adattábla-elemzés során fellépő, felhasználónak megjeleníthető hiba."""
    pass


def elemzi_adattabla_kepet(kep_bytes: bytes, media_type: str) -> dict:
    """Elküld egy adattábla-fotót a Claude vision API-nak, és visszaadja a felismert mezőket dict-ként.
    Minden mező null, ha az AI nem volt biztos benne - soha nem tippel."""
    if AI_SCAN_MOCK_MODE:
        return {
            "gyarto": "MOCK Gyártó Kft.",
            "tipus": "MOCK-TESZT-1000",
            "gyari_szam": "MOCK-000000",
            "teherbiras_kg": 1000,
            "gyartas_datum": None,
            "gyartas_datum_nyers_szoveg": "2024 (mock adat)",
            "leltari_szam": None,
            "egyeb_megjegyzes": "Ez egy fejlesztői tesztválasz (AI_SCAN_MOCK_MODE=true) - nem valódi AI-elemzés, nem hívta az API-t."
        }

    if not ANTHROPIC_API_KEY:
        raise AiElemzesHiba("Az AI szkennelés nincs beállítva a szerveren (hiányzó API kulcs).")

    client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
    kep_base64 = base64.standard_b64encode(kep_bytes).decode("utf-8")

    try:
        response = client.messages.create(
            model="claude-opus-4-8",
            max_tokens=1024,
            system=NAMEPLATE_SYSTEM_PROMPT,
            messages=[{
                "role": "user",
                "content": [
                    {
                        "type": "image",
                        "source": {
                            "type": "base64",
                            "media_type": media_type,
                            "data": kep_base64
                        }
                    },
                    {"type": "text", "text": "Olvasd le ennek a gépnek a gyártói adattábláját, és add vissza a kért mezőket."}
                ]
            }],
            output_config={
                "format": {
                    "type": "json_schema",
                    "schema": NAMEPLATE_JSON_SCHEMA
                }
            }
        )
    except anthropic.APIStatusError as e:
        # A nyers API-hibaüzenet (e.message) csak a szerver konzol-naplójában landol - a
        # kliensnek a hibakodok.py mintáját követve egy generikus üzenet megy vissza
        # (l. routers/ai_scan.py, E-AI-01).
        print(f"❌ Hiba az AI szkennelés Anthropic API hívásakor: {e.status_code} {e.message}")
        raise AiElemzesHiba("Hiba történt az AI szolgáltatás hívása közben!")
    except anthropic.APIConnectionError:
        raise AiElemzesHiba("Hálózati hiba az AI szolgáltatás elérésekor - ellenőrizd a szerver internetkapcsolatát.")

    if response.stop_reason == "refusal":
        raise AiElemzesHiba("Az AI biztonsági okból nem tudta feldolgozni ezt a képet.")

    szoveg = next((b.text for b in response.content if b.type == "text"), None)
    if not szoveg:
        raise AiElemzesHiba("Az AI nem adott vissza értelmezhető választ.")

    try:
        return json.loads(szoveg)
    except json.JSONDecodeError:
        raise AiElemzesHiba("Az AI válasza nem volt érvényes JSON formátumú.")
