import { useState, type FormEvent } from "react";
import { Link, useParams } from "react-router";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { client, type IssueResponse } from "@/client";
import {
  Circle,
  CircleDot,
  GitFork,
  MessageSquare,
  Plus,
  Search,
  Tag,
  Milestone,
  User,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
import { workspaceColor, workspaceInitial } from "@/components/shell/shared";
import { LabelManageDialog } from "./label-manage-dialog";
import { MilestoneManageDialog } from "./milestone-manage-dialog";

function formatDate(date: string) {
  const now = new Date();
  const d = new Date(date);
  const diff = now.getTime() - d.getTime();
  const days = Math.floor(diff / 86400000);
  if (days < 1) return "today";
  if (days === 1) return "1 day ago";
  if (days < 30) return `${days} days ago`;
  if (days < 365) return `${Math.floor(days / 30)}mo ago`;
  return `${Math.floor(days / 365)}y ago`;
}

function AuthorAvatar({ author }: { author: { username: string; avatar_url?: string | null; display_name?: string | null } }) {
  const name = author.display_name ?? author.username;
  return (
    <span
      className={cn(
        "grid size-5 place-items-center overflow-hidden rounded-full bg-gradient-to-br text-[10px] font-bold text-white",
        workspaceColor(name),
      )}
    >
      {author.avatar_url ? (
        <img alt="" className="size-full object-cover" src={author.avatar_url} />
      ) : (
        workspaceInitial(name)
      )}
    </span>
  );
}

function LabelBadge({ label }: { label: { name: string; color: string } }) {
  return (
    <span
      className="inline-flex h-[18px] items-center rounded px-1.5 text-[11px] font-medium leading-none whitespace-nowrap"
      style={{ backgroundColor: label.color + "18", color: label.color }}
    >
      {label.name}
    </span>
  );
}

function IssueRow({ issue, projectName }: { issue: IssueResponse; projectName: string }) {
  const isOpen = issue.state === "open";
  return (
    <Link
      className="group flex items-start gap-3 border-b border-border px-4 py-2.5 last:border-b-0 transition-colors hover:bg-muted/40"
      to={`/${projectName}/issues/${issue.number}`}
    >
      <span className="mt-0.5 shrink-0">
        {isOpen ? <Circle className="size-[14px] text-success" /> : <CircleDot className="size-[14px] text-purple-600" />}
      </span>
      <div className="min-w-0 flex-1">
        <div className="flex items-baseline gap-1.5 flex-wrap">
          <span className="font-heading text-[13px] font-semibold text-foreground leading-tight">{issue.title}</span>
          <span className="font-mono text-[11px] text-muted-foreground/60"># {issue.number}</span>
          {issue.labels.map((label) => <LabelBadge key={label.id} label={label} />)}
        </div>
        <div className="mt-0.5 flex items-center gap-2 text-[11px] text-muted-foreground">
          <span className="flex items-center gap-1">
            <AuthorAvatar author={issue.author} />
            {issue.author.display_name ?? issue.author.username}
          </span>
          <span>opened {formatDate(issue.created_at)}</span>
          {issue.milestone && (
            <span className="flex items-center gap-0.5">
              <Milestone className="size-[10px]" />
              {issue.milestone.title}
            </span>
          )}
          {issue.assignees.length > 0 && <span className="flex items-center gap-0.5"><User className="size-[10px]" />{issue.assignees.length}</span>}
          {issue.pull_requests.length > 0 && <span className="flex items-center gap-0.5"><GitFork className="size-[10px]" />{issue.pull_requests.length}</span>}
        </div>
      </div>
    </Link>
  );
}

function IssueListView({ projectName, onCreate }: { projectName: string; onCreate: () => void }) {
  const [stateFilter, setStateFilter] = useState<string>("open");
  const [search, setSearch] = useState("");
  const [labelManOpen, setLabelManOpen] = useState(false);
  const [mileManOpen, setMileManOpen] = useState(false);

  const { data: issues = [], isLoading } = useQuery({
    queryKey: ["issues", projectName, stateFilter],
    queryFn: async () => {
      const res = await client.issuesListIssues(projectName, { state: stateFilter });
      return res.data;
    },
    retry: false,
  });

  const filteredIssues = search
    ? issues.filter((i) => i.title.toLowerCase().includes(search.toLowerCase()) || String(i.number).includes(search))
    : issues;

  const openCount = issues.filter((i) => i.state === "open").length;
  const closedCount = issues.filter((i) => i.state === "closed").length;

  return (
    <>
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <h1 className="font-heading text-lg font-bold text-foreground">Issues</h1>
          {/* label & milestone manage buttons */}
          <Button className="h-7 px-2 text-[11px]" variant="ghost" onClick={() => setLabelManOpen(true)}>
            <Tag className="size-3.5 mr-1" />
            Labels
          </Button>
          <Button className="h-7 px-2 text-[11px]" variant="ghost" onClick={() => setMileManOpen(true)}>
            <Milestone className="size-3.5 mr-1" />
            Milestones
          </Button>
        </div>
        <Button className="h-8 rounded px-3 text-[13px]" onClick={onCreate}>
          <Plus className="size-3.5 mr-1" />New issue
        </Button>
      </div>

      <div className="mt-6 rounded-md border border-border overflow-hidden">
        <div className="flex items-center gap-2 bg-muted/50 px-3 py-2 border-b border-border">
          <nav className="flex items-center">
            {[
              { key: "open", icon: <Circle className="size-3 text-success" />, count: openCount },
              { key: "closed", icon: <CircleDot className="size-3 text-purple-600" />, count: closedCount },
              { key: "all", icon: null, count: issues.length },
            ].map((tab) => (
              <button
                className={cn("flex items-center gap-1.5 px-2.5 py-1 text-[12px] font-medium transition-colors", stateFilter === tab.key ? "text-foreground" : "text-muted-foreground hover:text-foreground")}
                key={tab.key}
                onClick={() => setStateFilter(tab.key)}
              >
                {tab.icon}
                {tab.key === "all" ? "All" : tab.key.charAt(0).toUpperCase() + tab.key.slice(1)}
                <span className="font-mono text-[10px] text-muted-foreground">{tab.count}</span>
              </button>
            ))}
          </nav>
          <div className="ml-auto relative">
            <Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
            <Input className="h-7 w-52 rounded-sm border-border bg-card pl-7 text-[12px]" placeholder="Filter issues..." value={search} onChange={(e) => setSearch(e.target.value)} />
          </div>
        </div>
        {isLoading ? (
          <div className="px-4 py-2">
            {Array.from({ length: 5 }).map((_, i) => <div className="h-6 animate-pulse rounded bg-muted/50 my-1.5" key={i} />)}
          </div>
        ) : filteredIssues.length > 0 ? (
          <div>{filteredIssues.map((issue) => <IssueRow key={issue.number} issue={issue} projectName={projectName} />)}</div>
        ) : (
          <div className="flex flex-col items-center justify-center py-16 text-center">
            <div className="grid size-14 place-items-center rounded-2xl bg-muted/40">
              <MessageSquare className="size-6 text-muted-foreground/40" />
            </div>
            <h3 className="mt-4 font-heading text-sm font-semibold text-foreground">
              {stateFilter === "open" ? "No open issues" : stateFilter === "closed" ? "No closed issues" : "No issues yet"}
            </h3>
            <p className="mt-1.5 max-w-[280px] text-[12px] leading-relaxed text-muted-foreground">
              {stateFilter === "open"
                ? "All caught up! Create an issue to track bugs, features, or tasks."
                : stateFilter === "closed"
                  ? "No closed issues found."
                  : "Issues help you track bugs, features, and tasks."}
            </p>
            {stateFilter !== "closed" && (
              <Button className="mt-4 h-8 px-3 text-[12px]" onClick={onCreate}>
                <Plus className="size-3.5 mr-1" /> Create first issue
              </Button>
            )}
          </div>
        )}
      </div>

      {/* Label & Milestone management dialogs */}
      <LabelManageDialog open={labelManOpen} onOpenChange={setLabelManOpen} projectName={projectName} />
      <MilestoneManageDialog open={mileManOpen} onOpenChange={setMileManOpen} projectName={projectName} />
    </>
  );
}

function IssueCreateView({ projectName, onCancel }: { projectName: string; onCancel: () => void }) {
  const qc = useQueryClient();
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState("");
  const [priority, setPriority] = useState("normal");

  const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError("");
    setSubmitting(true);

    const form = new FormData(event.currentTarget);
    const title = form.get("title") as string;
    const body = (form.get("body") as string) || null;
    const dueAt = (form.get("due_at") as string) || null;

    if (!title.trim()) {
      setError("Title is required.");
      setSubmitting(false);
      return;
    }

    try {
      await client.issuesCreateIssue(projectName, {
        title: title.trim(),
        body,
        priority,
        due_at: dueAt,
      });
      await qc.invalidateQueries({ queryKey: ["issues", projectName] });
      onCancel();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to create issue.");
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <>
      <h1 className="font-heading text-lg font-bold text-foreground">New issue</h1>

      <form className="mt-6 grid grid-cols-[1fr_240px] gap-6" onSubmit={(e) => void handleSubmit(e)}>
        <div className="space-y-4">
          <div>
            <label className="text-[13px] font-medium text-foreground">Title</label>
            <Input
              className="mt-1.5 h-9 text-[14px] font-heading font-semibold"
              name="title"
              placeholder="Issue title"
              required
              autoFocus
            />
          </div>
          <div>
            <label className="text-[13px] font-medium text-foreground">Description</label>
            <Textarea
              className="mt-1.5 min-h-[200px] text-[13px]"
              name="body"
              placeholder="Leave a comment... Markdown is supported"
            />
          </div>
          {error && <p className="text-[12px] text-destructive">{error}</p>}
          <div className="flex items-center gap-3">
            <Button className="h-9 px-4 text-[13px]" disabled={submitting} type="submit">
              {submitting ? "Submitting..." : "Submit new issue"}
            </Button>
            <Button className="h-9 px-4 text-[13px]" onClick={onCancel} variant="outline">Cancel</Button>
          </div>
        </div>

        <div className="space-y-4">
          <div>
            <label className="text-[12px] font-medium text-foreground">Priority</label>
            <Select value={priority} onValueChange={(v) => setPriority(v ?? "normal")}>
              <SelectTrigger className="mt-1 w-full h-8 text-[12px]">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="critical">Critical</SelectItem>
                <SelectItem value="high">High</SelectItem>
                <SelectItem value="normal">Normal</SelectItem>
                <SelectItem value="low">Low</SelectItem>
              </SelectContent>
            </Select>
          </div>

          <div>
            <label className="text-[12px] font-medium text-foreground">Due date <span className="text-muted-foreground">(optional)</span></label>
            <Input className="mt-1 h-8 w-full text-[12px]" name="due_at" placeholder="e.g. 2026-06-30" type="date" />
          </div>
        </div>
      </form>
    </>
  );
}

export default function WorkspaceIssuesPage() {
  const { projectName = "" } = useParams();
  const [mode, setMode] = useState<"list" | "create">("list");

  return (
    <div className="px-8 py-10">
      {mode === "list" ? (
        <IssueListView projectName={projectName} onCreate={() => setMode("create")} />
      ) : (
        <IssueCreateView projectName={projectName} onCancel={() => setMode("list")} />
      )}
    </div>
  );
}
