import { useState, useMemo, useCallback } from "react";

interface ConflictHunk {
  id: string;
  filePath: string;
  startLine: number;
  endLine: number;
  ours: string[];       // Changes from current branch
  theirs: string[];     // Changes from incoming branch
  base?: string[];      // Original content (if 3-way merge)
  resolved?: "ours" | "theirs" | "both" | "custom";
  customResolution?: string[];
}

interface ConflictFile {
  path: string;
  hunks: ConflictHunk[];
  resolved: boolean;
}

interface MergeConflictResolverProps {
  conflicts: ConflictFile[];
  sourceBranch: string;
  targetBranch: string;
  loading?: boolean;
  onResolve: (resolutions: Map<string, ConflictHunk[]>) => Promise<void>;
  onAbort: () => void;
  onAskLLM?: (hunk: ConflictHunk) => Promise<string[]>;
}

type ResolutionChoice = "ours" | "theirs" | "both" | "custom";

function ConflictHunkView({
  hunk,
  sourceBranch,
  targetBranch,
  onResolve,
  onAskLLM,
}: {
  hunk: ConflictHunk;
  sourceBranch: string;
  targetBranch: string;
  onResolve: (resolution: ResolutionChoice, customLines?: string[]) => void;
  onAskLLM?: () => Promise<void>;
}) {
  const [showCustomEditor, setShowCustomEditor] = useState(false);
  const [customText, setCustomText] = useState(
    hunk.customResolution?.join("\n") || [...hunk.ours, ...hunk.theirs].join("\n")
  );
  const [askingLLM, setAskingLLM] = useState(false);

  const handleAskLLM = async () => {
    if (!onAskLLM || askingLLM) return;
    setAskingLLM(true);
    try {
      await onAskLLM();
    } finally {
      setAskingLLM(false);
    }
  };

  const handleCustomSave = () => {
    const lines = customText.split("\n");
    onResolve("custom", lines);
    setShowCustomEditor(false);
  };

  const isResolved = hunk.resolved !== undefined;

  return (
    <div
      className={`border ${
        isResolved
          ? "border-green-400/30 bg-green-400/5"
          : "border-yellow-400/30 bg-yellow-400/5"
      } mb-3`}
    >
      {/* Hunk header */}
      <div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(117,170,252,0.2)]">
        <div className="font-mono text-xs text-[#75aafc]">
          Lines {hunk.startLine}-{hunk.endLine}
          {isResolved && (
            <span className="ml-2 text-green-400">
              (Resolved: {hunk.resolved})
            </span>
          )}
        </div>
        <div className="flex items-center gap-2">
          {onAskLLM && (
            <button
              onClick={handleAskLLM}
              disabled={askingLLM}
              className="px-2 py-1 font-mono text-[10px] text-purple-400 border border-purple-400/30 hover:border-purple-400/50 disabled:opacity-50 transition-colors"
            >
              {askingLLM ? "..." : "Ask LLM"}
            </button>
          )}
          <button
            onClick={() => setShowCustomEditor(!showCustomEditor)}
            className="px-2 py-1 font-mono text-[10px] text-[#75aafc] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] transition-colors"
          >
            Edit
          </button>
        </div>
      </div>

      {/* Conflict content */}
      {!showCustomEditor ? (
        <div className="grid grid-cols-2 divide-x divide-[rgba(117,170,252,0.2)]">
          {/* Ours (current branch) */}
          <div className="p-2">
            <div className="flex items-center justify-between mb-2">
              <span className="font-mono text-[10px] text-[#9bc3ff] uppercase">
                {targetBranch} (ours)
              </span>
              <button
                onClick={() => onResolve("ours")}
                className={`px-2 py-0.5 font-mono text-[9px] border transition-colors ${
                  hunk.resolved === "ours"
                    ? "text-green-400 border-green-400/50 bg-green-400/10"
                    : "text-[#75aafc] border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3]"
                }`}
              >
                Use This
              </button>
            </div>
            <pre className="font-mono text-xs text-red-400 bg-red-400/5 p-2 overflow-x-auto">
              {hunk.ours.map((line, i) => (
                <div key={i}>
                  <span className="text-[#555] select-none mr-2">-</span>
                  {line}
                </div>
              ))}
            </pre>
          </div>

          {/* Theirs (incoming branch) */}
          <div className="p-2">
            <div className="flex items-center justify-between mb-2">
              <span className="font-mono text-[10px] text-[#9bc3ff] uppercase">
                {sourceBranch} (theirs)
              </span>
              <button
                onClick={() => onResolve("theirs")}
                className={`px-2 py-0.5 font-mono text-[9px] border transition-colors ${
                  hunk.resolved === "theirs"
                    ? "text-green-400 border-green-400/50 bg-green-400/10"
                    : "text-[#75aafc] border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3]"
                }`}
              >
                Use This
              </button>
            </div>
            <pre className="font-mono text-xs text-green-400 bg-green-400/5 p-2 overflow-x-auto">
              {hunk.theirs.map((line, i) => (
                <div key={i}>
                  <span className="text-[#555] select-none mr-2">+</span>
                  {line}
                </div>
              ))}
            </pre>
          </div>
        </div>
      ) : (
        /* Custom editor */
        <div className="p-2">
          <div className="flex items-center justify-between mb-2">
            <span className="font-mono text-[10px] text-[#9bc3ff] uppercase">
              Custom Resolution
            </span>
            <div className="flex items-center gap-2">
              <button
                onClick={() => setShowCustomEditor(false)}
                className="px-2 py-0.5 font-mono text-[9px] text-[#555] hover:text-[#9bc3ff]"
              >
                Cancel
              </button>
              <button
                onClick={handleCustomSave}
                className="px-2 py-0.5 font-mono text-[9px] text-green-400 border border-green-400/30 hover:border-green-400/50"
              >
                Apply
              </button>
            </div>
          </div>
          <textarea
            value={customText}
            onChange={(e) => setCustomText(e.target.value)}
            className="w-full bg-[rgba(0,0,0,0.3)] border border-[rgba(117,170,252,0.25)] text-[#dbe7ff] font-mono text-xs p-2 outline-none focus:border-[#3f6fb3] min-h-[100px] resize-y"
          />
        </div>
      )}

      {/* Both option */}
      <div className="px-3 py-2 border-t border-[rgba(117,170,252,0.1)] flex justify-center">
        <button
          onClick={() => onResolve("both")}
          className={`px-3 py-1 font-mono text-[10px] border transition-colors ${
            hunk.resolved === "both"
              ? "text-green-400 border-green-400/50 bg-green-400/10"
              : "text-[#75aafc] border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3]"
          }`}
        >
          Keep Both
        </button>
      </div>
    </div>
  );
}

