// ThaiHao submit module — single-POST against Cloudflare Pages Function.
//
// Different from the original Apps Script bundle: there is no Drive folder
// and no per-file upload phase. We base64-encode files inline and send
// everything to /api/submit in one request. The backend sends two emails
// (applicant confirmation + team notification) via SMTP and returns the
// registration_id.

const ConfigEl = document.getElementById("thaihao-config");
const SubmitConfig = ConfigEl ? JSON.parse(ConfigEl.textContent) : {};

const DEFAULT_ENDPOINT = "/api/submit";
const isConfigured = () => true;
const endpoint = () => SubmitConfig.submitEndpoint || DEFAULT_ENDPOINT;

// ---------- reCAPTCHA v3 loader (only if configured) ----------
let recaptchaReady = null;
function ensureRecaptcha() {
  if (!SubmitConfig.recaptchaSiteKey) return Promise.resolve(null);
  if (recaptchaReady) return recaptchaReady;
  recaptchaReady = new Promise((resolve) => {
    if (window.grecaptcha && window.grecaptcha.ready) {
      window.grecaptcha.ready(() => resolve(window.grecaptcha));
      return;
    }
    const s = document.createElement("script");
    s.src = `https://www.google.com/recaptcha/api.js?render=${encodeURIComponent(SubmitConfig.recaptchaSiteKey)}`;
    s.async = true; s.defer = true;
    s.onload = () => {
      if (window.grecaptcha && window.grecaptcha.ready) {
        window.grecaptcha.ready(() => resolve(window.grecaptcha));
      } else { resolve(null); }
    };
    s.onerror = () => resolve(null);
    document.head.appendChild(s);
  });
  return recaptchaReady;
}
async function getRecaptchaToken(action) {
  if (!SubmitConfig.recaptchaSiteKey) return null;
  const g = await ensureRecaptcha();
  if (!g) return null;
  try {
    return await g.execute(SubmitConfig.recaptchaSiteKey, { action });
  } catch (e) { return null; }
}

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onerror = reject;
    r.onload = () => {
      const s = r.result;
      const comma = s.indexOf(",");
      resolve(s.slice(comma + 1));
    };
    r.readAsDataURL(file);
  });
}

function ensureIdempotencyId() {
  let id = sessionStorage.getItem("thaihao_idem");
  if (!id) {
    id = (crypto && crypto.randomUUID)
      ? crypto.randomUUID()
      : ("id-" + Date.now().toString(36) + "-" + Math.random().toString(36).slice(2, 10));
    sessionStorage.setItem("thaihao_idem", id);
  }
  return id;
}
function clearIdempotencyId() {
  sessionStorage.removeItem("thaihao_idem");
}

function makeRegistrationId() {
  const d = new Date();
  const yyyymm = d.getUTCFullYear().toString() + String(d.getUTCMonth() + 1).padStart(2, "0");
  const rand = Math.random().toString(36).slice(2, 7).toUpperCase();
  return `TH-${yyyymm}-${rand}`;
}

async function inlineFiles(data, onProgress, lang) {
  const groups = ["doc_cert", "doc_logo", "doc_id", "doc_licenses"];
  const totalFiles =
    groups.reduce((n, k) => n + (data[k] || []).length, 0) +
    (data.products || []).reduce((n, p) => n + (p.images || []).length, 0);

  let i = 0;
  const tick = (entry) => {
    i += 1;
    onProgress && onProgress({
      phase: "upload",
      current: i,
      total: totalFiles,
      label: lang === "th"
        ? `กำลังเตรียมไฟล์ ${i} จาก ${totalFiles}`
        : `Preparing file ${i} of ${totalFiles}`,
      fileName: entry && entry.name,
    });
  };

  async function packList(list) {
    const out = [];
    for (const entry of list || []) {
      if (!entry || !entry.file) {
        out.push({
          id: entry && entry.id, name: entry && entry.name,
          size: entry && entry.size, type: entry && entry.type, data: null,
        });
        continue;
      }
      tick(entry);
      let b64 = null;
      try { b64 = await fileToBase64(entry.file); } catch (e) { b64 = null; }
      out.push({ id: entry.id, name: entry.name, size: entry.size, type: entry.type, data: b64 });
    }
    return out;
  }

  const packed = { ...data };
  for (const k of groups) packed[k] = await packList(data[k]);
  packed.products = [];
  for (const p of data.products || []) {
    packed.products.push({ ...p, images: await packList(p.images) });
  }
  return packed;
}

async function postSubmit(payload) {
  const body = JSON.stringify(payload);
  const res = await fetch(endpoint(), {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body,
  });
  const text = await res.text();
  let parsed = null;
  try { parsed = JSON.parse(text); } catch (e) {
    throw new Error(`Bad response (${res.status}): ${text.slice(0, 200)}`);
  }
  if (!res.ok && (!parsed || parsed.ok !== false)) {
    throw new Error(`HTTP ${res.status}`);
  }
  return parsed;
}

async function submitRegistration(data, lang, onProgress) {
  const idempotencyId = ensureIdempotencyId();
  const honeypot = "";
  const recaptchaToken = await getRecaptchaToken("submit");

  onProgress && onProgress({
    phase: "init", current: 0, total: 0,
    label: lang === "th" ? "กำลังเตรียมส่งข้อมูล" : "Preparing submission",
  });

  const packed = await inlineFiles(data, onProgress, lang);

  onProgress && onProgress({
    phase: "finalize", current: 0, total: 0,
    label: lang === "th" ? "กำลังลงทะเบียน" : "Finalizing",
  });

  const registrationId = makeRegistrationId();

  let result;
  try {
    result = await postSubmit({
      action: "submit",
      idempotency_id: idempotencyId,
      registration_id: registrationId,
      recaptcha_token: recaptchaToken,
      website_url_check: honeypot,
      lang,
      signed_at: new Date().toISOString(),
      origin: location.origin,
      data: packed,
    });
  } catch (e) {
    return { ok: false, error: "network", detail: { message: String(e) } };
  }

  if (!result || result.ok === false) {
    return { ok: false, error: (result && result.error) || "server", detail: result };
  }

  clearIdempotencyId();
  return {
    ok: true,
    registration_id: result.registration_id || registrationId,
    folder_url: result.folder_url || null,
  };
}

Object.assign(window, {
  submitRegistration, isSubmitConfigured: isConfigured, SubmitConfig,
  ensureIdempotencyId, clearIdempotencyId,
});
