// =================================================================
// pw-screens-coupons.jsx — Publisher Admin · Coupon Offers · Brand Codes
// =================================================================

function discountSummary(c) {
  if (!c) return "—";
  const amt = c.discount_type === "percent" ? `${c.discount_value}% off` : `${fmt.currency(c.discount_value, c.currency)} off`;
  const bits = [amt];
  if (c.applies_to) bits.push(`on ${c.applies_to === "both" ? "products & services" : c.applies_to + "s"}`);
  if (c.min_order_amount) bits.push(`min ${fmt.currency(c.min_order_amount, c.currency)}`);
  if (c.max_discount_amount) bits.push(`cap ${fmt.currency(c.max_discount_amount, c.currency)}`);
  return bits.join(" · ");
}

const overlayPositionOptions = [
  { label: "Bottom left", value: "bottom_left" },
  { label: "Bottom right", value: "bottom_right" },
  { label: "Top left", value: "top_left" },
  { label: "Top right", value: "top_right" },
  { label: "Center", value: "center" },
];
const overlayToneOptions = [
  { label: "Dark", value: "dark" },
  { label: "Light", value: "light" },
  { label: "Brand", value: "brand" },
];

const offerVisual = (offer, code) => ({
  image: offer.image_url || code?.image_url || "",
  title: offer.overlay_title || code?.name || "Reader offer",
  subtitle: offer.overlay_subtitle || discountSummary(code),
  badge: offer.overlay_badge || code?.brand || "Offer",
  position: offer.overlay_position || "bottom_left",
  tone: offer.overlay_tone || "dark",
});

const OfferImagePreview = ({ offer, code, compact }) => {
  const v = offerVisual(offer || {}, code || {});
  return (
    <div className={`pw-offer-img ${compact ? "compact" : ""} ${v.image ? "" : "empty"}`}>
      {v.image ? <img src={v.image} alt="" /> : <div className="pw-offer-img-empty"><IconGift size={28}/></div>}
      <div className={`pw-offer-ov ${v.position} ${v.tone}`}>
        {v.badge && <span>{v.badge}</span>}
        {v.title && <strong>{v.title}</strong>}
        {v.subtitle && <small>{v.subtitle}</small>}
      </div>
      <style>{`
        .pw-offer-img { position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-md); overflow: hidden; background: var(--panel-2); border: 1px solid var(--line); }
        .pw-offer-img.compact { margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 14px; border-left: 0; border-right: 0; border-top: 0; border-radius: var(--r-md) var(--r-md) 0 0; }
        .pw-offer-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
        .pw-offer-img-empty { height: 100%; display: flex; align-items: center; justify-content: center; color: var(--muted-2); }
        .pw-offer-ov { position: absolute; display: flex; flex-direction: column; gap: 3px; max-width: 78%; padding: 10px 12px; border-radius: 8px; }
        .pw-offer-ov.bottom_left { left: 12px; bottom: 12px; }
        .pw-offer-ov.bottom_right { right: 12px; bottom: 12px; text-align: right; align-items: flex-end; }
        .pw-offer-ov.top_left { left: 12px; top: 12px; }
        .pw-offer-ov.top_right { right: 12px; top: 12px; text-align: right; align-items: flex-end; }
        .pw-offer-ov.center { left: 50%; top: 50%; transform: translate(-50%, -50%); text-align: center; align-items: center; }
        .pw-offer-ov.dark { color: white; background: rgba(13,17,28,.74); }
        .pw-offer-ov.light { color: #101828; background: rgba(255,255,255,.82); }
        .pw-offer-ov.brand { color: var(--accent-strong); background: color-mix(in oklab, var(--accent-soft) 90%, white); }
        .pw-offer-ov span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; opacity: .88; }
        .pw-offer-ov strong { font-size: 14px; line-height: 1.2; }
        .pw-offer-ov small { font-size: 11.5px; line-height: 1.3; opacity: .9; }
      `}</style>
    </div>
  );
};

