/* KitRate — brand-specific share links with live (prototype) open tracking.
   Each link is the same kit served at /k/slug/brand with a private
   pitch line and per-brand analytics. v2 data model: every open is an
   event { ts, dwellRates, source } — opens/last-viewed/dwell are derived.
   Opening the brand preview in this prototype logs a real tracked event. */

const KR_BRANDLINKS_KEY = "kitrate.brandlinks.v3";
const KR_BRANDLINKS_KEY_V2 = "kitrate.brandlinks.v2";
const KR_BRANDLINKS_KEY_V1 = "kitrate.brandlinks.v1";

const krDaysAgo = (d, hour = 14) => {
  const t = new Date(); t.setDate(t.getDate() - d); t.setHours(hour, 12 + d * 7 % 40, 0, 0);
  return t.getTime();
};

function krBrandLinksSeed() {
  return [
    {
      id: "bl1", brand: "Haymaker Supply Co.",
      note: "Spring-launch numbers are in Proof in motion — built this view for your Q3 planning.",
      created: "2026-06-04",
      events: [
        { ts: krDaysAgo(9, 10), dwellRates: 22, source: "link" },
        { ts: krDaysAgo(5, 15), dwellRates: 35, source: "link" },
        { ts: krDaysAgo(2, 9), dwellRates: 63, source: "link" }
      ]
    },
    {
      id: "bl2", brand: "Ridgeline Nutrition", note: "", created: "2026-06-06",
      events: [{ ts: krDaysAgo(4, 11), dwellRates: 12, source: "link" }]
    }
  ];
}

/* migrate v1 records (static opens/lastOpened/ratesDwell) into events */
function krMigrateV1(old) {
  return old.map(l => {
    if (l.events) return l;
    const opens = l.opens || 0;
    const dwell = parseInt(l.ratesDwell, 10) || 0;
    const events = [];
    for (let i = 0; i < opens; i++) {
      events.push({ ts: krDaysAgo((opens - 1 - i) * 3 + 2), dwellRates: i === opens - 1 ? dwell : Math.max(5, Math.round(dwell * 0.6)), source: "link" });
    }
    return { id: l.id, brand: l.brand, note: l.note || "", created: l.created, events };
  });
}

function loadBrandLinks() {
  try {
    const raw = localStorage.getItem(KR_BRANDLINKS_KEY);
    if (raw) return JSON.parse(raw);
    const v2 = localStorage.getItem(KR_BRANDLINKS_KEY_V2);
    if (v2) {
      const migrated = JSON.parse(v2).filter((link) => !["bl1", "bl2"].includes(link.id));
      saveBrandLinks(migrated);
      return migrated;
    }
    const v1 = localStorage.getItem(KR_BRANDLINKS_KEY_V1);
    if (v1) { const migrated = krMigrateV1(JSON.parse(v1)); saveBrandLinks(migrated); return migrated; }
  } catch (e) {}
  const seed = [];
  saveBrandLinks(seed);
  return seed;
}
function saveBrandLinks(links) { localStorage.setItem(KR_BRANDLINKS_KEY, JSON.stringify(links)); }
function brandSlug(s) { return (s || "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, ""); }

/* ---------- live tracking API (called from the brand share view) ---------- */
function recordBrandOpen(linkId) {
  const links = loadBrandLinks();
  const link = links.find(l => l.id === linkId);
  if (!link) return null;
  const ev = { ts: Date.now(), dwellRates: 0, source: "preview" };
  link.events = [...(link.events || []), ev];
  saveBrandLinks(links);
  return ev.ts; // event id = its timestamp
}
function updateBrandDwell(linkId, eventTs, seconds) {
  const links = loadBrandLinks();
  const link = links.find(l => l.id === linkId);
  if (!link) return;
  const ev = (link.events || []).find(e => e.ts === eventTs);
  if (!ev) return;
  ev.dwellRates = Math.max(ev.dwellRates || 0, Math.round(seconds));
  saveBrandLinks(links);
}

/* ---------- derived stats & formatting ---------- */
function linkStats(link) {
  const events = (link.events || []).slice().sort((a, b) => a.ts - b.ts);
  const last = events[events.length - 1] || null;
  const weekAgo = Date.now() - 7 * 864e5;
  return {
    opens: events.length,
    last,
    opensThisWeek: events.filter(e => e.ts >= weekAgo).length,
    totalDwell: events.reduce((s, e) => s + (e.dwellRates || 0), 0)
  };
}
function fmtDwell(s) {
  if (!s || s < 1) return "<1s";
  if (s < 60) return Math.round(s) + "s";
  return Math.floor(s / 60) + "m " + String(Math.round(s % 60)).padStart(2, "0") + "s";
}
function fmtDay(ts) { return new Date(ts).toLocaleDateString("en-US", { month: "short", day: "numeric" }); }
function fmtTime(ts) { return new Date(ts).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }); }
function fmtRelative(ts) {
  const days = Math.floor((Date.now() - ts) / 864e5);
  if (days <= 0) return "today";
  if (days === 1) return "yesterday";
  return days + "d ago";
}

