/* =========================================================
   Tickets — the follow-ups the agent promised on a call
   =========================================================
   Every row here was raised on a live call: either the agent ran
   create_ticket for something it could not resolve, or the promise-keeper
   noticed it committed to something no action ever satisfied.

   These rows have existed since migration 019 and were written faithfully
   the whole time — there was just never a route or a screen, so callers
   were told "I've logged that for you" and nobody could ever see it. This
   page is the other half of that promise.

   Endpoints:
     GET   /tickets?status=&priority=      -> { tickets, counts, open_total }
     PATCH /tickets/{id}  { status, priority, assignee, note }
   ========================================================= */

const TICKET_STATUS_TABS = [
  { key: "open", label: "Needs action" },
  { key: "resolved", label: "Resolved" },
  { key: "closed", label: "Closed" },
  { key: "", label: "All" },
];

const TICKET_PRIORITY_STYLE = {
  high: { bg: "rgba(220,38,38,.10)", fg: "#b91c1c", label: "High" },
  medium: { bg: "rgba(217,119,6,.10)", fg: "#b45309", label: "Medium" },
  low: { bg: "rgba(100,116,139,.12)", fg: "#475569", label: "Low" },
};

const TICKET_STATUS_LABEL = {
  open: "Open",
  in_progress: "In progress",
  resolved: "Resolved",
  closed: "Closed",
};