const OfferDrawer = ({ open, onClose, offer, codes, onSave }) => {
  const blank = {
    code_id: codes[0]?.code_id || "",
    coin_cost: 250,
    max_per_user: 1,
    total_limit: 500,
    valid_from: "2026-06-01",
    valid_until: "2026-12-31",
    status: "active",
    image_url: "",
    image_asset_id: "",
    overlay_title: "",
    overlay_subtitle: "",
    overlay_badge: "",
    overlay_position: "bottom_left",
    overlay_tone: "dark",
  };
  const [f, setF] = React.useState(blank);
  const [uploading, setUploading] = React.useState(false);
  const fileRef = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const prefill = window.__pwOfferPrefillCode || "";
    window.__pwOfferPrefillCode = null;
    setF(offer ? { ...blank, ...offer } : { ...blank, code_id: prefill || blank.code_id });
  }, [open, offer, codes.length]);
  const set = (patch) => setF(prev => ({ ...prev, ...patch }));
  const code = codes.find(c => c.code_id === f.code_id);

  const upload = async (file) => {
    if (!file) return;
    if (!["image/jpeg", "image/png", "image/webp"].includes(file.type)) { window.__toast("Use JPEG, PNG, or WebP", "warn"); return; }
    const localPreview = URL.createObjectURL(file);
    set({ image_url: localPreview });
    if (!window.__api.getConfig().live) return;
    const fd = new FormData();
    fd.append("file", file);
    setUploading(true);
    try {
      const res = await window.__api.call("uploadCouponImage", { body: fd });
      set({ image_asset_id: res.asset_id, image_url: res.image_url });
      window.__toast("Image uploaded", "good");
    } catch (e) {
      window.__toast(e.message || "Image upload failed", "warn");
    } finally {
      setUploading(false);
    }
  };

  return (
    <Drawer open={open} onClose={onClose} title={offer ? "Edit coupon offer" : "New coupon offer"} width={620}
      footer={<><Btn kind="secondary" onClick={onClose}>Cancel</Btn>
        <Btn kind="primary" disabled={!f.code_id || uploading} onClick={() => { onSave(f); onClose(); }}>{offer ? "Save offer" : "Create offer"}</Btn></>}>
      <div className="pw-offer-form">
        <OfferImagePreview offer={f} code={code}/>
        <FieldRow label="Image" hint="Use a hosted URL or upload JPEG, PNG, or WebP." layout="stacked">
          <FieldGroup cols={2}>
            <Input value={f.image_url || ""} onChange={e => set({ image_url: e.target.value, image_asset_id: "" })} placeholder="https://brand.com/offer.jpg"/>
            <div>
              <input ref={fileRef} type="file" accept="image/jpeg,image/png,image/webp" style={{ display: "none" }} onChange={e => upload(e.target.files?.[0])}/>
              <Btn kind="secondary" icon={<IconUpload size={14}/>} disabled={uploading} onClick={() => fileRef.current?.click()} style={{ width: "100%", justifyContent: "center" }}>
                {uploading ? "Uploading..." : "Upload image"}
              </Btn>
            </div>
          </FieldGroup>
        </FieldRow>
        <FieldRow label="Discount code" hint="The assigned brand template this offer reveals." layout="stacked">
          <Select value={f.code_id} onChange={v => set({ code_id: v })} options={codes.map(c => ({ label: `${c.brand} · ${c.name}`, value: c.code_id }))}/>
          {code && <div className="pw-code-summary"><strong>{code.code}</strong><span>{discountSummary(code)}</span></div>}
        </FieldRow>
        <FieldRow label="Overlay" layout="stacked">
          <FieldGroup cols={2}>
            <Input value={f.overlay_title || ""} onChange={e => set({ overlay_title: e.target.value })} placeholder="Title on image"/>
            <Input value={f.overlay_badge || ""} onChange={e => set({ overlay_badge: e.target.value })} placeholder="Badge"/>
          </FieldGroup>
          <Input value={f.overlay_subtitle || ""} onChange={e => set({ overlay_subtitle: e.target.value })} placeholder="Subtitle"/>
          <FieldGroup cols={2}>
            <Select value={f.overlay_position || "bottom_left"} onChange={v => set({ overlay_position: v })} options={overlayPositionOptions}/>
            <Select value={f.overlay_tone || "dark"} onChange={v => set({ overlay_tone: v })} options={overlayToneOptions}/>
          </FieldGroup>
        </FieldRow>
        <FieldRow label="Coin cost"><NumberStepper value={f.coin_cost} onChange={v => set({ coin_cost: v })} min={0} max={100000} step={50} suffix="coins"/></FieldRow>
        <FieldRow label="Limits" layout="stacked">
          <FieldGroup cols={2}>
            <div><label className="pw-lbl">Per user</label><NumberStepper value={f.max_per_user} onChange={v => set({ max_per_user: v })} min={1} max={20}/></div>
            <div><label className="pw-lbl">Total limit</label><NumberStepper value={f.total_limit} onChange={v => set({ total_limit: v })} min={1} max={1000000} step={50}/></div>
          </FieldGroup>
        </FieldRow>
        <FieldRow label="Validity" layout="stacked">
          <FieldGroup cols={2}>
            <div><label className="pw-lbl">From</label><Input type="date" value={String(f.valid_from || "").slice(0, 10)} onChange={e => set({ valid_from: e.target.value })}/></div>
            <div><label className="pw-lbl">Until</label><Input type="date" value={String(f.valid_until || "").slice(0, 10)} onChange={e => set({ valid_until: e.target.value })}/></div>
          </FieldGroup>
        </FieldRow>
        <FieldRow label="Status">
          <SegmentedControl value={f.status} onChange={v => set({ status: v })} options={[{ label: "Active", value: "active" }, { label: "Paused", value: "paused" }]}/>
        </FieldRow>
        <InlineHelp icon={<IconInfo size={13}/>}>Images and overlay text are display metadata. Reveal, wallet, and redemption behavior stays unchanged.</InlineHelp>
      </div>
      <style>{`
        .pw-offer-form { display: flex; flex-direction: column; gap: 14px; }
        .pw-code-summary { margin-top: 8px; display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--panel-2); }
        .pw-code-summary strong { font-family: var(--mono); font-size: 12.5px; color: var(--ink); }
        .pw-code-summary span { font-size: 12.5px; color: var(--muted); }
      `}</style>
    </Drawer>
  );
};

