import { createFileRoute } from "@tanstack/react-router";
import { ChevronDown, Plus } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { Empty, Page, Panel } from "@/components/page";
import { Button } from "@/components/ui/button";
import { Field, Input, Select, Textarea } from "@/components/ui/input";
import { Tag } from "@/components/ui/tag";
import { cn } from "@/lib/cn";
import {
  dueKind,
  followUpDue,
  followUpIn,
  formatDay,
  fromDateInput,
  toDateInput,
  waitingFor,
} from "@/lib/format";
import { useWorkspace } from "@/lib/store";
import type { WaitingItem } from "@/lib/types";

export const Route = createFileRoute("/waiting")({ component: WaitingPage });

function WaitingPage() {
  const waiting = useWorkspace((s) => s.waiting);
  const projects = useWorkspace((s) => s.projects);
  const addWaiting = useWorkspace((s) => s.addWaiting);

  const [title, setTitle] = useState("");
  const [who, setWho] = useState("");
  const [follow, setFollow] = useState(() => toDateInput(followUpIn(3)));
  const [projectId, setProjectId] = useState("");
  const [showDone, setShowDone] = useState(false);

  const open = waiting.filter((w) => !w.done);
  const byFollowUp = (a: WaitingItem, b: WaitingItem) =>
    (a.followUpAt ?? "").localeCompare(b.followUpAt ?? "");

  const groups = [
    {
      key: "now",
      label: "Follow up now",
      items: open.filter(followUpDue).sort(byFollowUp),
    },
    {
      key: "later",
      label: "Waiting",
      items: open.filter((w) => w.followUpAt && !followUpDue(w)).sort(byFollowUp),
    },
    {
      key: "nodate",
      label: "No follow-up date",
      items: open.filter((w) => !w.followUpAt).sort((a, b) => a.since.localeCompare(b.since)),
    },
  ];
  const done = waiting
    .filter((w) => w.done)
    .sort((a, b) => (b.doneAt ?? "").localeCompare(a.doneAt ?? ""));

  return (
    <Page
      eyebrow="Time"
      title="Waiting on"
      description="Things that are with someone else. Log a follow-up when you chase it and the next one is scheduled for you; mark it received when it lands."
    >
      <Panel title="Waiting on something new" className="mb-4">
        <form
          className="grid md:grid-cols-[1fr_200px_160px_180px_auto] gap-2 items-end"
          onSubmit={(e) => {
            e.preventDefault();
            if (!title.trim()) return;
            addWaiting({
              title,
              who,
              projectId: projectId || null,
              followUpAt: fromDateInput(follow),
            });
            setTitle("");
            setWho("");
            setFollow(toDateInput(followUpIn(3)));
            toast("Added to waiting on");
          }}
        >
          <Field label="What">
            <Input
              value={title}
              onChange={(e) => setTitle(e.target.value)}
              placeholder="Quote, reply, approval, delivery…"
            />
          </Field>
          <Field label="From">
            <Input value={who} onChange={(e) => setWho(e.target.value)} placeholder="Person or company" />
          </Field>
          <Field label="Follow up">
            <Input type="date" value={follow} onChange={(e) => setFollow(e.target.value)} />
          </Field>
          <Field label="Project">
            <Select value={projectId} onChange={(e) => setProjectId(e.target.value)}>
              <option value="">Unfiled</option>
              {projects
                .filter((p) => p.status !== "done")
                .map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.name}
                  </option>
                ))}
            </Select>
          </Field>
          <Button variant="primary" type="submit" disabled={!title.trim()} className="mb-3">
            <Plus className="size-3.5" />
            Add
          </Button>
        </form>
      </Panel>

      <div className="flex flex-col gap-4">
        {groups.map((g) =>
          g.items.length === 0 ? null : (
            <Panel key={g.key} title={g.label} meta={`${g.items.length}`} flush>
              <ul>
                {g.items.map((w) => (
                  <WaitingRow key={w.id} item={w} />
                ))}
              </ul>
            </Panel>
          ),
        )}

        {open.length === 0 ? (
          <Panel>
            <Empty
              title="Not waiting on anything"
              body="When you hand something off — a question, a quote, an approval — add it above so it doesn't slip."
            />
          </Panel>
        ) : null}

        {done.length > 0 ? (
          <Panel
            title="Received"
            meta={
              <button type="button" onClick={() => setShowDone((v) => !v)} className="inline-flex items-center gap-1 hover:text-ink">
                {done.length}
                <ChevronDown className={cn("size-3.5 transition-transform", showDone && "rotate-180")} />
              </button>
            }
            flush
          >
            {showDone ? (
              <ul>
                {done.map((w) => (
                  <WaitingRow key={w.id} item={w} />
                ))}
              </ul>
            ) : null}
          </Panel>
        ) : null}
      </div>
    </Page>
  );
}