/* ---------- 14-day activity strip ---------- */
function ActivityStrip({ events }) {
  const days = [];
  for (let i = 13; i >= 0; i--) {
    const start = new Date(); start.setHours(0, 0, 0, 0); start.setDate(start.getDate() - i);
    const end = start.getTime() + 864e5;
    days.push((events || []).filter(e => e.ts >= start.getTime() && e.ts < end).length);
  }
  const max = Math.max(1, ...days);
  return (
    <div style={{ display: "flex", alignItems: "flex-end", gap: 3 }} title="Opens, last 14 days" aria-label="Opens over the last 14 days">
      {days.map((n, i) => (
        <span key={i} style={{
          width: 5, borderRadius: 1.5,
          height: n === 0 ? 3 : 5 + Math.round((n / max) * 11),
          background: n === 0 ? "var(--line)" : "var(--accent)",
          opacity: n === 0 ? 1 : 0.45 + 0.55 * (n / max)
        }}></span>
      ))}
      <span style={{ fontFamily: "var(--mono)", fontSize: 9, letterSpacing: "0.08em", color: "var(--muted)", marginLeft: 5 }}>14D</span>
    </div>
  );
}

function LinkStatusChip({ stats }) {
  if (stats.opens === 0) return <span className="kr-chip" style={{ fontSize: 9.5 }}>Not opened</span>;
  const days = (Date.now() - stats.last.ts) / 864e5;
  if (days <= 3) return <span className="kr-chip kr-chip-good" style={{ fontSize: 9.5 }}>● Hot</span>;
  return <span className="kr-chip kr-chip-accent" style={{ fontSize: 9.5 }}>Viewed</span>;
}

