"use client";

import Link from "next/link";
import { useParams } from "next/navigation";
import { useState } from "react";
import { ArrowLeft } from "lucide-react";
import { Button, ConfirmDialog, Field, Panel, Select, Skeleton, Textarea } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { api, ApiError } from "@/lib/api";
import { formatDateTime } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import { CATEGORY_LABEL, PriorityBadge, Thread, TicketStatus, type Ticket, type TicketMessage } from "./common";

type Detail = Ticket & {
  messages: TicketMessage[];
  organization?: { id: number; name: string; status: string; type: string; reseller_name: string | null; plan: string | null; subscription_status: string | null };
};

/** One ticket, for the customer (/support/:id) or platform support (/admin/tickets/:id). */
export function TicketView({ side }: { side: "customer" | "support" }) {
  const { id } = useParams<{ id: string }>();
  const toast = useToast();
  const { can } = useSession();
  const base = side === "customer" ? "/support/tickets" : "/admin/tickets";
  const { data, error, reload } = useApi<{ data: Detail }>(`${base}/${id}`);
  const staff = useApi<{ data: { id: number; name: string }[] }>(side === "support" ? "/admin/tickets/staff" : null);
  const [body, setBody] = useState("");
  const [internal, setInternal] = useState(false);
  const [after, setAfter] = useState<"pending" | "resolved">("pending");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState<string | null>(null);
  const [closing, setClosing] = useState(false);
  const manage = side === "customer" ? can("support.manage") : can("platform.support.manage");

  async function send() {
    setBusy(true);
    setErr(null);
    try {
      await api.post(`${base}/${id}/messages`, side === "customer" ? { body } : { body, internal, ...(internal ? {} : { status: after }) });
      setBody("");
      toast("success", internal ? "Note added" : "Reply sent");
      reload();
    } catch (e) {
      if (e instanceof ApiError && e.fields.body) setErr(e.fields.body);
      else toast("error", (e as Error).message);
    } finally {
      setBusy(false);
    }
  }
  async function patch(change: Record<string, unknown>, ok: string) {
    try {
      await api.patch(`/admin/tickets/${id}`, change);
      toast("success", ok);
      reload();
    } catch (e) {
      toast("error", (e as Error).message);
    }
  }

  if (error) return <p className="rounded-md bg-brick-soft px-4 py-3 text-sm text-brick">{error}</p>;
  if (!data) return <Skeleton className="h-96" />;
  const t = data.data;
  return (
    <>
      <Link href={side === "customer" ? "/support" : "/admin/tickets"} className="mb-3 inline-flex items-center gap-1.5 text-sm text-muted hover:text-teal">
        <ArrowLeft className="size-4" /> {side === "customer" ? "Support" : "Support queue"}
      </Link>
      <header className="mb-5">
        <h1 className="text-2xl font-semibold tracking-tight text-ink">
          <span className="text-muted">{t.number}</span> {t.subject}
        </h1>
        <p className="mt-2 flex flex-wrap items-center gap-2 text-sm text-muted">
          <TicketStatus status={t.status} side={side} />
          <PriorityBadge priority={t.priority} />
          {CATEGORY_LABEL[t.category]}, opened {formatDateTime(t.created_at)} by {t.created_by_name ?? "a teammate"}
          {side === "support" && t.organization ? `, ${t.organization.name}` : ""}
        </p>
      </header>
      <div className="grid gap-6 lg:grid-cols-3">
        <div className="lg:col-span-2">
          <Panel className="p-5">
            <Thread messages={t.messages} viewer={side} />
          </Panel>
          {manage && t.status !== "closed" && (
            <Panel className="mt-4 p-5">
              <Field label={side === "customer" ? "Reply" : internal ? "Internal note (only support staff see it)" : "Reply to the customer"} htmlFor="tk-reply" error={err ?? undefined}>
                <Textarea id="tk-reply" rows={5} value={body} onChange={(e) => setBody(e.target.value)} invalid={!!err} />
              </Field>
              <div className="mt-3 flex flex-wrap items-center gap-3">
                {side === "support" && (
                  <>
                    <label className="flex items-center gap-2 text-sm">
                      <input type="checkbox" className="size-4 accent-teal" checked={internal} onChange={(e) => setInternal(e.target.checked)} />
                      Internal note
                    </label>
                    {!internal && (
                      <Select aria-label="After replying" className="w-60" value={after} onChange={(e) => setAfter(e.target.value as "pending" | "resolved")}>
                        <option value="pending">Then wait for customer</option>
                        <option value="resolved">Then mark resolved</option>
                      </Select>
                    )}
                  </>
                )}
                <Button variant="primary" className="ml-auto" loading={busy} disabled={!body.trim()} onClick={send}>
                  {internal ? "Add note" : "Send reply"}
                </Button>
              </div>
            </Panel>
          )}
          {t.status === "closed" && <p className="mt-4 text-sm text-muted">This ticket is closed. {side === "customer" ? `Open a new one and mention ${t.number} if you need more help.` : ""}</p>}
        </div>
        <aside className="space-y-4">
          {side === "support" && data.data.organization && (
            <Panel className="p-5 text-sm">
              <h2 className="mb-2 font-semibold">Customer</h2>
              <p>
                <Link href={`/admin/customers/${data.data.organization.id}`} className="font-medium hover:text-teal">
                  {data.data.organization.name}
                </Link>
              </p>
              <p className="text-muted">
                {data.data.organization.plan ? `${data.data.organization.plan} (${data.data.organization.subscription_status})` : "No plan"}
                {data.data.organization.reseller_name ? `, via ${data.data.organization.reseller_name}` : ""}
                {data.data.organization.status !== "active" ? ", suspended" : ""}
              </p>
            </Panel>
          )}
          {side === "support" && manage && (
            <Panel className="space-y-3 p-5">
              <Field label="Assigned to" htmlFor="tk-assign">
                <Select id="tk-assign" value={t.assigned_to?.id ?? ""} onChange={(e) => patch({ assigned_to: e.target.value ? Number(e.target.value) : null }, "Assignment saved")}>
                  <option value="">Nobody</option>
                  {staff.data?.data.map((s) => (
                    <option key={s.id} value={s.id}>
                      {s.name}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Priority" htmlFor="tk-priority">
                <Select id="tk-priority" value={t.priority} onChange={(e) => patch({ priority: e.target.value }, "Priority saved")}>
                  {["low", "normal", "high", "urgent"].map((p) => (
                    <option key={p} value={p}>
                      {p[0].toUpperCase() + p.slice(1)}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field label="Status" htmlFor="tk-status">
                <Select id="tk-status" value={t.status} onChange={(e) => patch({ status: e.target.value }, "Status saved")}>
                  <option value="open">Needs reply</option>
                  <option value="pending">Waiting for customer</option>
                  <option value="resolved">Resolved</option>
                  <option value="closed">Closed</option>
                </Select>
              </Field>
            </Panel>
          )}
          {side === "customer" && manage && t.status !== "closed" && (
            <Panel className="p-5 text-sm">
              <p className="mb-3 text-muted">{t.status === "resolved" ? "Resolved tickets close by themselves after 7 days without a reply." : "Sorted it out yourself?"}</p>
              <Button onClick={() => setClosing(true)}>Close ticket</Button>
            </Panel>
          )}
        </aside>
      </div>
      <ConfirmDialog
        open={closing}
        title="Close this ticket?"
        message="Support won't work on it any more. You can always open a new one."
        confirmLabel="Close ticket"
        onConfirm={async () => {
          await api.post(`/support/tickets/${id}/close`).catch((e) => toast("error", (e as Error).message));
          setClosing(false);
          reload();
        }}
        onClose={() => setClosing(false)}
      />
    </>
  );
}
