#!/usr/bin/env python3
import argparse
import csv
import subprocess
import sys
import tempfile
from pathlib import Path
from urllib.parse import urlparse

AUTO_ROOT = Path("/home/bowerybay/public_html/wilgus-automation")
IMAGE_ROOT = Path("/home/bowerybay/public_html/wilgus-images/WILGUS")
OUTPUT_ROOT = Path("/home/bowerybay/public_html/wilgus-videos-vertical")

CATALOG_CSV = AUTO_ROOT / "wilgus-meta-hotel-catalog.csv"
IMAGES_CSV = AUTO_ROOT / "meta-hotel-images.csv"

FONT_REGULAR = "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf"
FONT_BOLD = "/usr/share/fonts/truetype/liberation/LiberationSerif-Bold.ttf"

CREAM = "0xF8F4EC"
NAVY = "0x0E2A5A"
GOLD = "0x98752E"


def die(message):
    print(f"ERROR: {message}", file=sys.stderr)
    sys.exit(1)


def esc(text):
    # Escape text for FFmpeg drawtext.
    return (
        str(text)
        .replace("\\", r"\\")
        .replace(":", r"\:")
        .replace("'", r"\'")
        .replace("%", r"\%")
    )


def load_catalog():
    with CATALOG_CSV.open("r", encoding="utf-8-sig", newline="") as f:
        return {row["id"].strip(): row for row in csv.DictReader(f)}


def load_images():
    with IMAGES_CSV.open("r", encoding="utf-8-sig", newline="") as f:
        return {row["hotel_id"].strip(): row for row in csv.DictReader(f)}


def local_image_path(prop, url):
    name = Path(urlparse(url).path).name
    if not name:
        die(f"{prop}: could not determine filename from {url}")
    path = IMAGE_ROOT / prop / name
    if not path.is_file():
        die(f"{prop}: image not found: {path}")
    return path


def number_text(value):
    value = str(value).strip()
    try:
        n = float(value)
        if n.is_integer():
            return str(int(n))
    except ValueError:
        pass
    return value


