#!/usr/bin/env python3
"""
immich_upload.py — nahrava wanted fotky z DB fotky_buzalkovi do Immiche.
Cte primo ze zalohy (NFS), nahrava KOPII pres Immich API. Zalohu nesaha.
Resumable: tabulka immich_upload (zaloha_id -> asset id, status).

Spousti se v kontejneru python-runner:
  docker exec python-runner python3 /scripts/immich_upload.py --like '...%' --limit 200
"""
import os
import sys
import argparse
from datetime import datetime, timezone

import requests
import psycopg

sys.stdout.reconfigure(encoding="utf-8")

DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka",
          password="Vlado7309208104++", dbname="fotky_buzalkovi")
IMMICH = "http://192.168.1.76:8888"
APIKEY = "UQV5PS1Td50hKOZTItnXEcXVkfQSUxcUH0XHZYxc"

SRC_PREFIX = "/mnt/user/ZalohaVsechObrazku"   # jak je cesta v DB
DST_PREFIX = "/mnt/ZalohaVsechObrazku"        # jak ji vidi kontejner

ap = argparse.ArgumentParser()
ap.add_argument("--like", default=None, help="filtr na z.cesta_zalohy LIKE")
ap.add_argument("--category", default=None, help="filtr na p.category")
ap.add_argument("--limit", type=int, default=0)
ap.add_argument("--dry-run", action="store_true")
args = ap.parse_args()

conn = psycopg.connect(**DB, autocommit=True)
cur = conn.cursor()

cur.execute("""
    CREATE TABLE IF NOT EXISTS immich_upload(
        zaloha_id   bigint PRIMARY KEY,
        immich_id   uuid,
        status      text,
        uploaded_at timestamptz DEFAULT now()
    )
""")

sql = """
    SELECT z.id, z.cesta_zalohy, p.taken_at
    FROM photos p
    JOIN zaloha_obrazku z ON p.zaloha_id = z.id
    LEFT JOIN immich_upload iu ON iu.zaloha_id = z.id
    WHERE p.wanted = TRUE AND iu.zaloha_id IS NULL
"""
params = []
if args.category:
    sql += " AND p.category = %s"; params.append(args.category)
if args.like:
    sql += " AND z.cesta_zalohy LIKE %s"; params.append(args.like)
sql += " ORDER BY z.cesta_zalohy"
if args.limit:
    sql += " LIMIT %s"; params.append(args.limit)

cur.execute(sql, params)
rows = cur.fetchall()
total = len(rows)
print(f"K nahrani (jeste nenahrano): {total:,}")
if args.dry_run:
    miss = sum(1 for _, c, _ in rows if not os.path.isfile(c.replace(SRC_PREFIX, DST_PREFIX, 1)))
    print(f"DRY-RUN: chybejicich souboru: {miss}")
    sys.exit(0)

sess = requests.Session()
sess.headers.update({"x-api-key": APIKEY, "Accept": "application/json"})

created = dup = err = 0
for i, (zid, cesta, taken) in enumerate(rows, 1):
    path = cesta.replace(SRC_PREFIX, DST_PREFIX, 1)
    if not os.path.isfile(path):
        err += 1
        print("MISSING:", path)
        continue
    st = os.stat(path)
    fmod = datetime.fromtimestamp(st.st_mtime, tz=timezone.utc)
    fcreated = taken if taken else fmod
    if fcreated.tzinfo is None:
        fcreated = fcreated.replace(tzinfo=timezone.utc)
    try:
        with open(path, "rb") as fh:
            r = sess.post(
                IMMICH + "/api/assets",
                files={"assetData": (os.path.basename(path), fh, "application/octet-stream")},
                data={
                    "deviceAssetId": f"fb-{zid}",
                    "deviceId": "fotky-buzalkovi",
                    "fileCreatedAt": fcreated.isoformat(),
                    "fileModifiedAt": fmod.isoformat(),
                    "isFavorite": "false",
                },
                timeout=300,
            )
        j = r.json()
        status = j.get("status")
        aid = j.get("id")
        cur.execute(
            """INSERT INTO immich_upload(zaloha_id, immich_id, status)
               VALUES (%s,%s,%s)
               ON CONFLICT (zaloha_id) DO UPDATE
               SET immich_id=EXCLUDED.immich_id, status=EXCLUDED.status, uploaded_at=now()""",
            (zid, aid, status),
        )
        if status == "created":
            created += 1
        elif status == "duplicate":
            dup += 1
        else:
            err += 1
            print("? neznamy status:", status, j)
    except Exception as e:
        err += 1
        print("ERR", zid, repr(e))
    if i % 50 == 0 or i == total:
        print(f"... {i}/{total}  created={created} dup={dup} err={err}", flush=True)

print(f"\nHOTOVO. created={created} dup={dup} err={err}")
conn.close()
