import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { LayoutGrid, List, Plus } from "lucide-react";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { Empty, Page, Panel } from "@/components/page";
import { TaskDetail } from "@/components/task-detail";
import { Button } from "@/components/ui/button";
import { Input, Select } from "@/components/ui/input";
import { Tag, statusTone } from "@/components/ui/tag";
import { cn } from "@/lib/cn";
import { formatDue } from "@/lib/format";
import { useWorkspace } from "@/lib/store";
import type { Status } from "@/lib/types";

type Search = { focus?: string };

export const Route = createFileRoute("/tasks")({
  validateSearch: (s: Record<string, unknown>): Search => ({
    focus: typeof s.focus === "string" ? s.focus : undefined,
  }),
  component: TasksPage,
});

function TasksPage() {
  const { focus } = Route.useSearch();
  const navigate = useNavigate();
  const tasks = useWorkspace((s) => s.tasks);
  const projects = useWorkspace((s) => s.projects);
  const addTask = useWorkspace((s) => s.addTask);
  const setTaskStatus = useWorkspace((s) => s.setTaskStatus);

  const [q, setQ] = useState("");
  const [projectId, setProjectId] = useState("");
  const [view, setView] = useState<"list" | "board">("list");

  const filtered = useMemo(() => {
    return tasks.filter((t) => {
      if (projectId && t.projectId !== projectId) return false;
      if (q && !`${t.title} ${t.body}`.toLowerCase().includes(q.toLowerCase())) return false;
      return true;
    });
  }, [tasks, projectId, q]);

  const selected = tasks.find((t) => t.id === focus) ?? null;

  const create = () => {
    const id = addTask({ title: "Untitled task", projectId: projectId || null });
    toast("Task posted");
    void navigate({ to: "/tasks", search: { focus: id } });
  };

  return (
    <Page
      eyebrow="Book"
      title="Tasks"
      description="Status moves between todo, doing, and done. A task can carry a reminder, notes, and a source on a board."
      actions={
        <div className="flex gap-2">
          <Button size="sm" variant={view === "list" ? "default" : "ghost"} onClick={() => setView("list")}>
            <List className="size-3.5" />
            List
          </Button>
          <Button size="sm" variant={view === "board" ? "default" : "ghost"} onClick={() => setView("board")}>
            <LayoutGrid className="size-3.5" />
            Board
          </Button>
          <Button variant="primary" onClick={create}>
            <Plus className="size-3.5" />
            New task
          </Button>
        </div>
      }
    >
      <div className="flex flex-col md:flex-row gap-2 mb-4">
        <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Filter tasks" className="md:max-w-xs" />
        <Select value={projectId} onChange={(e) => setProjectId(e.target.value)} className="md:w-56">
          <option value="">All projects</option>
          {projects.map((p) => (
            <option key={p.id} value={p.id}>
              {p.name}
            </option>
          ))}
        </Select>
      </div>
      <div className={cn("grid gap-4", selected ? "lg:grid-cols-[1fr_320px]" : "")}>
        <div>
          {view === "list" ? (
            <Panel flush>
              {filtered.length === 0 ? (
                <Empty title="No tasks" body="Post a line on Today, or create one here." />
              ) : (
                <table className="ledger-table">
                  <thead>
                    <tr>
                      <th>Title</th>
                      <th>Project</th>
                      <th>Status</th>
                      <th>Pri</th>
                      <th className="r">Due</th>
                    </tr>
                  </thead>
                  <tbody>
                    {filtered.map((t) => (
                      <tr
                        key={t.id}
                        data-active={t.id === focus ? "true" : undefined}
                        onClick={() => void navigate({ to: "/tasks", search: { focus: t.id } })}
                      >
                        <td className="font-medium">{t.title}</td>
                        <td className="text-ink-2">{projects.find((p) => p.id === t.projectId)?.name ?? "Unfiled"}</td>
                        <td>
                          <Tag tone={statusTone(t.status)}>{t.status}</Tag>
                        </td>
                        <td>
                          <Tag tone={statusTone(t.priority)}>{t.priority}</Tag>
                        </td>
                        <td className="r m text-ink-2">{formatDue(t.dueAt)}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              )}
            </Panel>
          ) : (
            <div className="grid md:grid-cols-3 gap-3">
              {(["todo", "doing", "done"] as Status[]).map((col) => (
                <div
                  key={col}
                  className="border border-line rounded-md bg-sunken min-h-48"
                  onDragOver={(e) => e.preventDefault()}
                  onDrop={(e) => {
                    const id = e.dataTransfer.getData("text/task-id");
                    if (id) setTaskStatus(id, col);
                  }}
                >
                  <div className="px-3 py-2 text-xs font-semibold text-ink-2 border-b border-line flex justify-between">
                    <span className="capitalize">{col}</span>
                    <span className="font-mono tabular-nums">{filtered.filter((t) => t.status === col).length}</span>
                  </div>
                  <ul className="p-2 flex flex-col gap-2">
                    {filtered
                      .filter((t) => t.status === col)
                      .map((t) => (
                        <li
                          key={t.id}
                          draggable
                          onDragStart={(e) => e.dataTransfer.setData("text/task-id", t.id)}
                          onClick={() => void navigate({ to: "/tasks", search: { focus: t.id } })}
                          className={cn(
                            "bg-surface border border-line rounded-md px-3 py-2 cursor-grab text-[13px]",
                            t.id === focus && "border-accent bg-accent-soft",
                          )}
                        >
                          <div className="font-medium">{t.title}</div>
                          <div className="mt-1 text-[11px] text-ink-3 font-mono">{formatDue(t.dueAt)}</div>
                        </li>
                      ))}
                  </ul>
                </div>
              ))}
            </div>
          )}
        </div>
        {selected ? (
          <Panel title="Task">
            <TaskDetail task={selected} onClose={() => void navigate({ to: "/tasks", search: { focus: undefined } })} />
          </Panel>
        ) : null}
      </div>
    </Page>
  );
}
