/* ============================================================
   Activity log — tamper-evident record of who did what, when.
   CEOs see everything; employees see only entries that involve them.
   Rows are written server-side by database triggers (see
   supabase-schema.sql) and can't be edited or deleted from the app.
   ============================================================ */
const { useState, useEffect } = React;

/* ---- helpers ---- */
function logPersonName(id, fallbackEmail) {
  const p = id && VP_DATA.byId[id];
  if (p) return `${p.first} ${p.last}`.trim() || p.email;
  return fallbackEmail || "A former teammate";
}
function logRelTime(iso) {
  const then = new Date(iso);
  const s = Math.round((Date.now() - then.getTime()) / 1000);
  if (s < 45) return "just now";
  const m = Math.round(s / 60);
  if (m < 60) return `${m}m ago`;
  const h = Math.round(m / 60);
  if (h < 24) return `${h}h ago`;
  const d = Math.round(h / 24);
  if (d < 7) return `${d}d ago`;
  return then.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" });
}
function logAbsTime(iso) {
  return new Date(iso).toLocaleString("en-GB", {
    day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit",
  });
}
const FIELD_LABELS = {
  first: "First name", last: "Last name", role: "Role", team: "Team",
  allowance: "Allowance", weekly_hours: "Weekly hours", workdays: "Workdays", start_date: "Start date",
  type: "Type", from: "Start", to: "End", replacement: "Replacement", note: "Note",
  title: "Title", assignee: "Assignee", priority: "Priority", due: "Due date", start: "Start date",
};
const WD = { 1: "Mon", 2: "Tue", 3: "Wed", 4: "Thu", 5: "Fri", 6: "Sat", 0: "Sun" };
function fmtFieldValue(field, v) {
  if (v === null || v === undefined || v === "") return "—";
  if (field === "workdays" && Array.isArray(v)) return v.map((d) => WD[d] || d).join(", ");
  if (field === "type" && VP_DATA.leaveTypes[v]) return VP_DATA.leaveTypes[v].label;
  if (field === "replacement") return logPersonName(v);
  if (field === "from" || field === "to" || field === "start_date") {
    try { return fmtDateLong(v); } catch (e) { return String(v); }
  }
  return String(v);
}

const ACTION_META = {
  "request.submitted": { icon: "inbox", tone: "pending",  verb: "submitted a leave request" },
  "request.approved":  { icon: "check", tone: "approved", verb: "approved a leave request" },
  "request.declined":  { icon: "x",     tone: "declined", verb: "declined a leave request" },
  "request.reopened":  { icon: "swap",  tone: "pending",  verb: "reopened a leave request" },
  "request.updated":   { icon: "clock", tone: "default",  verb: "edited a leave request" },
  "request.deleted":   { icon: "x",     tone: "declined", verb: "deleted a leave request" },
  "profile.created":   { icon: "users", tone: "approved", verb: "joined the team" },
  "profile.updated":   { icon: "users", tone: "default",  verb: "updated a profile" },
  "profile.deleted":   { icon: "x",     tone: "declined", verb: "removed a teammate" },
  "task.created":      { icon: "plus",  tone: "default",  verb: "created a task" },
  "task.moved":        { icon: "swap",  tone: "default",  verb: "moved a task" },
  "task.updated":      { icon: "clock", tone: "default",  verb: "edited a task" },
  "task.deleted":      { icon: "x",     tone: "declined", verb: "deleted a task" },
  "project.created":   { icon: "plus",  tone: "approved", verb: "created a project" },
  "project.deleted":   { icon: "x",     tone: "declined", verb: "deleted a project" },
};
const TASK_STATUS_LABELS = { todo: "To Do", in_progress: "In Progress", blocked: "Blocked", done: "Done" };
const TONE_COLOR = {
  approved: "var(--st-approved)",
  declined: "var(--st-declined)",
  pending:  "var(--st-pending)",
  default:  "var(--ink-3)",
};