/* ---------- per-link row ---------- */
function BrandLinkRow({ link, baseUrl, onChange, onDelete, onPreview, onPublish, toast }) {
  const [logOpen, setLogOpen] = useState(false);
  const url = baseUrl + "/" + brandSlug(link.brand);
  const stats = linkStats(link);
  const events = (link.events || []).slice().sort((a, b) => b.ts - a.ts);
  return (
    <div style={{ borderTop: "1px solid var(--line)", padding: "12px 0" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
            <span style={{ fontWeight: 600, fontSize: 13.5 }}>{link.brand}</span>
            <LinkStatusChip stats={stats} />
          </div>
          <div style={{ fontFamily: "var(--mono)", fontSize: 11, color: "var(--muted)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", marginTop: 2 }}>{url.replace(/^https?:\/\//, "")}</div>
        </div>
        <button className="kr-btn kr-btn-secondary kr-btn-sm" onClick={async () => {
          try {
            const publishedUrl = await onPublish(link);
            await navigator.clipboard.writeText(publishedUrl);
            toast("Brand link copied");
          } catch (error) {
            toast(error.message || "Could not publish this link");
          }
        }} aria-label={"Publish and copy link for " + link.brand} title="Publish and copy link"><KrIcon d={ICONS.link} size={13} /></button>
        <button className="kr-btn kr-btn-secondary kr-btn-sm" onClick={() => onPreview(link)} aria-label={"Preview link for " + link.brand} title="Open as this brand — logs a tracked open"><KrIcon d={ICONS.eye} size={13} /></button>
        <button className="kr-btn kr-btn-ghost kr-btn-sm" onClick={onDelete} aria-label={"Delete link for " + link.brand}><KrIcon d={ICONS.x} size={13} /></button>
      </div>

      {/* analytics line */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 9, flexWrap: "wrap" }}>
        <ActivityStrip events={link.events} />
        <button onClick={() => setLogOpen(!logOpen)} disabled={stats.opens === 0} style={{
          background: "none", border: "none", padding: 0,
          fontFamily: "var(--mono)", fontSize: 10.5, letterSpacing: "0.04em",
          color: stats.opens > 0 ? "var(--accent)" : "var(--muted)",
          cursor: stats.opens > 0 ? "pointer" : "default", textAlign: "left"
        }}>
          {stats.opens > 0
            ? stats.opens + (stats.opens === 1 ? " open" : " opens") + " · last " + fmtRelative(stats.last.ts) + " · " + fmtDwell(stats.last.dwellRates) + " on rate card " + (logOpen ? "▾" : "▸")
            : "No opens yet — tracking starts when the brand first views it"}
        </button>
      </div>

      {/* expandable open log */}
      {logOpen && stats.opens > 0 && (
        <div className="kr-fade-in" style={{ margin: "8px 0 2px", border: "1px solid var(--line)", borderRadius: 8, background: "var(--surface-2)", padding: "4px 12px" }}>
          {events.map((e) => (
            <div key={e.ts} style={{ display: "flex", alignItems: "baseline", gap: 10, padding: "6px 0", borderBottom: "1px solid var(--line)", fontSize: 11.5 }}>
              <span style={{ fontFamily: "var(--mono)", fontSize: 10.5, color: "var(--ink-2)", whiteSpace: "nowrap" }}>{fmtDay(e.ts)} · {fmtTime(e.ts)}</span>
              <span style={{ flex: 1, color: "var(--ink-2)" }}>Opened the kit{e.dwellRates ? " — " + fmtDwell(e.dwellRates) + " on the rate card" : ""}</span>
              {e.source === "preview" && <span style={{ fontFamily: "var(--mono)", fontSize: 9.5, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--muted)" }}>your preview</span>}
            </div>
          ))}
          <div style={{ padding: "6px 0", fontFamily: "var(--mono)", fontSize: 9.5, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--muted)" }}>
            Total rate-card dwell {fmtDwell(stats.totalDwell)}
          </div>
        </div>
      )}

      <input className="kr-input" value={link.note} placeholder="Private pitch line shown only on this brand's view…"
        onChange={(e) => onChange({ ...link, note: e.target.value })}
        style={{ marginTop: 8, fontSize: 12.5, padding: "7px 10px" }} />
    </div>
  );
}

/* ---------- panel ---------- */
function BrandLinksPanel({ baseUrl, toast, onPreview, onPublish }) {
  const [links, setLinks] = useState(loadBrandLinks);
  const [draft, setDraft] = useState("");
  const update = (next) => { setLinks(next); saveBrandLinks(next); };

  /* re-read when the tab regains focus — opens logged from the brand view land here */
  useEffect(() => {
    const refresh = () => setLinks(loadBrandLinks());
    window.addEventListener("focus", refresh);
    return () => window.removeEventListener("focus", refresh);
  }, []);

  const add = () => {
    const brand = draft.trim();
    if (!brand) return;
    if (links.some(l => brandSlug(l.brand) === brandSlug(brand))) { toast("A link for " + brand + " already exists"); return; }
    update([{ id: "bl" + Date.now(), brand, note: "", created: new Date().toISOString().slice(0, 10), events: [] }, ...links]);
    setDraft("");
    toast("Link created for " + brand);
  };

  const totals = links.reduce((t, l) => {
    const s = linkStats(l);
    t.opens += s.opens; t.week += s.opensThisWeek;
    return t;
  }, { opens: 0, week: 0 });

  return (
    <div>
      <div style={{ display: "flex", alignItems: "baseline", gap: 10, marginBottom: 2 }}>
        <div style={{ fontWeight: 600, fontSize: 13.5 }}>Brand-specific links</div>
        {totals.opens > 0 && (
          <span style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--muted)" }}>
            {totals.opens} {totals.opens === 1 ? "open" : "opens"} all-time · {totals.week} this week
          </span>
        )}
      </div>
      <p style={{ fontSize: 12, color: "var(--muted)", marginBottom: 10 }}>Same kit, addressed to one brand — with a private pitch line and per-brand open tracking.</p>
      <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
        <input className="kr-input" value={draft} placeholder="Brand name, e.g. Nike" onKeyDown={(e) => { if (e.key === "Enter") add(); }} onChange={(e) => setDraft(e.target.value)} />
        <button className="kr-btn kr-btn-primary kr-btn-sm" onClick={add} disabled={!draft.trim()}><KrIcon d={ICONS.plus} size={13} /> Create</button>
      </div>
      {links.map(l => (
        <BrandLinkRow key={l.id} link={l} baseUrl={baseUrl} toast={toast} onPreview={onPreview} onPublish={onPublish}
          onChange={(nl) => update(links.map(x => x.id === nl.id ? nl : x))}
          onDelete={() => update(links.filter(x => x.id !== l.id))} />
      ))}
      {links.length === 0 && <p style={{ fontSize: 12.5, color: "var(--muted)", padding: "10px 0", borderTop: "1px solid var(--line)" }}>No brand links yet.</p>}
      <IntegrationNote>
        Published visits are recorded on the server with a privacy-preserving visitor hash and rate-card dwell time. Your editor preview stays local and is not counted as a public visit.
      </IntegrationNote>
    </div>
  );
}

Object.assign(window, { BrandLinksPanel, loadBrandLinks, brandSlug, recordBrandOpen, updateBrandDwell, linkStats });
