#!/usr/bin/env python3
import argparse, csv, subprocess, sys
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-wilgus")
ASSET_ROOT = AUTO_ROOT / "wilgus-v4-assets"

CATALOG_CSV = AUTO_ROOT / "wilgus-meta-hotel-catalog.csv"
IMAGES_CSV = AUTO_ROOT / "meta-hotel-images.csv"
HEADER = ASSET_ROOT / "wilgus-v4-header.jpg"
FOOTER = ASSET_ROOT / "wilgus-v4-beach-footer.jpg"
LOGO = ASSET_ROOT / "wilgus-logo.png"

FONT_REGULAR = "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf"
FONT_BOLD = "/usr/share/fonts/truetype/liberation/LiberationSerif-Bold.ttf"
FONT_ITALIC = "/usr/share/fonts/truetype/liberation/LiberationSerif-Italic.ttf"
FONT_AWESOME = "/usr/share/fonts/opentype/font-awesome/FontAwesome.otf"

CREAM="0xF8F4EC"; NAVY="0x0E2A5A"; ORANGE="0xF04A00"

def die(s):
    print("ERROR:", s, file=sys.stderr); sys.exit(1)

def esc(s):
    return str(s).replace("\\",r"\\").replace(":",r"\:").replace("'",r"\'").replace("%",r"\%")

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

def num(v):
    v=str(v).strip()
    try:
        n=float(v)
        return str(int(n)) if n.is_integer() else v
    except: return v

def local_image(prop,url):
    p=IMAGE_ROOT/prop/Path(urlparse(url).path).name
    if not p.is_file(): die(f"{prop}: missing {p}")
    return p