/* ---- one row ---- */
function ActivityRow({ entry, viewerIsCeo, last }) {
  const meta = ACTION_META[entry.action] || { icon: "dot", tone: "default", verb: entry.action };
  const color = TONE_COLOR[meta.tone] || "var(--ink-3)";
  const d = entry.details || {};
  const actorName = logPersonName(entry.actor, entry.actorEmail) || "System";
  const subjectName = logPersonName(entry.subject, d.email || d.name);
  const isRequest = entry.entity === "leave_request";
  const isTask = entry.entity === "task";
  const isProject = entry.entity === "project";
  const isSelfActor = entry.actor && entry.subject && entry.actor === entry.subject;

  // headline
  let headline;
  if (entry.action === "profile.created") {
    headline = <><strong>{subjectName}</strong> joined the team</>;
  } else if (isRequest) {
    const who = isSelfActor
      ? <strong>{actorName}</strong>
      : <><strong>{actorName}</strong> · {subjectName}’s request</>;
    headline = <>{who} — {meta.verb.replace("a leave request", "request")}</>;
  } else if (isTask || isProject) {
    headline = <><strong>{actorName}</strong> {meta.verb}</>;
  } else {
    // profile.updated / profile.deleted
    const obj = isSelfActor ? "their own profile" : <><strong>{subjectName}</strong>’s profile</>;
    headline = entry.action === "profile.deleted"
      ? <><strong>{actorName}</strong> removed <strong>{subjectName}</strong></>
      : <><strong>{actorName}</strong> updated {obj}</>;
  }

  // detail line
  let detail = null;
  if (isRequest) {
    detail = (
      <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginTop: 7 }}>
        {d.type && VP_DATA.leaveTypes[d.type] && <TypeTag type={d.type} size="sm" />}
        {d.from && <span style={{ fontSize: 12.5, color: "var(--ink-3)", fontWeight: 600 }}>{fmtRange(d.from, d.to || d.from)}</span>}
        {entry.action === "request.declined" && d.reason &&
          <span style={{ fontSize: 12.5, color: "var(--ink-3)" }}>· “{d.reason}”</span>}
      </div>
    );
  } else if (isTask) {
    detail = (
      <div style={{ display: "flex", flexDirection: "column", gap: 4, marginTop: 7 }}>
        <div style={{ fontSize: 13, color: "var(--ink-2)" }}>
          {d.title && <span style={{ fontWeight: 600 }}>“{d.title}”</span>}
          {d.project && <span style={{ color: "var(--ink-4)" }}> · {d.project}</span>}
        </div>
        {entry.action === "task.moved" && (
          <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>
            {TASK_STATUS_LABELS[d.old_status] || d.old_status} <span style={{ color: "var(--ink-4)" }}>→</span> {TASK_STATUS_LABELS[d.status] || d.status}
          </div>
        )}
        {entry.action === "task.updated" && d.changed && typeof d.changed === "object" && (
          <div style={{ fontSize: 12.5, color: "var(--ink-3)" }}>{Object.keys(d.changed).map((f) => FIELD_LABELS[f] || f).join(", ")} changed</div>
        )}
      </div>
    );
  } else if (isProject) {
    detail = d.name ? <div style={{ fontSize: 13, color: "var(--ink-2)", marginTop: 7 }}><span style={{ fontWeight: 600 }}>{d.name}</span>{d.kind && <span style={{ color: "var(--ink-4)" }}> · {d.kind}</span>}</div> : null;
  } else if (d.changed && typeof d.changed === "object") {
    const fields = Object.keys(d.changed);
    detail = (
      <div style={{ display: "flex", flexDirection: "column", gap: 3, marginTop: 7 }}>
        {fields.map((f) => {
          const pair = d.changed[f] || [];
          // sensitive fields stay coarse for non-CEO viewers
          return (
            <div key={f} style={{ fontSize: 12.5, color: "var(--ink-3)" }}>
              <span style={{ fontWeight: 600, color: "var(--ink-2)" }}>{FIELD_LABELS[f] || f}:</span>{" "}
              {fmtFieldValue(f, pair[0])} <span style={{ color: "var(--ink-4)" }}>→</span> {fmtFieldValue(f, pair[1])}
            </div>
          );
        })}
      </div>
    );
  }

  return (
    <div style={{ display: "flex", gap: 14, padding: "16px 0", borderBottom: last ? "none" : "1px solid var(--line)" }}>
      <div style={{ position: "relative", flex: "0 0 auto" }}>
        <div style={{
          width: 34, height: 34, borderRadius: "50%", display: "grid", placeItems: "center",
          background: `color-mix(in srgb, ${color} 12%, var(--surface))`, color,
        }}>
          <Icon name={meta.icon} size={17} stroke={2} />
        </div>
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: "flex", justifyContent: "space-between", gap: 12, alignItems: "baseline" }}>
          <div style={{ fontSize: 14.5, color: "var(--ink)", lineHeight: 1.45 }}>{headline}</div>
          <span title={logAbsTime(entry.at)} style={{ fontSize: 12, color: "var(--ink-4)", whiteSpace: "nowrap", flex: "0 0 auto" }}>
            {logRelTime(entry.at)}
          </span>
        </div>
        {detail}
      </div>
    </div>
  );
}