def make_video(prop, catalog_row, image_row):
    city = catalog_row.get("address.city", "").strip() or catalog_row.get("neighborhood[0]", "").strip()
    address = catalog_row.get("address.addr1", "").strip()
    beds = number_text(catalog_row.get("custom_number_0", ""))
    baths = number_text(catalog_row.get("custom_number_1", ""))
    sleeps = number_text(catalog_row.get("custom_number_2", ""))

    if not all([city, address, beds, baths, sleeps]):
        die(f"{prop}: missing required catalog data")

    urls = [image_row.get(f"image[{i}].url", "").strip() for i in range(6)]
    if any(not u for u in urls):
        die(f"{prop}: fewer than six image URLs in supplemental CSV")
    paths = [local_image_path(prop, u) for u in urls]

    OUTPUT_ROOT.mkdir(parents=True, exist_ok=True)
    output = OUTPUT_ROOT / f"{prop}.mp4"
    if output.exists():
        print(f"SKIP: {output} already exists")
        return

    inputs = []
    for p in paths:
        inputs += ["-loop", "1", "-t", "2", "-i", str(p)]

    filters = []
    for i in range(6):
        filters.append(f"[{i}:v]scale=1080:771,setsar=1,format=yuv420p[v{i}]")

    filters += [
        "[v0][v1]xfade=transition=fade:duration=0.4:offset=1.6[x1]",
        "[x1][v2]xfade=transition=fade:duration=0.4:offset=3.2[x2]",
        "[x2][v3]xfade=transition=fade:duration=0.4:offset=4.8[x3]",
        "[x3][v4]xfade=transition=fade:duration=0.4:offset=6.4[x4]",
        "[x4][v5]xfade=transition=fade:duration=0.4:offset=8.0[photos]",
        f"color=c={CREAM}:s=1080x1920:d=10[bg]",
        "[bg][photos]overlay=0:550[tmp]",
    ]

    text_dir = OUTPUT_ROOT / ".text"
    text_dir.mkdir(parents=True, exist_ok=True)
    city_path = text_dir / f"{prop}-city.txt"
    address_path = text_dir / f"{prop}-address.txt"
    city_path.write_text(city.upper(), encoding="utf-8")
    address_path.write_text(address.upper(), encoding="utf-8")
    city_file = str(city_path).replace(":", r"\:")
    address_file = str(address_path).replace(":", r"\:")

    bed_word = "BEDROOM" if beds == "1" else "BEDROOMS"
    bath_word = "BATHROOM" if baths == "1" else "BATHROOMS"

    draw = (
        f"[tmp]"
        f"drawtext=fontfile={FONT_BOLD}:textfile='{city_file}':fontcolor={NAVY}:fontsize=68:x=(w-text_w)/2:y=325,"
        f"drawtext=fontfile={FONT_BOLD}:text='VACATION RENTAL':fontcolor={GOLD}:fontsize=38:x=(w-text_w)/2:y=405,"
        f"drawtext=fontfile={FONT_REGULAR}:textfile='{address_file}':fontcolor={NAVY}:fontsize=38:x=(w-text_w)/2:y=465,"
        f"drawtext=fontfile={FONT_BOLD}:text='{esc(beds)} {bed_word}':fontcolor={NAVY}:fontsize=40:x=85:y=1360,"
        f"drawtext=fontfile={FONT_BOLD}:text='{esc(baths)} {bath_word}':fontcolor={NAVY}:fontsize=40:x=(w-text_w)/2:y=1360,"
        f"drawtext=fontfile={FONT_BOLD}:text='SLEEPS {esc(sleeps)}':fontcolor={NAVY}:fontsize=40:x=w-text_w-85:y=1360,"
        f"drawbox=x=329:y=1357:w=2:h=48:color={GOLD}:t=fill,"
        f"drawbox=x=747:y=1357:w=2:h=48:color={GOLD}:t=fill,"
        f"drawtext=fontfile={FONT_BOLD}:text='WILGUS ASSOCIATES':fontcolor={NAVY}:fontsize=55:x=(w-text_w)/2:y=1440,"
        f"drawtext=fontfile={FONT_BOLD}:text='VACATION RENTALS - OVER 80 YEARS':fontcolor={GOLD}:fontsize=32:x=(w-text_w)/2:y=1510,"
        f"drawtext=fontfile={FONT_BOLD}:text='wilgusassociates.com':fontcolor={NAVY}:fontsize=34:x=(w-text_w)/2:y=1565[out]"
    )
    filters.append(draw)

    cmd = [
        "ffmpeg", "-y",
        *inputs,
        "-filter_complex", ";".join(filters),
        "-map", "[out]",
        "-t", "10",
        "-r", "30",
        "-c:v", "libx264",
        "-crf", "20",
        "-preset", "medium",
        "-pix_fmt", "yuv420p",
        "-movflags", "+faststart",
        str(output),
    ]

    print(f"{prop}: {city} | {address} | {beds} bed | {baths} bath | sleeps {sleeps}")
    print("Images:", ", ".join(p.name for p in paths))
    subprocess.run(cmd, check=True)
    city_path.unlink(missing_ok=True)
    address_path.unlink(missing_ok=True)
    print(f"DONE: {output}")


def main():
    parser = argparse.ArgumentParser(description="Create Wilgus 9:16 vertical catalog videos.")
    parser.add_argument("property_id", help="Property ID, or 'all' to generate every matched property")
    args = parser.parse_args()

    catalog = load_catalog()
    images = load_images()

    if args.property_id.lower() == "all":
        props = sorted(set(catalog) & set(images))
        print(f"Generating {len(props)} matched properties")
    else:
        prop = args.property_id.strip()
        if prop not in catalog:
            die(f"Property {prop} not found in catalog CSV")
        if prop not in images:
            die(f"Property {prop} not found in image CSV")
        props = [prop]

    for prop in props:
        make_video(prop, catalog[prop], images[prop])


if __name__ == "__main__":
    main()
