"""架空の請求下書きフォーム（成功表示のうそ編）。
mode:
  normal : 正常に保存
  ghost  : 「保存しました」と出るが、何も保存されない
  stale  : 保存はされるが、一覧と詳細に出るのは保存の12秒後から
  dup    : 同じ請求番号の既存レコード(DRAFT-0001, 9000円)があり、保存すると黙って上書きされる
"""
import html, json, sys, threading, time
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

mode, port, out = sys.argv[1], int(sys.argv[2]), sys.argv[3]
lock = threading.Lock()
log = []
posts = {"n": 0}
records = []
if mode == "dup":
    records.append({"id": "DRAFT-0001", "customer_code": "000123", "supplier": "Aoba Demo",
                    "invoice_no": "INV-2026-0042", "invoice_date": "2026-09-15", "total_jpy": "9000",
                    "visible_at": 0})

FIELDS = [("customer_code", "顧客コード"), ("supplier", "仕入先名"), ("invoice_no", "請求番号"),
          ("invoice_date", "請求日"), ("total_jpy", "税込金額（円）")]

def dump():
    json.dump({"mode": mode, "records": records, "log": log, "posts": posts["n"]},
              open(out, "w"), ensure_ascii=False)

def visible():
    now = time.time()
    return [r for r in records if r["visible_at"] <= now]

class H(BaseHTTPRequestHandler):
    def log_message(self, *_): pass
    def send(self, body, status=200):
        b = body.encode()
        self.send_response(status); self.send_header("Content-Type", "text/html; charset=utf-8")
        self.send_header("Content-Length", str(len(b))); self.end_headers(); self.wfile.write(b)
    def do_GET(self):
        with lock:
            log.append(["GET", self.path, round(time.time(), 1)]); dump()
            vis = visible()
        if self.path == "/":
            inputs = "".join(f'<p><label>{l}<br><input name="{k}"></label></p>' for k, l in FIELDS)
            self.send("<h1>請求書の下書き登録</h1><p><a href=\"/records\">下書き一覧</a></p>" + inputs +
              '<button id="save">下書き保存</button><p id="status"></p>'
              "<script>document.querySelector('#save').onclick=async()=>{"
              "const d=Object.fromEntries([...document.querySelectorAll('input')].map(e=>[e.name,e.value]));"
              "const r=await fetch('/save',{method:'POST',body:JSON.stringify(d)});"
              "const j=await r.json();document.querySelector('#status').innerHTML="
              "'下書きを保存しました（登録ID: '+j.id+'）　<a href=\"/records\">一覧へ</a>';};</script>")
        elif self.path == "/records":
            rows = "".join(f'<tr><td><a href="/record/{r["id"]}">{r["id"]}</a></td><td>{html.escape(r["supplier"])}</td>'
                           f'<td>{html.escape(r["invoice_no"])}</td><td>{html.escape(r["total_jpy"])}</td></tr>' for r in vis)
            self.send("<h1>下書き一覧</h1><table border=1><tr><th>登録ID</th><th>仕入先</th><th>請求番号</th><th>税込金額</th></tr>" + rows + "</table>")
        elif self.path.startswith("/record/"):
            rid = self.path.split("/")[-1]
            r = next((x for x in vis if x["id"] == rid), None)
            if not r: return self.send("not found", 404)
            self.send(f"<h1>下書き {rid}</h1>" + "".join(f"<p>{l}: <span>{html.escape(r[k])}</span></p>" for k, l in FIELDS))
        else:
            self.send("not found", 404)
    def do_POST(self):
        data = json.loads(self.rfile.read(int(self.headers["Content-Length"])))
        with lock:
            posts["n"] += 1
            log.append(["POST", "/save", data, round(time.time(), 1)])
            if mode == "ghost":
                rid = "DRAFT-0001"
            elif mode == "dup":
                old = records[0]
                old.update({k: data[k] for k, _ in FIELDS})
                rid = old["id"]
            else:
                rid = f"DRAFT-{len(records)+1:04d}"
                records.append({"id": rid, **data, "visible_at": time.time() + (12 if mode == "stale" else 0)})
            dump()
        self.send(json.dumps({"id": rid}))

ThreadingHTTPServer(("127.0.0.1", port), H).serve_forever()