const CouponOffersScreen = ({ data, setData }) => {
  const [drawer, setDrawer] = React.useState(false);
  const [editing, setEditing] = React.useState(null);
  const codeOf = (id) => data.storeDiscountCodes.find(c => c.code_id === id) || {};

  React.useEffect(() => {
    if (window.__pwPrefillCode) {
      window.__pwOfferPrefillCode = window.__pwPrefillCode;
      window.__pwPrefillCode = null;
      setEditing(null);
      setDrawer(true);
    }
  }, []);

  const save = (f) => {
    const body = { ...f, image_url: f.image_url && !String(f.image_url).startsWith("blob:") ? f.image_url : null, image_asset_id: f.image_asset_id || null };
    if (editing) {
      window.__api.write("updateCouponOffer",
        d => ({ ...d, couponOffers: d.couponOffers.map(o => o.offer_id === editing.offer_id ? { ...o, ...body } : o) }),
        { params: { offer_id: editing.offer_id }, body, ok: "Offer updated", err: "Couldn’t update offer" });
    } else {
      const offer_id = "off_" + Math.random().toString(36).slice(2, 7);
      window.__api.write("createCouponOffer",
        d => ({ ...d, couponOffers: [{ ...body, offer_id, claimed_count: 0 }, ...d.couponOffers] }),
        { body, ok: "Offer created", err: "Couldn’t create offer" });
    }
  };

  return (
    <Screen>
      <PageHead icon={IconGift} title="Coupon Offers" subtitle="Tap-to-reveal brand offers your readers unlock with coins."
        actions={<Btn kind="primary" icon={<IconPlus size={15}/>} onClick={() => { setEditing(null); setDrawer(true); }}>New offer</Btn>}/>

      <div className="pw-offer-grid">
        {data.couponOffers.map(o => {
          const c = codeOf(o.code_id);
          const total = Number(o.total_limit || 0);
          const pct = total > 0 ? Math.round((o.claimed_count / total) * 100) : 0;
          return (
            <Card key={o.offer_id}>
              <OfferImagePreview offer={o} code={c} compact/>
              <div className="pw-offer-head">
                <div style={{ minWidth: 0 }}>
                  <div className="pw-offer-brand">{c.brand}</div>
                  <div className="pw-offer-name">{c.name}</div>
                </div>
                <StatusPill status={o.status}/>
              </div>
              <div className="pw-offer-meta"><span className="pw-offer-cost"><IconCoin size={14}/> {fmt.number(o.coin_cost)}</span><span>to reveal</span></div>
              <div style={{ fontSize: 12.5, color: "var(--muted)", margin: "2px 0 14px" }}>{discountSummary(c)}</div>
              <ProgressBar value={o.claimed_count} max={total || Math.max(o.claimed_count, 1)} tone={pct >= 100 ? "warn" : "accent"} label="Claimed" format={(v) => fmt.number(v)}/>
              <div className="pw-offer-foot">
                <span>{fmt.date(o.valid_from)} - {fmt.date(o.valid_until)} · max {o.max_per_user}/user</span>
                <Btn kind="ghost" size="sm" icon={<IconPencil size={13}/>} onClick={() => { setEditing(o); setDrawer(true); }}>Edit</Btn>
              </div>
            </Card>
          );
        })}
      </div>

      <OfferDrawer open={drawer} onClose={() => setDrawer(false)} offer={editing} codes={data.storeDiscountCodes} onSave={save}/>

      <style>{`
        .pw-offer-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); }
        .pw-offer-grid > * { min-width: 0; overflow: hidden; }
        @media (max-width: 1100px) { .pw-offer-grid { grid-template-columns: repeat(2, 1fr); } }
        @media (max-width: 640px) { .pw-offer-grid { grid-template-columns: 1fr; } }
        .pw-offer-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
        .pw-offer-brand { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
        .pw-offer-name { font-size: 15.5px; font-weight: 600; color: var(--ink); margin-top: 2px; }
        .pw-offer-meta { display: flex; align-items: baseline; gap: 6px; margin: 12px 0 2px; color: var(--muted); font-size: 12px; }
        .pw-offer-cost { display: inline-flex; align-items: center; gap: 5px; font-size: 20px; font-weight: 600; font-family: var(--mono); color: var(--ink); }
        .pw-offer-cost svg { color: var(--warn); }
        .pw-offer-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 14px; }
        .pw-offer-foot span { font-size: 11.5px; color: var(--muted); }
      `}</style>
    </Screen>
  );
};

