import io
from pathlib import Path

from fpdf import FPDF
from fpdf.enums import XPos, YPos
from PIL import Image, ImageDraw, ImageFont

STATIC_DIR = Path(__file__).resolve().parent / "static"

SULYOSSAG_SZIN = {"ENYHE": (13, 202, 240), "KOZEPES": (255, 193, 7), "SULYOS": (220, 53, 69)}
SULYOSSAG_CIMKE = {"ENYHE": "Enyhe", "KOZEPES": "Közepes", "SULYOS": "Súlyos"}

SZAKTERULET_MEZOK = [
    ("szakterulet_iparbiztonsagi", "Iparbiztonsági"),
    ("szakterulet_tuzvedelmi", "Tűzvédelmi"),
    ("szakterulet_munkavedelmi", "Munkavédelmi"),
    ("szakterulet_kornyezetvedelmi", "Környezetvédelmi"),
]


def _szakteruletek_szovege(sz) -> str:
    cimkek = [cimke for mezo, cimke in SZAKTERULET_MEZOK if getattr(sz, mezo, False)]
    return ", ".join(cimkek) if cimkek else "-"


SZAKTERULET_ROVIDITESEK = {
    "szakterulet_iparbiztonsagi": "IB", "szakterulet_tuzvedelmi": "TV",
    "szakterulet_munkavedelmi": "MV", "szakterulet_kornyezetvedelmi": "KV",
}


def _szakteruletek_roviden(sz) -> str:
    rovidek = [rov for mezo, rov in SZAKTERULET_ROVIDITESEK.items() if getattr(sz, mezo, False)]
    return ", ".join(rovidek) if rovidek else "-"


def _betutipus(meret: int, felkover: bool = False):
    try:
        fajl = "DejaVuSans-Bold.ttf" if felkover else "DejaVuSans.ttf"
        return ImageFont.truetype(str(STATIC_DIR / fajl), meret)
    except Exception:
        return ImageFont.load_default()