function ConflictFileView({
  file,
  sourceBranch,
  targetBranch,
  onResolveHunk,
  onAskLLM,
}: {
  file: ConflictFile;
  sourceBranch: string;
  targetBranch: string;
  onResolveHunk: (hunkId: string, resolution: ResolutionChoice, customLines?: string[]) => void;
  onAskLLM?: (hunk: ConflictHunk) => Promise<string[]>;
}) {
  const [expanded, setExpanded] = useState(true);
  const resolvedCount = file.hunks.filter((h) => h.resolved !== undefined).length;

  return (
    <div className="border border-[rgba(117,170,252,0.2)] mb-3">
      {/* File header */}
      <button
        onClick={() => setExpanded(!expanded)}
        className="w-full flex items-center gap-2 px-3 py-2 bg-[rgba(0,0,0,0.2)] hover:bg-[rgba(0,0,0,0.3)] text-left"
      >
        <span className="font-mono text-[10px] text-[#555]">
          {expanded ? "▼" : "▶"}
        </span>
        <span
          className={`px-1.5 py-0.5 font-mono text-[9px] ${
            file.resolved
              ? "text-green-400 bg-green-400/10"
              : "text-yellow-400 bg-yellow-400/10"
          }`}
        >
          {file.resolved ? "RESOLVED" : "CONFLICT"}
        </span>
        <span className="font-mono text-sm text-[#dbe7ff] flex-1 truncate">
          {file.path}
        </span>
        <span className="font-mono text-[10px] text-[#555]">
          {resolvedCount}/{file.hunks.length} hunks
        </span>
      </button>

      {/* Hunks */}
      {expanded && (
        <div className="p-3">
          {file.hunks.map((hunk) => (
            <ConflictHunkView
              key={hunk.id}
              hunk={hunk}
              sourceBranch={sourceBranch}
              targetBranch={targetBranch}
              onResolve={(resolution, customLines) =>
                onResolveHunk(hunk.id, resolution, customLines)
              }
              onAskLLM={
                onAskLLM
                  ? async () => {
                      const resolution = await onAskLLM(hunk);
                      onResolveHunk(hunk.id, "custom", resolution);
                    }
                  : undefined
              }
            />
          ))}
        </div>
      )}
    </div>
  );
}

