"""
Wspólny rdzeń dla generatorów PSD pudełek komunijnych (chłopiec/dziewczynka).

Makieta A3 zawiera do 4 grup warstw (GL/GP/DL/DP) — 1 PSD = 1 zamówienie,
te same dane lecą do górnej i dolnej części makiety. Brak Smart Objectów,
teksty są bezpośrednio w grupach. Po normalizacji nazw (rename w PSD) wszystkie
warianty mają identyczną strukturę: od_kogo / naglowek / zyczenia / imie / data / tytul.

Jeśli szablon nie zawiera niektórych grup (np. tylko DL/DP bez GL/GP) —
pomijamy brakujące bez błędu.
"""

import argparse
import os
import photoshop.api as ps


ZYCZENIA_GROUPS = [
    ("GL", "dane"),
    ("DL", None),
]
IMIE_GROUPS = [
    ("GP", "dane"),
    ("DP", None),
]


def set_text(layer, new_text):
    """Zmienia tekst warstwy zachowując środek bounding boxa.
    Photoshop API po zmianie textItem.contents resetuje pozycję warstwy do
    punktu kotwiczenia, co dla tekstu wycentrowanego psuje layout. Liczymy
    środek bounds przed/po i kompensujemy translacją."""
    b = [float(x) for x in layer.bounds]
    cx_before = (b[0] + b[2]) / 2
    cy_before = (b[1] + b[3]) / 2
    layer.textItem.contents = new_text
    b2 = [float(x) for x in layer.bounds]
    cx_after = (b2[0] + b2[2]) / 2
    cy_after = (b2[1] + b2[3]) / 2
    dx = cx_before - cx_after
    dy = cy_before - cy_after
    if dx or dy:
        layer.translate(dx, dy)


def get_container(doc, set_name, inner_name):
    try:
        container = doc.layerSets[set_name]
    except Exception:
        return None
    if inner_name:
        try:
            container = container.layerSets[inner_name]
        except Exception:
            return None
    return container


def apply_replacements(container, replacements):
    for layer_name, new_text in replacements.items():
        if new_text is None:
            continue
        layer = container.artLayers[layer_name]
        old_text = layer.textItem.contents
        set_text(layer, new_text)
        print(f'    {layer_name}: "{old_text}" -> "{new_text}"')


def generate(szablon_path, gotowe_dir, imie, data, od_kogo, klient,
             zyczenia=None, naglowek=None, tytul=None):
    """Generuje PSD z podmienionymi danymi (1 PSD = 1 zamówienie)."""
    os.makedirs(gotowe_dir, exist_ok=True)
    output_path = os.path.join(gotowe_dir, f"{klient}.psd")

    app = ps.Application()
    doc = app.open(szablon_path)
    print(f"Otwarto szablon: {doc.name}")

    zyczenia_map = {"od_kogo": od_kogo, "naglowek": naglowek, "zyczenia": zyczenia}
    imie_map = {"imie": imie, "data": data, "tytul": tytul}

    for set_name, inner in ZYCZENIA_GROUPS:
        container = get_container(doc, set_name, inner)
        if container is None:
            print(f"  [{set_name}] życzenia: BRAK GRUPY — pomijam")
            continue
        print(f"  [{set_name}] życzenia:")
        apply_replacements(container, zyczenia_map)

    for set_name, inner in IMIE_GROUPS:
        container = get_container(doc, set_name, inner)
        if container is None:
            print(f"  [{set_name}] imię/data: BRAK GRUPY — pomijam")
            continue
        print(f"  [{set_name}] imię/data:")
        apply_replacements(container, imie_map)

    psd_opts = ps.PhotoshopSaveOptions()
    doc.saveAs(output_path, psd_opts, True)
    print(f"Zapisano: {output_path}")

    doc.close(ps.SaveOptions.DoNotSaveChanges)
    print("Gotowe!")
    return output_path


def build_arg_parser(description):
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument("--klient", required=True, help="Nazwa pliku wyjściowego")
    parser.add_argument("--imie", required=True, help="Imię dziecka")
    parser.add_argument("--data", required=True, help="Data uroczystości (np. 10.05.2026)")
    parser.add_argument("--od-kogo", dest="od_kogo", required=True, help="Od kogo (np. Rodzice Chrzestni)")
    parser.add_argument("--zyczenia", default=None, help="Treść życzeń (opcjonalnie, domyślnie z szablonu)")
    parser.add_argument("--naglowek", default=None, help="Nagłówek życzeń (opcjonalnie, domyślnie z szablonu)")
    parser.add_argument("--tytul", default=None, help="Tytuł (opcjonalnie, domyślnie z szablonu)")
    return parser
