import { useState } from "react";
import { Link, useParams, useSearchParams } from "react-router";
import { useQuery } from "@tanstack/react-query";
import { client, type PullRequestResponse } from "@/client";
import {
  Circle,
  CircleDot,
  GitMerge,
  GitPullRequest,
  Search,
  Plus,
} from "lucide-react";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import { workspaceColor, workspaceInitial } from "@/components/shell/shared";
import PaginationBar from "./pagination";

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 PullStateIcon({ pr }: { pr: PullRequestResponse }) {
  if (pr.merged_at) {
    return <GitMerge className="size-[14px] text-purple-600 shrink-0 mt-0.5" />;
  }
  if (pr.state === "closed") {
    return <CircleDot className="size-[14px] text-destructive shrink-0 mt-0.5" />;
  }
  return <Circle className="size-[14px] text-success shrink-0 mt-0.5" />;
}

function PullRow({ pr, projectName, repoName }: { pr: PullRequestResponse; projectName: string; repoName: string }) {
  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}/repo/${repoName}/pulls/${pr.number}`}
    >
      <PullStateIcon pr={pr} />
      <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">{pr.title}</span>
          <span className="font-mono text-[11px] text-muted-foreground/60"># {pr.number}</span>
          {pr.draft && (
            <span className="rounded-md border border-border bg-muted/30 px-1.5 py-0.5 text-[11px] font-medium leading-none text-muted-foreground">
              Draft
            </span>
          )}
          {pr.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 flex-wrap">
          <span className="flex items-center gap-1">
            <AuthorAvatar author={pr.author} />
            {pr.author.display_name ?? pr.author.username}
          </span>
          <span>opened {formatDate(pr.created_at)}</span>
          <span className="font-mono text-[10px] text-muted-foreground/60">
            {pr.source_branch} → {pr.target_branch}
          </span>
        </div>
      </div>
    </Link>
  );
}

const LIMIT = 20;

export default function PullsTab() {
  const { projectName = "", repoName = "" } = useParams();
  const [stateFilter, setStateFilter] = useState<string>("open");
  const [search, setSearch] = useState("");
  const [pullsSearchParams, setPullsSearchParams] = useSearchParams();
  const offset = Number(pullsSearchParams.get("offset") ?? "0");
  const setOffset = (n: number) => {
    const next = new URLSearchParams(pullsSearchParams);
    if (n <= 0) next.delete("offset"); else next.set("offset", String(n));
    setPullsSearchParams(next, { replace: true });
  };

  const { data: prs = [], isLoading } = useQuery({
    queryKey: ["repo", projectName, repoName, "pulls", stateFilter, offset],
    queryFn: async () => {
      const res = await client.pullRequestListPrs(projectName, repoName, { state: stateFilter === "all" ? undefined : stateFilter, offset, limit: LIMIT });
      return res.data;
    },
    enabled: Boolean(projectName) && Boolean(repoName),
    retry: false,
  });

  const filteredPrs = search
    ? prs.filter((pr) => pr.title.toLowerCase().includes(search.toLowerCase()) || String(pr.number).includes(search))
    : prs;

  const openCount = prs.filter((pr) => pr.state === "open" && !pr.merged_at).length;
  const closedCount = prs.filter((pr) => pr.state === "closed" || pr.merged_at).length;

  return (
    <div>
      <div className="overflow-hidden rounded-xl border border-border bg-card shadow-sm">
        <div className="flex items-center gap-2 border-b border-border bg-muted/40 px-3 py-2">
          <nav className="flex items-center">
            {[
              { key: "open", icon: <Circle className="size-3 text-success" />, count: openCount },
              { key: "closed", icon: <CircleDot className="size-3 text-destructive" />, count: closedCount },
              { key: "all", icon: <GitPullRequest className="size-3" />, count: prs.length },
            ].map((tab) => (
              <button
                className={cn("flex items-center gap-1.5 rounded-lg px-2.5 py-1 text-[12px] font-medium transition-colors", stateFilter === tab.key ? "bg-card text-foreground shadow-sm ring-1 ring-border" : "text-muted-foreground hover:bg-background/60 hover:text-foreground")}
                key={tab.key}
                onClick={() => { setStateFilter(tab.key); setOffset(0); }}
              >
                {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 flex items-center gap-2">
            <Link className="inline-flex h-8 items-center rounded-lg border border-border bg-card px-3 text-[12px] font-medium text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground" to={`/${projectName}/repo/${repoName}/pulls/new`}>
              <Plus className="size-3 mr-1" />New PR
            </Link>
            <div className="relative">
              <Search className="absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" />
              <Input autoComplete="off" className="h-8 w-52 rounded-lg border-border bg-background pl-7 text-[12px]" placeholder="Filter PRs…" value={search} onChange={(e) => setSearch(e.target.value)} />
            </div>
          </div>
        </div>

        {isLoading ? (
          <div className="px-4 py-2">
            {Array.from({ length: 3 }).map((_, i) => <div className="h-6 animate-pulse rounded bg-muted/50 my-1.5" key={i} />)}
          </div>
        ) : filteredPrs.length > 0 ? (
          <>
          <div>{filteredPrs.map((pr) => <PullRow key={pr.number} pr={pr} projectName={projectName} repoName={repoName} />)}</div>
          <PaginationBar offset={offset} limit={LIMIT} hasMore={prs.length >= LIMIT} onPrev={() => setOffset(Math.max(0, offset - LIMIT))} onNext={() => setOffset(offset + LIMIT)} />
          </>
        ) : (
          <div className="py-12 text-center">
            <GitPullRequest className="mx-auto size-5 text-muted-foreground/20" />
            <p className="mt-3 text-[13px] text-muted-foreground">
              {stateFilter === "open" ? "No open pull requests" : stateFilter === "closed" ? "No closed pull requests" : "No pull requests yet"}
            </p>
          </div>
        )}
      </div>
    </div>
  );
}