const BrandCodesScreen = ({ data }) => {
  const [q, setQ] = React.useState("");
  const [status, setStatus] = React.useState("all");
  const [brand, setBrand] = React.useState("all");
  const [type, setType] = React.useState("all");
  const brands = Array.from(new Set(data.storeDiscountCodes.map(c => c.brand))).sort();
  const rows = data.storeDiscountCodes.filter(c => {
    const hay = [c.code, c.name, c.brand, discountSummary(c)].join(" ").toLowerCase();
    return (!q || hay.includes(q.toLowerCase()))
      && (status === "all" || c.status === status)
      && (brand === "all" || c.brand === brand)
      && (type === "all" || c.discount_type === type);
  });

  const createOffer = (code_id) => {
    window.__pwPrefillCode = code_id;
    window.__nav("coupon-offers");
  };

  return (
    <Screen>
      <PageHead icon={IconTag} title="Brand Codes" subtitle="Assigned discount codes. Search, filter, and turn active codes into offers." />
      <Toolbar search={q} onSearchChange={setQ} searchPlaceholder="Search brand, code, discount">
        <Select value={status} onChange={setStatus} style={{ width: 150 }} options={[{ label: "All statuses", value: "all" }, { label: "Active", value: "active" }, { label: "Expired", value: "expired" }, { label: "Paused", value: "paused" }]}/>
        <Select value={brand} onChange={setBrand} style={{ width: 190 }} options={[{ label: "All brands", value: "all" }, ...brands.map(b => ({ label: b, value: b }))]}/>
        <Select value={type} onChange={setType} style={{ width: 150 }} options={[{ label: "All types", value: "all" }, { label: "Percent", value: "percent" }, { label: "Flat", value: "flat" }]}/>
      </Toolbar>

      <Card padded={false}>
        <DataTable rows={rows} keyField="code_id" rowsPerPage={8} defaultSort={{ key: "brand", dir: "asc" }}
          empty={<EmptyState icon={<IconTag size={30}/>} title="No brand codes" description="No assigned codes match your filters."/>}
          columns={[
            { key: "brand", label: "Brand", render: r => <strong style={{ color: "var(--ink)" }}>{r.brand}</strong> },
            { key: "code", label: "Code", render: r => <span style={{ fontFamily: "var(--mono)", fontSize: 12.5, color: "var(--ink)" }}>{r.code}</span> },
            { key: "name", label: "Name" },
            { key: "discount", label: "Discount", sortable: false, render: r => <span style={{ fontSize: 12.5 }}>{discountSummary(r)}</span> },
            { key: "valid_until", label: "Validity", align: "right", render: r => <span style={{ fontFamily: "var(--mono)", fontSize: 12 }}>{fmt.date(r.valid_from)} - {fmt.date(r.valid_until)}</span> },
            { key: "status", label: "Status", render: r => <StatusPill status={r.status}/> },
            { key: "_cta", label: "", sortable: false, align: "right", render: r => (
              <Btn kind="secondary" size="sm" icon={<IconGift size={13}/>} disabled={r.status !== "active"} onClick={() => createOffer(r.code_id)}>Create offer</Btn>) },
          ]}/>
      </Card>
    </Screen>
  );
};

Object.assign(window, { CouponOffersScreen, BrandCodesScreen, OfferDrawer, discountSummary, OfferImagePreview });
