#!/usr/bin/env python3
"""
DIY Passport Server
在 app.py 基础上增加 /diy 页面，固定区域(Type/Country/Nationality/Authority)
可逐项勾选是否写入护照。
用法: python3 diy_server.py   (端口 7860，替代原 app.py 启动)
"""

import sys, os, uuid, shutil

sys.path.insert(0, "/data/port")
sys.path.insert(0, "/data/port/scripts")

from app import (
    app, executor, tasks, tasks_lock,
    make_id_photo, swap_faces, TEMPLATE_GIRL,
    random_passport_data, paired_name, cleanup_old_files,
)
import passport_m03
from passport_m03 import (
    M02_FIELD_POS, M02_FIELD_SIZE,
    load_font, draw_text_mask, COLORS,
)
from flask import render_template, request, jsonify
from PIL import Image


# ────────────────────── /diy 页面 ──────────────────────

@app.route("/diy")
def diy_page():
    return render_template("diy.html")


@app.route("/generate_passport_diy", methods=["POST"])
def gen_passport_diy():
    """DIY 生成：固定区域可逐项勾选是否写入。"""
    if "source" not in request.files:
        return jsonify({"ok": False, "error": "请上传大头照"}), 400
    sf = request.files["source"]
    if sf.filename == "":
        return jsonify({"ok": False, "error": "请选择源图片"}), 400

    # ── 收集全部字段值 ──
    data = {}
    for key in ["type", "country_code", "passport_no", "name",
                "nationality", "dob", "sex", "issue_date", "expiry_date",
                "birth_place", "authority"]:
        data[key] = (request.form.get(key, "") or "").strip()

    # 勾选了哪些固定字段要写入
    write_fixed_str = (request.form.get("write_fixed_fields") or "").strip()
    write_fixed = set(f for f in write_fixed_str.split(",") if f)

    # ── 默认值 ──
    if not data["type"]:          data["type"] = "PV"
    if not data["country_code"]:  data["country_code"] = "MMR"
    if not data["nationality"]:   data["nationality"] = "MYANMAR"
    if not data["authority"]:     data["authority"] = "MOHA, KYAINGTONG"
    sex = (data.get("sex") or "F").upper()[:1]
    if sex not in ("M", "F"):     sex = "F"
    data["sex"] = sex
    rnd = random_passport_data(sex=sex)
    for k in ["passport_no", "dob", "birth_place", "issue_date",
              "expiry_date", "name"]:
        if not data[k]:
            data[k] = rnd[k]

    # ── 保存源图 ──
    src_ext = os.path.splitext(sf.filename)[1] or ".jpg"
    src_name = f"src_{uuid.uuid4().hex}{src_ext}"
    src_path = os.path.join(app.config["UPLOAD_FOLDER"], src_name)
    sf.save(src_path)

    pair_name = paired_name()
    shutil.copy2(src_path,
                 os.path.join(app.config["PAIRED_PIN"], f"{pair_name}{src_ext}"))

    # ── Step 1: 证件照 ──
    id_name = f"id_{uuid.uuid4().hex}.jpg"
    id_path = os.path.join(app.config["UPLOAD_FOLDER"], id_name)
    err = make_id_photo(src_path, id_path)
    if err:
        return jsonify({"ok": False, "error": f"制证失败: {err}"}), 500

    # ── Step 2: 换脸 ──
    swapped_name = f"swapped_{uuid.uuid4().hex}.png"
    swapped_path = os.path.join(app.config["UPLOAD_FOLDER"], swapped_name)
    err = swap_faces(id_path, TEMPLATE_GIRL, swapped_path)
    if err:
        return jsonify({"ok": False, "error": f"换脸失败: {err}"}), 500

    out_name = f"diy_{uuid.uuid4().hex}.png"
    out_path = os.path.join(app.config["RESULT_FOLDER"], out_name)
    task_id = out_name

    with tasks_lock:
        tasks[task_id] = {"status": "processing", "mode": "diy"}

    def _do():
        try:
            # 1) 写可编辑字段 + MRZ（跳过全部固定区域）
            passport_m03.write_passport(
                swapped_path, out_path, data,
                template="m02", skip_header=True, skip_fixed=True,
                no_affine=True,
            )

            # 2) 逐项写入勾选的固定字段
            drawn = write_fixed & {"type", "nationality", "authority", "country_code"}
            if drawn:
                img = Image.open(out_path)
                for fk in drawn:
                    val = data.get(fk, "")
                    if not val or fk not in M02_FIELD_POS:
                        continue
                    fx, fy = M02_FIELD_POS[fk]
                    fnt = load_font("val", M02_FIELD_SIZE.get(fk, 24))
                    draw_text_mask(img, (fx, fy), str(val),
                                   fnt, COLORS["val"], "lt")
                img.save(out_path, dpi=(300, 300))

            with tasks_lock:
                paired_out = os.path.join(
                    app.config["PAIRED_POUT"], f"{pair_name}.png")
                shutil.copy2(out_path, paired_out)
                tasks[task_id] = {
                    "status": "done",
                    "result_url": f"/result/{out_name}",
                    "mode": "diy",
                }
            print(f"[DIY] {task_id} done  write_fixed={write_fixed}", flush=True)
        except Exception as e:
            import traceback
            traceback.print_exc()
            with tasks_lock:
                tasks[task_id] = {"status": "error", "error": str(e)}
        finally:
            for p in [src_path, swapped_path]:
                try: os.remove(p)
                except OSError: pass

    executor.submit(_do)
    return jsonify({"ok": True, "task_id": task_id})


# ────────────────────── 启动 ──────────────────────

if __name__ == "__main__":
    BASE = "/data/port"
    cleanup_old_files(os.path.join(BASE, "web", "uploads"), 3600)
    cleanup_old_files(os.path.join(BASE, "web", "results"), 3600)
    print("[DIY] Ready ->  port.mbvpn.cn/diy  (port 7860)", flush=True)
    app.run(host="0.0.0.0", port=7860, debug=False, threaded=True)
