import { useState } from "react";
import { Link, useParams } from "react-router";
import { useQuery } from "@tanstack/react-query";
import { client } from "@/client";
import { GitCommitHorizontal, Plus, Minus, FileCode, ArrowLeft } from "lucide-react";
import { cn } from "@/lib/utils";
import { workspaceColor, workspaceInitial } from "@/components/shell/shared";

function formatTimeAgo(timeSecs: number) {
  const now = Math.floor(Date.now() / 1000);
  const diff = now - timeSecs;
  if (diff < 60) return "just now";
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
  if (diff < 2592000) return `${Math.floor(diff / 86400)}d ago`;
  return new Date(timeSecs * 1000).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
}

function AuthorAvatar({ author }: { author: { name: string } }) {
  return (
    <span className={cn("grid size-6 place-items-center overflow-hidden rounded-full bg-gradient-to-br text-[10px] font-bold text-white", workspaceColor(author.name))}>
      {workspaceInitial(author.name)}
    </span>
  );
}

export default function CommitDetailPage() {
  const { projectName = "", repoName = "", oid = "" } = useParams();
  const [selectedFileIndex, setSelectedFileIndex] = useState(0);

  const { data: commit, isLoading } = useQuery({
    queryKey: ["repo", projectName, repoName, "commit-info", oid],
    queryFn: async () => {
      const res = await (client as any).gitCommitInfo(projectName, repoName, oid);
      return res.data.commit;
    },
    enabled: Boolean(projectName) && Boolean(repoName) && Boolean(oid),
    retry: false,
  });

  const parentOid = commit?.parent_ids?.[0];

  const { data: diffData, error: diffError } = useQuery({
    queryKey: ["repo", projectName, repoName, "diff", oid],
    queryFn: async () => {
      if (!parentOid) return null;
      const res = await client.gitDiff(projectName, repoName, { old_oid: parentOid, new_oid: oid });
      return res.data;
    },
    enabled: Boolean(parentOid),
    retry: false,
  });

  if (isLoading) {
    return (
      <div className="px-8 py-10 space-y-4">
        <div className="h-7 animate-pulse rounded bg-muted/50 w-64" />
        <div className="h-20 animate-pulse rounded bg-muted/50" />
      </div>
    );
  }

  if (!commit) {
    return (
      <div className="px-8 py-10 text-center">
        <GitCommitHorizontal className="mx-auto size-5 text-muted-foreground/20" />
        <p className="mt-3 text-[13px] text-muted-foreground">Commit not found</p>
      </div>
    );
  }

  const extras = commit.parent_ids.length > 1 ? `(merge commit: ${commit.parent_ids.length} parents)` : "";
  const deltas = ((diffData as any)?.deltas ?? []).filter((d: any) => d.status !== "tree");
  const selectedDelta = deltas[selectedFileIndex] ?? null;

  return (
    <div className="px-8 py-10">
      {/* Back link */}
      <Link className="inline-flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground transition-colors mb-4" to={`/${projectName}/repo/${repoName}`}>
        <ArrowLeft className="size-3.5" />
        Back to repository
      </Link>

      {/* Commit header */}
      <div className="flex items-start gap-3">
        <AuthorAvatar author={{ name: commit.author?.name ?? "unknown" }} />
        <div className="min-w-0 flex-1">
          <h1 className="font-heading text-[15px] font-bold text-foreground break-words">{commit.summary}</h1>
          {commit.message !== commit.summary && (
            <pre className="mt-1 text-[13px] text-muted-foreground whitespace-pre-wrap font-sans">{commit.message.slice(commit.summary.length).trim()}</pre>
          )}
          <div className="mt-1.5 flex items-center gap-2 font-mono text-[12px] text-muted-foreground flex-wrap">
            <span className="font-medium text-foreground">{commit.author?.name}</span>
            <span>authored {commit.author?.time_secs ? formatTimeAgo(commit.author.time_secs) : ""}</span>
            {commit.committer?.name !== commit.author?.name && <span>(committed by {commit.committer?.name})</span>}
            <code className="text-muted-foreground/60">{commit.oid.slice(0, 7)}</code>
            {extras && <span className="text-muted-foreground/60">{extras}</span>}
          </div>
        </div>
      </div>

      {/* Diff stats */}
      {(diffData as any)?.stats && (
        <div className="mt-4 flex items-center gap-4 text-[12px]">
          <span className="font-mono text-muted-foreground">{ (diffData as any).stats.files_changed} files</span>
          <span className="flex items-center gap-1 text-success font-mono"><Plus className="size-3" />{ (diffData as any).stats.insertions}</span>
          <span className="flex items-center gap-1 text-destructive font-mono"><Minus className="size-3" />{ (diffData as any).stats.deletions}</span>
        </div>
      )}

      {/* Two-column layout */}
      {deltas.length > 0 ? (
        <div className="mt-4 grid grid-cols-[240px_1fr] gap-0 rounded-md border border-border overflow-hidden">
          {/* Left: file list */}
          <div className="border-r border-border bg-muted/20 overflow-y-auto max-h-[calc(100vh-280px)]">
            <div className="px-3 py-2 border-b border-border bg-muted/40">
              <span className="font-mono text-[10px] uppercase tracking-wider text-muted-foreground">Files changed</span>
            </div>
            {deltas.map((delta: any, i: number) => {
              const path = delta.new_file?.path ?? delta.old_file?.path ?? "unknown";
              return (
                <button
                  className={cn(
                    "flex items-center gap-2 w-full px-3 py-2 text-left transition-colors border-b border-border last:border-b-0",
                    i === selectedFileIndex ? "bg-primary/5 text-foreground" : "text-muted-foreground hover:bg-muted/40 hover:text-foreground",
                  )}
                  key={i}
                  onClick={() => setSelectedFileIndex(i)}
                >
                  <FileCode className="size-3.5 shrink-0" />
                  <span className="font-mono text-[12px] truncate">{path}</span>
                  {delta.new_file?.is_binary && <span className="font-mono text-[9px] text-muted-foreground ml-auto shrink-0">bin</span>}
                </button>
              );
            })}
          </div>

          {/* Right: diff content */}
          <div className="overflow-y-auto max-h-[calc(100vh-280px)]">
            {selectedDelta && (
              <div>
                <div className="flex items-center gap-2 bg-muted/40 px-4 py-2 border-b border-border sticky top-0">
                  <FileCode className="size-4 text-muted-foreground shrink-0" />
                  <span className="font-heading text-[13px] font-medium text-foreground truncate">
                    {selectedDelta.new_file?.path ?? selectedDelta.old_file?.path ?? "unknown"}
                  </span>
                  {selectedDelta.old_file?.is_binary && <span className="font-mono text-[10px] text-muted-foreground ml-auto">Binary file</span>}
                </div>
                {!selectedDelta.old_file?.is_binary && selectedDelta.lines.length > 0 ? (
                  <table className="w-full font-mono text-[12px] leading-relaxed">
                    <tbody>
                      {selectedDelta.lines.map((line: any, j: number) => (
                        <tr className={cn(line.origin === "+" && "bg-success/10", line.origin === "-" && "bg-destructive/10")} key={j}>
                          <td className="w-12 min-w-[48px] text-right px-2 text-muted-foreground/40 select-none border-r border-border">{line.old_lineno ?? ""}</td>
                          <td className="w-12 min-w-[48px] text-right px-2 text-muted-foreground/40 select-none border-r border-border">{line.new_lineno ?? ""}</td>
                          <td className="w-4 min-w-[16px] text-center text-muted-foreground/50 select-none">{line.origin}</td>
                          <td className={cn("px-3 whitespace-pre", line.origin === "+" ? "text-success" : line.origin === "-" ? "text-destructive" : "text-foreground")}>{line.content}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                ) : selectedDelta.old_file?.is_binary ? null : (
                  <div className="py-6 text-center text-[12px] text-muted-foreground">No diff lines</div>
                )}
              </div>
            )}
          </div>
        </div>
      ) : diffData ? (
        <div className="mt-6 py-8 text-center rounded-md border border-border">
          <p className="text-[13px] text-muted-foreground">No file changes</p>
        </div>
      ) : parentOid ? (
        <div className="mt-6 py-8 text-center rounded-md border border-border">
          <p className="text-[13px] text-muted-foreground">
            {diffError ? `Diff error: ${(diffError as any)?.message || 'unknown'}` : 'Loading diff…'}
          </p>
        </div>
      ) : (
        <div className="mt-6 py-8 text-center rounded-md border border-border">
          <GitCommitHorizontal className="mx-auto size-5 text-muted-foreground/20" />
          <p className="mt-2 text-[13px] text-muted-foreground">Initial commit</p>
          <p className="text-[11px] text-muted-foreground/60">This is the first commit in the repository.</p>
        </div>
      )}
    </div>
  );
}