function WaitingRow({ item: w }: { item: WaitingItem }) {
  const projects = useWorkspace((s) => s.projects);
  const updateWaiting = useWorkspace((s) => s.updateWaiting);
  const nudgeWaiting = useWorkspace((s) => s.nudgeWaiting);
  const toggleWaiting = useWorkspace((s) => s.toggleWaiting);
  const removeWaiting = useWorkspace((s) => s.removeWaiting);
  const [open, setOpen] = useState(false);

  const project = projects.find((p) => p.id === w.projectId);
  const due = followUpDue(w);
  const overdue = !w.done && w.followUpAt && dueKind(w.followUpAt) === "overdue";

  return (
    <li className="border-b border-line-hair last:border-0">
      <div className="flex items-center gap-3 px-3.5 py-2.5 min-h-11">
        <button
          type="button"
          aria-label={w.done ? "Mark as still waiting" : "Mark received"}
          title={w.done ? "Still waiting" : "Received"}
          onClick={() => toggleWaiting(w.id)}
          className="size-4 rounded-full border border-line-strong shrink-0 data-[on=true]:bg-ok data-[on=true]:border-ok"
          data-on={w.done}
        />
        <button
          type="button"
          onClick={() => setOpen((v) => !v)}
          className="min-w-0 flex-1 text-left"
          aria-expanded={open}
        >
          <div className={w.done ? "text-[13px] line-through text-ink-3" : "text-[13px] font-medium"}>
            {w.title}
          </div>
          <div className="text-xs text-ink-3 flex flex-wrap gap-x-2">
            {w.who ? <span className="text-ink-2">from {w.who}</span> : null}
            <span>
              {w.done ? `received ${formatDay(w.doneAt)}` : `waiting ${waitingFor(w.since)}`}
            </span>
            {w.nudges > 0 ? (
              <span>
                chased {w.nudges}× · last {formatDay(w.lastNudgedAt)}
              </span>
            ) : null}
            {project ? <span>{project.name}</span> : null}
            {w.notes ? <span className="truncate max-w-[40ch]">— {w.notes}</span> : null}
          </div>
        </button>

        {!w.done ? (
          <>
            {w.followUpAt ? (
              <Tag tone={overdue ? "error" : due ? "accent" : "quiet"}>
                {due ? "Follow up" : "Next"} {formatDay(w.followUpAt)}
              </Tag>
            ) : null}
            <Button
              size="sm"
              onClick={() => {
                nudgeWaiting(w.id);
                toast(`Logged follow-up. Next check ${formatDay(followUpIn(3))}.`);
              }}
              title="Record that you chased it; schedules the next follow-up in 3 days"
            >
              Followed up
            </Button>
          </>
        ) : null}
      </div>

      {open ? (
        <div className="px-3.5 pb-3.5 pl-10 grid md:grid-cols-2 gap-x-3">
          <Field label="What">
            <Input defaultValue={w.title} onBlur={(e) => e.target.value.trim() && updateWaiting(w.id, { title: e.target.value.trim() })} />
          </Field>
          <Field label="From">
            <Input defaultValue={w.who} onBlur={(e) => updateWaiting(w.id, { who: e.target.value.trim() })} />
          </Field>
          <Field label="Waiting since">
            <Input
              type="date"
              defaultValue={toDateInput(w.since)}
              onChange={(e) => {
                const v = fromDateInput(e.target.value);
                if (v) updateWaiting(w.id, { since: v });
              }}
            />
          </Field>
          <Field label="Follow up">
            <div className="flex gap-2">
              <Input
                type="date"
                value={toDateInput(w.followUpAt)}
                onChange={(e) => updateWaiting(w.id, { followUpAt: fromDateInput(e.target.value) })}
              />
              {w.followUpAt ? (
                <Button size="sm" variant="ghost" onClick={() => updateWaiting(w.id, { followUpAt: null })}>
                  Clear
                </Button>
              ) : null}
            </div>
          </Field>
          <Field label="Project">
            <Select
              value={w.projectId ?? ""}
              onChange={(e) => updateWaiting(w.id, { projectId: e.target.value || null })}
            >
              <option value="">Unfiled</option>
              {projects.map((p) => (
                <option key={p.id} value={p.id}>
                  {p.name}
                </option>
              ))}
            </Select>
          </Field>
          <div className="md:col-span-2">
            <Field label="Notes">
              <Textarea
                rows={3}
                defaultValue={w.notes}
                placeholder="What you asked for, what they said, where the thread is…"
                onBlur={(e) => updateWaiting(w.id, { notes: e.target.value })}
              />
            </Field>
          </div>
          <div className="md:col-span-2 flex justify-end">
            <Button
              size="sm"
              variant="ghost"
              onClick={() => {
                if (window.confirm(`Delete "${w.title}"?`)) removeWaiting(w.id);
              }}
            >
              Delete
            </Button>
          </div>
        </div>
      ) : null}
    </li>
  );
}
