import { useState, useMemo } from "react";
import {
  ChevronDown,
  ChevronRight,
  Plus,
  Minus,
  CheckCircle2,
  Circle,
  Loader2,
} from "lucide-react";
import { Badge } from "@/components/ui/badge";
import type { FileDiff, FileDiffDetail, DiffLine, ReviewComment } from "./types";
import { HunkRows } from "./HunkRows";
import { useHighlightedFile } from "./use-syntax-highlight";
import { parseUnifiedDiff } from "./parse-diff";
import { trpc } from "@/lib/trpc";

const statusBadge: Record<FileDiff['status'], { label: string; classes: string } | null> = {
  added: {
    label: "NEW",
    classes:
      "bg-status-success-bg text-status-success-fg border-status-success-border",
  },
  deleted: {
    label: "DELETED",
    classes:
      "bg-status-error-bg text-status-error-fg border-status-error-border",
  },
  renamed: {
    label: "RENAMED",
    classes:
      "bg-status-active-bg text-status-active-fg border-status-active-border",
  },
  modified: null,
  binary: {
    label: "BINARY",
    classes: "bg-muted text-muted-foreground border-border",
  },
};

const leftBorderClass: Record<FileDiff['status'], string> = {
  added: "border-l-2 border-l-status-success-fg",
  deleted: "border-l-2 border-l-status-error-fg",
  renamed: "border-l-2 border-l-status-active-fg",
  modified: "border-l-2 border-l-primary/40",
  binary: "border-l-2 border-l-primary/40",
};

interface FileCardProps {
  file: FileDiff;
  detail?: FileDiffDetail;
  phaseId: string;
  commitMode: boolean;
  commentsByLine: Map<string, ReviewComment[]>;
  isExpandedOverride?: boolean;
  onAddComment: (
    filePath: string,
    lineNumber: number,
    lineType: DiffLine["type"],
    body: string,
  ) => void;
  onResolveComment: (commentId: string) => void;
  onUnresolveComment: (commentId: string) => void;
  onReplyComment?: (parentCommentId: string, body: string) => void;
  onEditComment?: (commentId: string, body: string) => void;
  isViewed?: boolean;
  onToggleViewed?: () => void;
}

