"""
Načte layout z layouts.json a aplikuje ho na 2 vstupní PDF soubory.

Použití:
    python 27_ApplyLayout.py <pdf1> <pdf2> <vystup.pdf> [--layout 2PuzzleOnA4]

Skript si sám detekuje hranice každého puzzle (ray-cast), spočítá
scale z aktuální velikosti vs. cílové velikosti v JSON a rozmístí je.
"""

import sys
import json
import argparse
import fitz
from pathlib import Path

LAYOUTS_JSON = Path(__file__).parent.parent / "layouts.json"
DEFAULT_LAYOUT = "2PuzzleOnA4"
CROP_MARGIN_FALLBACK = 2


def detect_clip(page, crop_margin) -> fitz.Rect:
    paths = page.get_drawings()
    y_mid = page.mediabox.height / 2
    hit_h = [(p["rect"], p.get("width") or 0) for p in paths
             if p["rect"].y0 <= y_mid <= p["rect"].y1]
    if not hit_h:
        raise ValueError("Ray-cast detekce selhala — zadne kresby na y_mid")
    rects = [r for r, _ in hit_h]
    x_left  = min(r.x0 for r in rects)
    x_right = max(r.x1 for r in rects)
    top_cut = min(r.y0 for r in rects)
    bot_cut = max(r.y1 for r in rects)
    lw_l = next((lw for r, lw in hit_h if r.x0 == x_left),  0)
    lw_r = next((lw for r, lw in hit_h if r.x1 == x_right), 0)
    return fitz.Rect(
        x_left  - lw_l / 2 - crop_margin,
        top_cut - crop_margin,
        x_right + lw_r / 2 + crop_margin,
        bot_cut + crop_margin,
    )


def mm_to_pt(mm):
    return mm / 25.4 * 72


def apply_2_vertical(doc_out, sources, layout):
    page_w = layout["page"]["width_pt"]
    page_h = layout["page"]["height_pt"]
    target_w_pt = mm_to_pt(layout["target_puzzle_width_mm"])
    target_h_pt = mm_to_pt(layout["target_puzzle_height_mm"])
    crop_margin = layout.get("crop_margin_pt", CROP_MARGIN_FALLBACK)

    page = doc_out.new_page(width=page_w, height=page_h)

    clips = []
    for doc_src in sources:
        clip = detect_clip(doc_src[0], crop_margin)
        clips.append(clip)
        actual_w_mm = clip.width / 72 * 25.4
        actual_h_mm = clip.height / 72 * 25.4
        scale_w = target_w_pt / clip.width
        scale_h = target_h_pt / clip.height
        print(f"  Puzzle: {actual_w_mm:.1f} x {actual_h_mm:.1f} mm  ->  scale {scale_w:.3f} x {scale_h:.3f}")

    # Pro každý puzzle spočítej scale individuálně
    positions = []
    for clip in clips:
        pw = clip.width  * (target_w_pt / clip.width)
        ph = clip.height * (target_h_pt / clip.height)
        positions.append((pw, ph))

    # Vertikální rozmístění — equal gaps (předpokládáme stejnou výšku obou)
    ph0 = positions[0][1]
    ph1 = positions[1][1]
    gap0 = (page_h - ph0 - ph1) / 3
    gap1 = gap0

    y0 = gap0
    y1 = gap0 + ph0 + gap1

    for i, (doc_src, clip, (pw, ph)) in enumerate(zip(sources, clips, positions)):
        x0 = (page_w - pw) / 2
        y_pos = y0 if i == 0 else y1
        page.show_pdf_page(
            fitz.Rect(x0, y_pos, x0 + pw, y_pos + ph),
            doc_src, 0,
            clip=clip,
        )

    side_mm = ((page_w - positions[0][0]) / 2) / 72 * 25.4
    gap_mm = gap0 / 72 * 25.4
    print(f"  Misto po stranach: {side_mm:.1f} mm  |  Mezera: {gap_mm:.1f} mm")


def main():
    parser = argparse.ArgumentParser(description="Aplikuje layout na 2 puzzle PDF")
    parser.add_argument("pdf1", help="Prvni puzzle PDF")
    parser.add_argument("pdf2", help="Druhy puzzle PDF")
    parser.add_argument("vystup", help="Vystupni PDF")
    parser.add_argument("--layout", default=DEFAULT_LAYOUT, help=f"Nazev layoutu (default: {DEFAULT_LAYOUT})")
    args = parser.parse_args()

    if not LAYOUTS_JSON.exists():
        print(f"CHYBA: {LAYOUTS_JSON} nenalezen. Spust nejdrive 26_SaveLayout.py.", file=sys.stderr)
        sys.exit(1)

    layouts = json.loads(LAYOUTS_JSON.read_text(encoding="utf-8"))
    if args.layout not in layouts:
        print(f"CHYBA: layout '{args.layout}' nenalezen v {LAYOUTS_JSON}", file=sys.stderr)
        print(f"Dostupne layouty: {list(layouts.keys())}", file=sys.stderr)
        sys.exit(1)

    layout = layouts[args.layout]
    print(f"Layout: {args.layout}")
    print(f"Cilova velikost: {layout['target_puzzle_width_mm']} x {layout['target_puzzle_height_mm']} mm")

    doc1 = fitz.open(args.pdf1)
    doc2 = fitz.open(args.pdf2)
    doc_out = fitz.open()

    apply_2_vertical(doc_out, [doc1, doc2], layout)

    doc_out.save(args.vystup)
    doc1.close()
    doc2.close()
    doc_out.close()
    print(f"Ulozeno: {args.vystup}")


if __name__ == "__main__":
    main()