export function MergeConflictResolver({
  conflicts: initialConflicts,
  sourceBranch,
  targetBranch,
  loading = false,
  onResolve,
  onAbort,
  onAskLLM,
}: MergeConflictResolverProps) {
  const [conflicts, setConflicts] = useState<ConflictFile[]>(initialConflicts);
  const [resolving, setResolving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Calculate resolution stats
  const stats = useMemo(() => {
    const totalHunks = conflicts.reduce((sum, f) => sum + f.hunks.length, 0);
    const resolvedHunks = conflicts.reduce(
      (sum, f) => sum + f.hunks.filter((h) => h.resolved !== undefined).length,
      0
    );
    const resolvedFiles = conflicts.filter((f) => f.resolved).length;
    return {
      totalFiles: conflicts.length,
      resolvedFiles,
      totalHunks,
      resolvedHunks,
      allResolved: resolvedHunks === totalHunks,
    };
  }, [conflicts]);

  // Handle resolving a single hunk
  const handleResolveHunk = useCallback(
    (filePath: string, hunkId: string, resolution: ResolutionChoice, customLines?: string[]) => {
      setConflicts((prev) =>
        prev.map((file) => {
          if (file.path !== filePath) return file;

          const updatedHunks = file.hunks.map((hunk) => {
            if (hunk.id !== hunkId) return hunk;
            return {
              ...hunk,
              resolved: resolution,
              customResolution: customLines,
            };
          });

          const allHunksResolved = updatedHunks.every((h) => h.resolved !== undefined);

          return {
            ...file,
            hunks: updatedHunks,
            resolved: allHunksResolved,
          };
        })
      );
    },
    []
  );

  // Resolve all hunks in a file with same choice
  const handleResolveFileAll = useCallback(
    (filePath: string, resolution: ResolutionChoice) => {
      setConflicts((prev) =>
        prev.map((file) => {
          if (file.path !== filePath) return file;

          const updatedHunks = file.hunks.map((hunk) => ({
            ...hunk,
            resolved: resolution,
            customResolution:
              resolution === "both"
                ? [...hunk.ours, ...hunk.theirs]
                : resolution === "ours"
                ? hunk.ours
                : resolution === "theirs"
                ? hunk.theirs
                : undefined,
          }));

          return {
            ...file,
            hunks: updatedHunks,
            resolved: true,
          };
        })
      );
    },
    []
  );

  // Apply all resolutions
  const handleApplyResolutions = async () => {
    if (!stats.allResolved || resolving) return;

    setResolving(true);
    setError(null);

    try {
      const resolutionMap = new Map<string, ConflictHunk[]>();
      conflicts.forEach((file) => {
        resolutionMap.set(file.path, file.hunks);
      });
      await onResolve(resolutionMap);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to apply resolutions");
    } finally {
      setResolving(false);
    }
  };

  if (loading) {
    return (
      <div className="panel p-4">
        <div className="flex items-center justify-center h-32">
          <div className="font-mono text-sm text-[#75aafc]">
            Analyzing conflicts...
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="panel flex flex-col max-h-[80vh] overflow-hidden">
      {/* Header */}
      <div className="flex items-center justify-between p-4 border-b border-[rgba(117,170,252,0.2)] shrink-0">
        <div className="flex items-center gap-3">
          <div className="font-mono text-xs text-[#9bc3ff] tracking-wide uppercase">
            Merge Conflicts
          </div>
          <span className="px-2 py-0.5 font-mono text-[10px] text-yellow-400 bg-yellow-400/10 border border-yellow-400/20">
            {sourceBranch} → {targetBranch}
          </span>
        </div>
        <button
          onClick={onAbort}
          className="font-mono text-xs text-red-400 hover:text-red-300"
        >
          Abort Merge
        </button>
      </div>

      {/* Progress */}
      <div className="px-4 py-3 border-b border-[rgba(117,170,252,0.1)] shrink-0">
        <div className="flex items-center justify-between mb-2">
          <span className="font-mono text-[10px] text-[#75aafc]">
            {stats.resolvedFiles}/{stats.totalFiles} files resolved
          </span>
          <span className="font-mono text-[10px] text-[#75aafc]">
            {stats.resolvedHunks}/{stats.totalHunks} conflicts resolved
          </span>
        </div>
        <div className="h-1.5 bg-[rgba(117,170,252,0.1)] rounded-full overflow-hidden">
          <div
            className="h-full bg-green-400 transition-all"
            style={{
              width: `${(stats.resolvedHunks / stats.totalHunks) * 100}%`,
            }}
          />
        </div>
      </div>

      {/* Error */}
      {error && (
        <div className="mx-4 mt-3 bg-red-400/10 border border-red-400/30 p-3 font-mono text-xs text-red-400 shrink-0">
          {error}
        </div>
      )}

      {/* Conflict files */}
      <div className="flex-1 overflow-y-auto p-4">
        {conflicts.map((file) => (
          <ConflictFileView
            key={file.path}
            file={file}
            sourceBranch={sourceBranch}
            targetBranch={targetBranch}
            onResolveHunk={(hunkId, resolution, customLines) =>
              handleResolveHunk(file.path, hunkId, resolution, customLines)
            }
            onAskLLM={onAskLLM}
          />
        ))}
      </div>

      {/* Footer actions */}
      <div className="flex items-center justify-between p-4 border-t border-[rgba(117,170,252,0.2)] shrink-0">
        <div className="flex items-center gap-2">
          <button
            onClick={() =>
              conflicts.forEach((f) => handleResolveFileAll(f.path, "ours"))
            }
            className="px-3 py-1.5 font-mono text-[10px] text-[#75aafc] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] transition-colors"
          >
            Accept All Ours
          </button>
          <button
            onClick={() =>
              conflicts.forEach((f) => handleResolveFileAll(f.path, "theirs"))
            }
            className="px-3 py-1.5 font-mono text-[10px] text-[#75aafc] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] transition-colors"
          >
            Accept All Theirs
          </button>
        </div>
        <button
          onClick={handleApplyResolutions}
          disabled={!stats.allResolved || resolving}
          className="px-4 py-2 font-mono text-xs text-green-400 border border-green-400/30 hover:border-green-400/50 hover:bg-green-400/10 disabled:opacity-50 disabled:cursor-not-allowed transition-colors uppercase"
        >
          {resolving
            ? "Applying..."
            : stats.allResolved
            ? "Complete Merge"
            : `Resolve ${stats.totalHunks - stats.resolvedHunks} Conflicts`}
        </button>
      </div>
    </div>
  );
}

// Export types for use in other components
export type { ConflictHunk, ConflictFile, ResolutionChoice };