export function FileCard({
  file,
  detail,
  phaseId,
  commitMode,
  commentsByLine,
  isExpandedOverride,
  onAddComment,
  onResolveComment,
  onUnresolveComment,
  onReplyComment,
  onEditComment,
  isViewed = false,
  onToggleViewed = () => {},
}: FileCardProps) {
  // Uncontrolled expand for normal file clicks.
  // Start expanded if detail prop is provided (commit mode).
  const [isExpandedLocal, setIsExpandedLocal] = useState(() => !!detail);

  // Merge with override from DiffViewer expandAll
  const isExpanded = isExpandedOverride ?? isExpandedLocal;

  const fileDiffQuery = trpc.getFileDiff.useQuery(
    { phaseId, filePath: encodeURIComponent(file.newPath) },
    {
      enabled: isExpanded && !commitMode && file.status !== 'binary' && !detail,
      staleTime: Infinity,
    },
  );

  // Compute hunks from query data (phase mode)
  const parsedHunks = useMemo(() => {
    if (!fileDiffQuery.data?.rawDiff) return null;
    const parsed = parseUnifiedDiff(fileDiffQuery.data.rawDiff);
    return parsed[0] ?? null;
  }, [fileDiffQuery.data]);

  // Collect all lines for syntax highlighting
  const allLines = useMemo(() => {
    if (detail) return detail.hunks.flatMap((h) => h.lines);
    if (parsedHunks) return parsedHunks.hunks.flatMap((h) => h.lines);
    return [];
  }, [detail, parsedHunks]);

  const tokenMap = useHighlightedFile(file.newPath, allLines);

  const commentCount = useMemo(() => {
    let count = 0;
    for (const [key, arr] of commentsByLine) {
      if (key.startsWith(`${file.newPath}:`)) count += arr.length;
    }
    return count;
  }, [commentsByLine, file.newPath]);

  const badge = statusBadge[file.status];

  const handlers = {
    onAddComment,
    onResolveComment,
    onUnresolveComment,
    onReplyComment,
    onEditComment,
    tokenMap,
  };

  return (
    <div className="rounded-lg border border-border overflow-clip">
      {/* File header */}
      <button
        className={`sticky z-10 flex w-full items-center gap-2 px-3 py-2 bg-muted hover:bg-muted/90 text-left text-sm font-mono transition-colors ${leftBorderClass[file.status]}`}
        style={{ top: 'var(--review-header-h, 0px)' }}
        onClick={() => setIsExpandedLocal(!isExpandedLocal)}
      >
        {isExpanded ? (
          <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
        ) : (
          <ChevronRight className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
        )}
        <span className="truncate flex-1 flex items-center gap-2">
          {file.newPath}
          {badge && (
            <span
              className={`inline-flex text-[9px] font-semibold uppercase px-1.5 py-0 rounded border leading-4 ${badge.classes}`}
            >
              {badge.label}
            </span>
          )}
        </span>
        <span className="flex items-center gap-2 shrink-0 text-xs">
          {/* Viewed toggle */}
          <span
            role="checkbox"
            aria-checked={isViewed}
            tabIndex={0}
            className="cursor-pointer"
            onClick={(e) => {
              e.stopPropagation();
              onToggleViewed();
            }}
            onKeyDown={(e) => {
              if (e.key === "Enter" || e.key === " ") {
                e.stopPropagation();
                e.preventDefault();
                onToggleViewed();
              }
            }}
          >
            {isViewed ? (
              <CheckCircle2 className="h-4 w-4 text-status-success-fg" />
            ) : (
              <Circle className="h-4 w-4 text-muted-foreground" />
            )}
          </span>
          {file.additions > 0 && (
            <span className="flex items-center gap-0.5 text-diff-add-fg">
              <Plus className="h-3 w-3" />
              {file.additions}
            </span>
          )}
          {file.deletions > 0 && (
            <span className="flex items-center gap-0.5 text-diff-remove-fg">
              <Minus className="h-3 w-3" />
              {file.deletions}
            </span>
          )}
          {commentCount > 0 && (
            <Badge variant="secondary" className="text-[10px] px-1.5 py-0">
              {commentCount}
            </Badge>
          )}
        </span>
      </button>

      {/* Diff content */}
      {isExpanded && (
        <div className="overflow-x-auto">
          {detail ? (
            // Commit mode: pre-parsed hunks from detail prop
            detail.hunks.length === 0 ? (
              <div className="px-4 py-3 text-xs text-muted-foreground">No content changes</div>
            ) : (
              <table className="w-full text-xs font-mono border-collapse">
                <tbody>
                  {detail.hunks.map((hunk, hi) => (
                    <HunkRows
                      key={hi}
                      hunk={hunk}
                      filePath={file.newPath}
                      commentsByLine={commentsByLine}
                      {...handlers}
                    />
                  ))}
                </tbody>
              </table>
            )
          ) : file.status === 'binary' ? (
            <div className="px-4 py-3 text-xs text-muted-foreground">Binary file — diff not shown</div>
          ) : fileDiffQuery.isLoading ? (
            <div className="flex items-center gap-2 px-4 py-3 text-xs text-muted-foreground">
              <Loader2 className="h-3.5 w-3.5 animate-spin" />
              Loading diff…
            </div>
          ) : fileDiffQuery.isError ? (
            <div className="flex items-center gap-2 px-4 py-3 text-xs text-destructive">
              Failed to load diff.
              <button
                className="underline hover:no-underline"
                onClick={() => fileDiffQuery.refetch()}
              >
                Retry
              </button>
            </div>
          ) : fileDiffQuery.data ? (
            !parsedHunks || parsedHunks.hunks.length === 0 ? (
              <div className="px-4 py-3 text-xs text-muted-foreground">No content changes</div>
            ) : (
              <table className="w-full text-xs font-mono border-collapse">
                <tbody>
                  {parsedHunks.hunks.map((hunk, hi) => (
                    <HunkRows
                      key={hi}
                      hunk={hunk}
                      filePath={file.newPath}
                      commentsByLine={commentsByLine}
                      {...handlers}
                    />
                  ))}
                </tbody>
              </table>
            )
          ) : null}
        </div>
      )}
    </div>
  );
}