function ticketAgo(iso) {
  if (!iso) return "";
  const then = new Date(iso).getTime();
  if (!Number.isFinite(then)) return "";
  const mins = Math.floor((Date.now() - then) / 60000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  const days = Math.floor(hrs / 24);
  return days === 1 ? "yesterday" : `${days}d ago`;
}

const TicketPriorityPill = ({ priority }) => {
  const s = TICKET_PRIORITY_STYLE[priority] || TICKET_PRIORITY_STYLE.low;
  return (
    <span
      style={{
        background: s.bg, color: s.fg, borderRadius: 999, padding: "2px 10px",
        fontSize: 12, fontWeight: 600, whiteSpace: "nowrap",
      }}
    >
      {s.label}
    </span>
  );
};

const TicketCard = ({ ticket, onPatch, busy, onGo }) => {
  const [open, setOpen] = useState(false);
  const [note, setNote] = useState("");
  const [assignee, setAssignee] = useState((ticket.metadata || {}).assignee || "");
  const meta = ticket.metadata || {};
  const done = ticket.status === "resolved" || ticket.status === "closed";
  const notes = Array.isArray(meta.notes) ? meta.notes : [];

  return (
    <div className="card" style={{ padding: 16, marginBottom: 12, opacity: busy ? 0.6 : 1 }}>
      <div className="row gap-2" style={{ justifyContent: "space-between", alignItems: "flex-start" }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div className="row gap-2" style={{ alignItems: "center", flexWrap: "wrap" }}>
            <TicketPriorityPill priority={ticket.priority} />
            <strong style={{ fontSize: 15 }}>{ticket.subject}</strong>
          </div>
          <div className="muted" style={{ fontSize: 13, marginTop: 6 }}>
            {TICKET_STATUS_LABEL[ticket.status] || ticket.status}
            {ticket.category ? ` · ${ticket.category}` : ""}
            {" · raised "}{ticketAgo(ticket.created_at)}
            {meta.assignee ? ` · ${meta.assignee}` : ""}
          </div>
        </div>
        <button className="btn btn-outline btn-sm" onClick={() => setOpen(!open)}>
          {open ? "Hide" : "Open"}
        </button>
      </div>

      {open && (
        <div style={{ marginTop: 14, borderTop: "1px solid var(--line, #e5e7eb)", paddingTop: 14 }}>
          <p style={{ whiteSpace: "pre-wrap", fontSize: 14, marginBottom: 12 }}>{ticket.description}</p>

          {(ticket.caller_name || ticket.caller_phone) && (
            <div className="muted" style={{ fontSize: 13, marginBottom: 10 }}>
              Caller: {ticket.caller_name || "Unknown"}
              {ticket.caller_phone ? ` · ${ticket.caller_phone}` : ""}
            </div>
          )}

          {ticket.call_id && onGo && (
            <button
              className="btn btn-outline btn-sm"
              style={{ marginBottom: 12 }}
              onClick={() => onGo("call-detail", { callId: ticket.call_id })}
            >
              View the call
            </button>
          )}

          {notes.length > 0 && (
            <div style={{ marginBottom: 12 }}>
              {notes.map((n, i) => (
                <div key={i} className="muted" style={{ fontSize: 13, marginBottom: 4 }}>
                  <strong>{n.by}</strong> · {ticketAgo(n.at)} — {n.text}
                </div>
              ))}
            </div>
          )}

          <div className="row gap-2" style={{ flexWrap: "wrap", marginBottom: 10 }}>
            <input
              className="input"
              placeholder="Assign to (name or email)"
              value={assignee}
              onChange={(e) => setAssignee(e.target.value)}
              style={{ maxWidth: 260 }}
            />
            <select
              className="input"
              value={ticket.priority}
              onChange={(e) => onPatch(ticket.id, { priority: e.target.value })}
              style={{ maxWidth: 140 }}
            >
              <option value="high">High</option>
              <option value="medium">Medium</option>
              <option value="low">Low</option>
            </select>
          </div>

          <textarea
            className="input"
            placeholder="Add a note (what you did, what's next)"
            value={note}
            onChange={(e) => setNote(e.target.value)}
            rows={2}
            style={{ width: "100%", marginBottom: 10 }}
          />

          <div className="row gap-2" style={{ flexWrap: "wrap" }}>
            <button
              className="btn btn-outline btn-sm"
              disabled={busy}
              onClick={() => {
                const patch = {};
                if (note.trim()) patch.note = note.trim();
                if (assignee !== (meta.assignee || "")) patch.assignee = assignee;
                if (!Object.keys(patch).length) return;
                onPatch(ticket.id, patch).then(() => setNote(""));
              }}
            >
              Save
            </button>
            {!done && ticket.status !== "in_progress" && (
              <button
                className="btn btn-outline btn-sm"
                disabled={busy}
                onClick={() => onPatch(ticket.id, { status: "in_progress" })}
              >
                I'm on it
              </button>
            )}
            {!done && (
              <button
                className="btn btn-primary btn-sm"
                disabled={busy}
                onClick={() => onPatch(ticket.id, { status: "resolved", note: note.trim() || undefined })}
              >
                Mark resolved
              </button>
            )}
            {done && (
              <button
                className="btn btn-outline btn-sm"
                disabled={busy}
                onClick={() => onPatch(ticket.id, { status: "open" })}
              >
                Reopen
              </button>
            )}
          </div>
        </div>
      )}
    </div>
  );
};

const TicketsPage = ({ onGo }) => {
  const [tab, setTab] = useState("open");
  const [data, setData] = useState({ tickets: [], counts: {}, open_total: 0 });
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState("");
  const [busyId, setBusyId] = useState(null);

  const load = async (statusKey) => {
    setLoading(true);
    setErr("");
    try {
      const qs = statusKey ? `?status=${encodeURIComponent(statusKey)}` : "";
      const res = await apiRequest(`/tickets${qs}`);
      setData(res || { tickets: [], counts: {}, open_total: 0 });
    } catch (e) {
      setErr(e?.message || "Could not load tickets.");
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => { load(tab); }, [tab]);

  const patch = async (id, body) => {
    setBusyId(id);
    try {
      await apiRequest(`/tickets/${id}`, { method: "PATCH", body: JSON.stringify(body) });
      await load(tab);
    } catch (e) {
      setErr(e?.message || "Could not update the ticket.");
    } finally {
      setBusyId(null);
    }
  };

  const tickets = data.tickets || [];

  return (
    <div className="page page-mount">
      <div className="page-header" style={{ marginBottom: 26 }}>
        <div>
          <h1 className="page-title display" style={{ fontWeight: 600 }}>Tickets</h1>
          <p className="page-sub">
            Follow-ups your agent promised on a call. Every one of these was raised because
            something could not be finished while the caller was on the line.
          </p>
        </div>
      </div>

      <div className="intel-view" style={{ maxWidth: 1020 }}>
        <div className="row gap-2" style={{ marginBottom: 18, flexWrap: "wrap" }}>
          {TICKET_STATUS_TABS.map((t) => {
            const count = t.key === "open"
              ? (data.open_total || 0)
              : (t.key ? (data.counts || {})[t.key] : null);
            return (
              <button
                key={t.key || "all"}
                className={`btn btn-sm ${tab === t.key ? "btn-primary" : "btn-outline"}`}
                onClick={() => setTab(t.key)}
              >
                {t.label}{count ? ` (${count})` : ""}
              </button>
            );
          })}
        </div>

        {err && <div className="card" style={{ padding: 14, marginBottom: 12, color: "#b91c1c" }}>{err}</div>}

        {loading && <div className="muted" style={{ padding: 12 }}>Loading…</div>}

        {!loading && !tickets.length && (
          <div className="card" style={{ padding: 24, textAlign: "center" }}>
            <strong style={{ display: "block", marginBottom: 6 }}>
              {tab === "open" ? "Nothing waiting on a human" : "Nothing here"}
            </strong>
            <span className="muted" style={{ fontSize: 14 }}>
              {tab === "open"
                ? "When the agent can't finish something on a call, it lands here."
                : "Try another tab."}
            </span>
          </div>
        )}

        {!loading && tickets.map((t) => (
          <TicketCard
            key={t.id}
            ticket={t}
            onPatch={patch}
            busy={busyId === t.id}
            onGo={onGo}
          />
        ))}
      </div>
    </div>
  );
};

Object.assign(window, { TicketsPage });