def make(prop,c,i):
    city=(c.get("address.city","").strip() or c.get("neighborhood[0]","").strip()).upper()
    state=c.get("address.region","").strip().upper()
    location=f"{city}, {state}" if state else city
    address=c.get("address.addr1","").strip()
    beds=num(c.get("custom_number_0","")); baths=num(c.get("custom_number_1","")); sleeps=num(c.get("custom_number_2",""))
    if not all([city,address,beds,baths,sleeps]): die(f"{prop}: missing catalog data")

    urls=[i.get(f"image[{x}].url","").strip() for x in range(6)]
    if any(not x for x in urls): die(f"{prop}: fewer than six images")
    pics=[local_image(prop,u) for u in urls]

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

    textdir=OUTPUT_ROOT/".text"; textdir.mkdir(exist_ok=True)
    ap=textdir/f"{prop}-address.txt"; lp=textdir/f"{prop}-location.txt"
    ap.write_text(address,encoding="utf-8"); lp.write_text(location,encoding="utf-8")
    af=str(ap).replace(":",r"\:"); lf=str(lp).replace(":",r"\:")

    inputs=[]
    for p in pics: inputs += ["-loop","1","-t","2","-i",str(p)]
    inputs += ["-loop","1","-t","10","-i",str(HEADER),
               "-loop","1","-t","10","-i",str(FOOTER),
               "-loop","1","-t","10","-i",str(LOGO)]

    f=[]
    # Photos fill their slot completely; no decorative background is allowed to peek around them.
    for x in range(6):
        f.append(f"[{x}:v]scale=1080:560:force_original_aspect_ratio=increase,crop=1080:560,setsar=1,format=yuv420p[v{x}]")
    f += [
      "[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]",
      "[6:v]scale=1080:400[head]",
      "[7:v]scale=1080:320[foot]",
      "[8:v]scale=300:-1[logo]",
      "[bg][head]overlay=0:0[a]",
      "[a][photos]overlay=0:400[b]",
      "[b][foot]overlay=0:1600[c]",
    ]

    # FontAwesome: bed=f236, bath=f2cd, users=f0c0, map-marker=f041
    bed="\\uf236"; bath="\\uf2cd"; users="\\uf0c0"; pin="\\uf041"
    draw = (
      f"[c]"
      f"drawtext=fontfile='{FONT_AWESOME}':text='{bed}':fontcolor={NAVY}:fontsize=48:x=120:y=1000,"
      f"drawtext=fontfile='{FONT_BOLD}':text='{esc(beds)}':fontcolor={NAVY}:fontsize=54:x=205:y=990,"
      f"drawtext=fontfile='{FONT_REGULAR}':text='Bedrooms':fontcolor={NAVY}:fontsize=31:x=125:y=1050,"
      f"drawbox=x=330:y=985:w=2:h=95:color={ORANGE}:t=fill,"
      f"drawtext=fontfile='{FONT_AWESOME}':text='{bath}':fontcolor={NAVY}:fontsize=48:x=405:y=1000,"
      f"drawtext=fontfile='{FONT_BOLD}':text='{esc(baths)}':fontcolor={NAVY}:fontsize=54:x=485:y=990,"
      f"drawtext=fontfile='{FONT_REGULAR}':text='Bathrooms':fontcolor={NAVY}:fontsize=31:x=405:y=1050,"
      f"drawbox=x=680:y=985:w=2:h=95:color={ORANGE}:t=fill,"
      f"drawtext=fontfile='{FONT_AWESOME}':text='{users}':fontcolor={NAVY}:fontsize=48:x=755:y=1000,"
      f"drawtext=fontfile='{FONT_BOLD}':text='{esc(sleeps)}':fontcolor={NAVY}:fontsize=54:x=845:y=990,"
      f"drawtext=fontfile='{FONT_REGULAR}':text='Sleeps':fontcolor={NAVY}:fontsize=31:x=790:y=1050,"
      f"drawbox=x=75:y=1110:w=930:h=2:color={ORANGE}:t=fill,"
      f"drawtext=fontfile='{FONT_AWESOME}':text='{pin}':fontcolor={ORANGE}:fontsize=50:x=260:y=1145,"
      f"drawtext=fontfile='{FONT_BOLD}':textfile='{af}':fontcolor={NAVY}:fontsize=40:x=330:y=1138,"
      f"drawtext=fontfile='{FONT_REGULAR}':textfile='{lf}':fontcolor={NAVY}:fontsize=27:x=(w-text_w)/2:y=1195,"
      f"drawbox=x=75:y=1245:w=930:h=2:color={ORANGE}:t=fill,"
      f"drawtext=fontfile='{FONT_ITALIC}':text='Come for a week. Remember it for years.':fontcolor={NAVY}:fontsize=40:x=(w-text_w)/2:y=1280[base];"
      f"[base][logo]overlay=(W-w)/2:1360[mid];"
      f"[mid]drawtext=fontfile='{FONT_BOLD}':text='wilgusassociates.com':fontcolor={NAVY}:fontsize=31:x=(w-text_w)/2:y=1460[out]"
    )
    f.append(draw)

    cmd=["ffmpeg","-y",*inputs,"-filter_complex",";".join(f),"-map","[out]",
         "-t","10","-r","30","-c:v","libx264","-crf","20","-preset","medium",
         "-pix_fmt","yuv420p","-movflags","+faststart",str(out)]
    print(f"{prop}: {address} | {location} | {beds} bed | {baths} bath | sleeps {sleeps}")
    subprocess.run(cmd,check=True)
    ap.unlink(missing_ok=True); lp.unlink(missing_ok=True)
    print("DONE:",out)

def main():
    for p in [CATALOG_CSV,IMAGES_CSV,HEADER,FOOTER,LOGO]:
        if not p.is_file(): die(f"required file missing: {p}")
    pa=argparse.ArgumentParser()
    pa.add_argument("property_id",help="property ID or all")
    a=pa.parse_args()
    cat=rows(CATALOG_CSV,"id"); imgs=rows(IMAGES_CSV,"hotel_id")
    props=sorted(set(cat)&set(imgs)) if a.property_id.lower()=="all" else [a.property_id.strip()]
    print(f"Generating {len(props)} properties into {OUTPUT_ROOT}")
    for p in props:
        if p not in cat or p not in imgs: die(f"{p}: not found in both CSVs")
        make(p,cat[p],imgs[p])

if __name__=="__main__": main()