/* ---- screen ---- */
function ActivityLog({ user }) {
  const isCeo = user.role === "ceo";
  const [phase, setPhase] = useState("loading"); // loading | ready | error
  const [rows, setRows] = useState([]);
  const [err, setErr] = useState("");
  const [filter, setFilter] = useState("all"); // all | leave_request | profile

  async function load() {
    setPhase("loading"); setErr("");
    try {
      const data = await MesperDB.loadAuditLog({ limit: 300 });
      setRows(data);
      setPhase("ready");
    } catch (e) {
      setErr((e && e.message) || "Could not load the activity log.");
      setPhase("error");
    }
  }
  useEffect(() => { load(); }, []);

  const filtered = rows.filter((r) =>
    filter === "all" ? true
    : filter === "tasks" ? (r.entity === "task" || r.entity === "project")
    : r.entity === filter);

  const FILTERS = [
    { id: "all", label: "All" },
    { id: "leave_request", label: "Leave" },
    { id: "tasks", label: "Tasks" },
    { id: "profile", label: "People" },
  ];

  return (
    <div className="vp-fade-up">
      {/* header */}
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 16, flexWrap: "wrap", marginBottom: 6 }}>
        <div>
          <Eyebrow>Audit log</Eyebrow>
          <h1 style={{ fontSize: 26, margin: "6px 0 4px" }}>Activity</h1>
          <p style={{ color: "var(--ink-3)", fontSize: 14.5, margin: 0, maxWidth: 560, lineHeight: 1.5 }}>
            {isCeo
              ? "Every request decision and profile change across the team, in order. Entries are written by the database and can’t be edited or removed."
              : "A record of everything that involves you — your requests and any changes to your profile. Written by the system, so it can be relied on as proof."}
          </p>
        </div>
        <Button variant="outline" size="sm" icon="swap" onClick={load} disabled={phase === "loading"}>Refresh</Button>
      </div>

      {/* filters */}
      <div style={{ display: "flex", gap: 7, margin: "18px 0 14px", flexWrap: "wrap" }}>
        {FILTERS.map((f) => {
          const on = filter === f.id;
          return (
            <button key={f.id} type="button" onClick={() => setFilter(f.id)} className="vp-focusable"
              style={{
                padding: "6px 13px", borderRadius: "var(--r-pill)", cursor: "pointer",
                fontSize: 13, fontWeight: 600, transition: "all .14s ease",
                border: `1px solid ${on ? "transparent" : "var(--line-2)"}`,
                background: on ? "var(--accent-soft)" : "var(--surface)",
                color: on ? "var(--accent-ink)" : "var(--ink-3)",
                boxShadow: on ? "inset 0 0 0 1px var(--accent)" : "none",
              }}>{f.label}</button>
          );
        })}
      </div>

      <Card pad="6px 22px">
        {phase === "loading" && (
          <p style={{ color: "var(--ink-4)", fontSize: 14, padding: "26px 0", textAlign: "center" }}>Loading activity…</p>
        )}
        {phase === "error" && (
          <div style={{ padding: "24px 0", textAlign: "center" }}>
            <p style={{ color: "var(--st-declined)", fontSize: 14, marginBottom: 12 }}>{err}</p>
            <Button variant="outline" size="sm" onClick={load}>Try again</Button>
          </div>
        )}
        {phase === "ready" && filtered.length === 0 && (
          <p style={{ color: "var(--ink-4)", fontSize: 14, padding: "26px 0", textAlign: "center" }}>Nothing logged yet.</p>
        )}
        {phase === "ready" && filtered.map((entry, i) => (
          <ActivityRow key={entry.id} entry={entry} viewerIsCeo={isCeo} last={i === filtered.length - 1} />
        ))}
      </Card>
    </div>
  );
}

Object.assign(window, { ActivityLog });