def oszlopdiagram_kep(cim: str, adatok: list, szin=(220, 53, 69), szelesseg: int = 380, magassag: int = 220) -> bytes:
    """Egyszerű, PIL-lel rajzolt vízszintes oszlopdiagram PNG-ként - a fpdf2 nem tud
    natívan diagramot rajzolni, a projekt pedig szándékosan nem használ matplotlib-et."""
    img = Image.new("RGB", (szelesseg, magassag), "white")
    draw = ImageDraw.Draw(img)
    font_cim = _betutipus(15, felkover=True)
    font = _betutipus(12)

    draw.text((6, 6), cim, fill="black", font=font_cim)
    draw.rectangle([0, 0, szelesseg - 1, magassag - 1], outline=(200, 200, 200))

    if not adatok:
        draw.text((10, 45), "Nincs adat erre a napra", fill=(120, 120, 120), font=font)
        return _png_bytes(img)

    label_szelesseg = 150
    jobb_margo = 45
    grafikon_szelesseg = szelesseg - label_szelesseg - jobb_margo
    max_ertek = max(ertek for _, ertek in adatok) or 1
    sor_magassag = max(18, min(30, (magassag - 40) // len(adatok)))
    y = 36

    for label, ertek in adatok:
        cimke = (label[:20] + "…") if len(label) > 21 else label
        draw.text((6, y + (sor_magassag - 14) // 2), cimke, fill="black", font=font)
        bar_hossz = int((ertek / max_ertek) * grafikon_szelesseg) if max_ertek else 0
        bar_hossz = max(bar_hossz, 2) if ertek > 0 else 0
        draw.rectangle(
            [label_szelesseg, y + 3, label_szelesseg + bar_hossz, y + sor_magassag - 5],
            fill=szin,
        )
        draw.text((label_szelesseg + bar_hossz + 6, y + (sor_magassag - 14) // 2), str(ertek), fill="black", font=font)
        y += sor_magassag
        if y > magassag - 10:
            break

    return _png_bytes(img)


def _png_bytes(img: Image.Image) -> bytes:
    buf = io.BytesIO()
    img.save(buf, format="PNG")
    return buf.getvalue()


def _kep_meret_dobozba(fajl, max_szelesseg: float, max_magassag: float) -> tuple[float, float]:
    """Kiszámolja egy kép arány-megtartó, pontos (nem "laza") méretét egy adott dobozba.
    SZÁNDÉKOSAN nem az fpdf2 image()-jének saját keep_aspect_ratio=True paraméterét
    használjuk erre - lásd ebk_pdf_utils.py azonos nevű függvényét a bug részletes leírásáért."""
    with Image.open(fajl) as im:
        img_w, img_h = im.size
    arany = img_w / img_h
    if max_magassag * arany <= max_szelesseg:
        return max_magassag * arany, max_magassag
    return max_szelesseg, max_szelesseg / arany


class VivuNapiOsszefoglaloPDF(FPDF):
    """A VIVÜ ügyintéző időszaki (napi) összefoglalója egy adott Megrendelő egy adott napjáról -
    az első oldalon 3 diagram (ellenőrzött telephelyek, szabálytalanságok tételenként,
    szabálytalanságok súlya), utána a részletes táblázatok."""

    def __init__(self, ugyfel, datum):
        super().__init__(orientation="P", format="A4")
        self.ugyfel = ugyfel
        self.datum = datum
        self.add_font("DejaVu", "", str(STATIC_DIR / "DejaVuSans.ttf"))
        self.add_font("DejaVu", "B", str(STATIC_DIR / "DejaVuSans-Bold.ttf"))

    def header(self):
        self.set_font("DejaVu", "B", 15)
        self.cell(0, 9, "Veszélyes ipari védelmi ügyintézői összefoglaló", ln=True, align="C")
        self.set_font("DejaVu", "", 10)
        self.cell(0, 6, f"{self.ugyfel.nev} - {self.datum.strftime('%Y-%m-%d')}", ln=True, align="C")
        if self.ugyfel.cim:
            self.cell(0, 5, self.ugyfel.cim, ln=True, align="C")
        self.ln(2)

    def footer(self):
        self.set_y(-15)
        self.set_font("DejaVu", "", 8)
        self.cell(0, 10, "EmeLOG Nyilvántartó rendszerrel készült", align="L")
        self.set_x(-30)
        self.cell(0, 10, f"Oldal {self.page_no()}/{{nb}}", align="R")

    def diagramok_hozzaadasa(self, telephely_adatok, tetel_adatok, sulyossag_adatok):
        kep_szelesseg = 90
        x_bal, x_jobb = 10, 108
        y_felso = self.get_y()

        self.image(io.BytesIO(oszlopdiagram_kep("Ellenőrzött telephelyek", telephely_adatok, (13, 110, 253))), x=x_bal, y=y_felso, w=kep_szelesseg)
        self.image(io.BytesIO(oszlopdiagram_kep("Szabálytalanságok tételenként", tetel_adatok, (220, 53, 69))), x=x_jobb, y=y_felso, w=kep_szelesseg)
        y_also = y_felso + 62
        self.image(io.BytesIO(oszlopdiagram_kep("Szabálytalanságok súlya", sulyossag_adatok, (108, 117, 125))), x=x_bal, y=y_also, w=kep_szelesseg)
        self.set_y(y_also + 62)

    def tablazat_fejlec(self, cim: str):
        self.ln(4)
        self.set_font("DejaVu", "B", 12)
        self.cell(0, 8, cim, ln=True)

    def ellenorzesek_tablazata(self, ellenorzesek):
        oszlopok = [35, 40, 25, 30, 25, 25]
        fejlecek = ["Helyszín", "Érintett épület(ek)", "Típus", "Ellenőrizte", "Rendben", "Szabálytalanság"]
        self.set_font("DejaVu", "B", 8)
        self.set_fill_color(220, 220, 220)
        for szel, cim in zip(oszlopok, fejlecek):
            self.cell(szel, 7, cim, border=1, fill=True, align="C")
        self.ln()
        self.set_font("DejaVu", "", 8)
        for e in ellenorzesek:
            szab_szam = len([t for t in e.tetel_eredmenyek if t.statusz == "SZABALYTALANSAG"])
            rendben_szam = len([t for t in e.tetel_eredmenyek if t.statusz == "RENDBEN"])
            erintett_epuletek = ", ".join(ep.nev for ep in e.epuletek) or "-"
            tipus_cimke = "Dokumentáció" if e.tipus == "DOKUMENTACIO" else "Bejárás"
            self.cell(oszlopok[0], 7, (e.telephely.nev if e.telephely else "-")[:20], border=1)
            self.cell(oszlopok[1], 7, erintett_epuletek[:23], border=1)
            self.cell(oszlopok[2], 7, tipus_cimke, border=1, align="C")
            self.cell(oszlopok[3], 7, (e.ellenorzo.username if e.ellenorzo else "-")[:16], border=1, align="C")
            self.cell(oszlopok[4], 7, str(rendben_szam), border=1, align="C")
            self.cell(oszlopok[5], 7, str(szab_szam), border=1, align="C")
            self.ln()

    def szabalytalansagok_tablazata(self, szabalytalansagok):
        oszlopok = [45, 22, 15, 33, 75]
        fejlecek = ["Tétel", "Szint", "Súly.", "Szakterület", "Leírás"]
        self.set_font("DejaVu", "B", 8)
        self.set_fill_color(220, 220, 220)
        for szel, cim in zip(oszlopok, fejlecek):
            self.cell(szel, 7, cim, border=1, fill=True, align="C")
        self.ln()
        self.set_font("DejaVu", "", 8)
        x_start = self.get_x()
        for sz in szabalytalansagok:
            y_start = self.get_y()
            self.set_xy(x_start, y_start)
            self.cell(oszlopok[0], 7, (sz.tetel.szoveg if sz.tetel else "-")[:28], border=1)
            self.cell(oszlopok[1], 7, (sz.szint.nev if sz.szint else "-")[:13], border=1)
            self.cell(oszlopok[2], 7, SULYOSSAG_CIMKE.get(sz.sulyossag, "-"), border=1, align="C")
            self.cell(oszlopok[3], 7, _szakteruletek_roviden(sz), border=1, align="C")
            self.set_xy(x_start + sum(oszlopok[:4]), y_start)
            self.multi_cell(oszlopok[4], 7, (sz.leiras or "-")[:200], border=1, new_x=XPos.LMARGIN, new_y=YPos.NEXT)
            self.set_y(max(self.get_y(), y_start + 7))


class VivuEllenorzesPDF(FPDF):
    """Egy konkrét bejárás vagy dokumentáció-felülvizsgálat teljes, nyomtatható jegyzőkönyve -
    a szabálytalanságoknál a hozzájuk (akár utólag) csatolt összes fényképpel, rácsos
    galéria-elrendezésben."""

    def __init__(self, ellenorzes):
        super().__init__(orientation="P", format="A4")
        self.ellenorzes = ellenorzes
        self.add_font("DejaVu", "", str(STATIC_DIR / "DejaVuSans.ttf"))
        self.add_font("DejaVu", "B", str(STATIC_DIR / "DejaVuSans-Bold.ttf"))
        self.set_auto_page_break(auto=True, margin=18)

    def header(self):
        e = self.ellenorzes
        cim = "Dokumentáció-felülvizsgálat" if e.tipus == "DOKUMENTACIO" else "Bejárás"
        self.set_font("DejaVu", "B", 15)
        self.cell(0, 9, f"Veszélyes ipari védelmi ügyintézői {cim.lower()}", ln=True, align="C")
        self.set_font("DejaVu", "", 10)
        self.cell(0, 6, f"{e.telephely.ugyfel.nev} - {e.datum.strftime('%Y-%m-%d') if e.datum else '-'}", ln=True, align="C")
        helyszin = e.telephely.nev if e.telephely else None
        if helyszin:
            self.cell(0, 5, helyszin, ln=True, align="C")
        if e.celellenorzes:
            self.cell(0, 5, f"Célellenőrzés: {e.celellenorzes}", ln=True, align="C")
        self.ln(2)

    def footer(self):
        self.set_y(-15)
        self.set_font("DejaVu", "", 8)
        self.cell(0, 10, "EmeLOG Nyilvántartó rendszerrel készült", align="L")
        self.set_x(-30)
        self.cell(0, 10, f"Oldal {self.page_no()}/{{nb}}", align="R")

    def alapadatok(self):
        e = self.ellenorzes
        self.set_font("DejaVu", "", 10)
        self.cell(0, 6, f"Ellenőrizte: {e.ellenorzo.username if e.ellenorzo else '-'}", ln=True)
        self.cell(0, 6, f'"Minden rendben" gomb használva: {"Igen" if e.mindenrendben else "Nem"}', ln=True)
        if e.epuletek:
            self.ln(1)
            self.set_font("DejaVu", "B", 11)
            self.cell(0, 6, "Ellenőrzött területek", ln=True)
            self.set_font("DejaVu", "", 10)
            self.multi_cell(0, 5, ", ".join(ep.nev for ep in e.epuletek), new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        self.ln(2)

    def szabalytalansag_blokk(self, sz):
        fenykepek = [
            k for k in (sz.fenykepek or [])
            if k.file_path and Path(k.file_path.lstrip("/")).exists()
        ]
        doboz = 40
        gap = 5
        oszlopok_szama = 3
        galeria_sorok = -(-len(fenykepek) // oszlopok_szama) if fenykepek else 0
        # Előre lefoglalunk kb. 35mm-t a szöveges résznek + a fénykép-galéria becsült
        # magasságának - ha nem férne ki, inkább új oldalon kezdjük, minthogy a galéria
        # (amit explicit y-nal helyezünk el) alul levágódjon.
        becsult_magassag = 35 + galeria_sorok * (doboz + gap)
        if self.get_y() > self.page_break_trigger - becsult_magassag:
            self.add_page()

        szin = SULYOSSAG_SZIN.get(sz.sulyossag, (108, 117, 125))
        self.set_fill_color(*szin)
        self.rect(10, self.get_y() + 1.5, 4, 4, style="F")
        self.set_xy(16, self.get_y())
        self.set_font("DejaVu", "B", 11)
        self.multi_cell(
            0, 6, f"{sz.tetel.szoveg}  [{SULYOSSAG_CIMKE.get(sz.sulyossag, '-')}]",
            new_x=XPos.LMARGIN, new_y=YPos.NEXT,
        )

        self.set_font("DejaVu", "", 9)
        helyszin_sor = f"Épület: {sz.epulet.nev if sz.epulet else '-'} | Szint: {sz.szint.nev if sz.szint else '-'}"
        if sz.helyiseg:
            helyszin_sor += f" | Helyiség: {sz.helyiseg}"
        self.cell(0, 5, helyszin_sor, ln=True)
        self.cell(0, 5, f"Szakterület: {_szakteruletek_szovege(sz)}", ln=True)

        self.ln(1)
        self.multi_cell(0, 5, f"Leírás: {sz.leiras or '-'}", new_x=XPos.LMARGIN, new_y=YPos.NEXT)

        if fenykepek:
            self.ln(1)
            self.set_font("DejaVu", "B", 9)
            self.cell(0, 5, f"Fényképek ({len(fenykepek)}):", ln=True)
            x_start = 16
            x = x_start
            y = self.get_y()
            legalul = y
            for idx, kep in enumerate(fenykepek):
                fajl = kep.file_path.lstrip("/")
                try:
                    kep_w, kep_h = _kep_meret_dobozba(fajl, doboz, doboz)
                    offset_x = x + (doboz - kep_w) / 2
                    offset_y = y + (doboz - kep_h) / 2
                    self.image(fajl, x=offset_x, y=offset_y, w=kep_w, h=kep_h)
                except Exception:
                    pass
                legalul = max(legalul, y + doboz)
                if (idx + 1) % oszlopok_szama == 0:
                    x = x_start
                    y = legalul + gap
                else:
                    x += doboz + gap
            self.set_y(legalul + gap)
        else:
            self.ln(2)

        self.ln(2)
        self.set_draw_color(200, 200, 200)
        self.line(10, self.get_y(), 200, self.get_y())
        self.ln(4)

    def egyszeru_lista(self, cim: str, tetelek: list):
        if not tetelek:
            return
        self.ln(2)
        self.set_font("DejaVu", "B", 11)
        self.cell(0, 7, cim, ln=True)
        self.set_font("DejaVu", "", 9)
        for t in tetelek:
            self.multi_cell(
                0, 5, f"- {t.tetel.szoveg}" + (f"  (Szint: {t.szint.nev})" if t.szint else ""),
                new_x=XPos.LMARGIN, new_y=YPos.NEXT,
            )
