import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  mergeAnalysis,
  mergeConflictCheck,
  mergeExecute,
  type MergeStrategy,
} from "@/client";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
import { Loader2, GitMerge, AlertTriangle, Check, ChevronDown } from "lucide-react";

interface MergeBoxProps {
  namespace: string;
  repoName: string;
  prNumber: number;
  /** Base branch name (e.g. "refs/heads/main") */
  base: string;
  /** Head branch name (e.g. "refs/heads/feature") */
  head: string;
  /** Whether the current user can merge (repo admin) */
  canMerge: boolean;
  /** Whether the PR is already merged */
  isMerged: boolean;
}

const STRATEGY_LABELS: Record<MergeStrategy, string> = {
  mergecommit: "Merge commit",
  squash: "Squash",
  rebase: "Rebase",
};

const STRATEGY_DESCRIPTIONS: Record<MergeStrategy, string> = {
  mergecommit: "All commits will be merged into a single merge commit",
  squash: "All commits will be squashed into one commit",
  rebase: "Commits will be rebased onto the target branch",
};

export function PRMergeBox({
  namespace,
  repoName,
  prNumber,
  base,
  head,
  canMerge,
  isMerged,
}: MergeBoxProps) {
  const queryClient = useQueryClient();
  const [selectedStrategy, setSelectedStrategy] = useState<MergeStrategy>("mergecommit");
  const [strategyDropdownOpen, setStrategyDropdownOpen] = useState(false);

  // Fetch merge analysis
  const { data: analysisData, isLoading: analysisLoading } = useQuery({
    queryKey: ["pr-merge-analysis", namespace, repoName, prNumber],
    queryFn: async () => {
      const resp = await mergeAnalysis({
        path: { namespace, repo: repoName, pr_number: prNumber },
      });
      return resp.data?.data ?? null;
    },
    enabled: !!namespace && !!repoName && !!prNumber,
    staleTime: 30 * 1000,
  });

  // Fetch conflict check
  const { data: conflictData, isLoading: conflictLoading } = useQuery({
    queryKey: ["pr-merge-conflict-check", namespace, repoName, prNumber],
    queryFn: async () => {
      const resp = await mergeConflictCheck({
        path: { namespace, repo: repoName, pr_number: prNumber },
      });
      return resp.data?.data ?? null;
    },
    enabled: !!namespace && !!repoName && !!prNumber,
    staleTime: 30 * 1000,
  });

  // Execute merge
  const mergeMutation = useMutation({
    mutationFn: async () => {
      await mergeExecute({
        path: { namespace, repo: repoName, pr_number: prNumber },
        body: {
          fast_forward: false,
          strategy: selectedStrategy,
          message: "",
        },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pull-request", namespace, repoName, prNumber] });
      toast.success("Pull request merged successfully");
    },
    onError: (err: unknown) => {
      const msg = err instanceof Error ? err.message : "Merge failed";
      toast.error(msg);
    },
  });

  const analysis = analysisData;
  const hasConflicts = conflictData?.has_conflicts ?? false;
  const isLoading = analysisLoading || conflictLoading;
  const supportedStrategies: MergeStrategy[] = (
    analysis?.supported_strategies ?? []
  )
    .filter((s): s is MergeStrategy =>
      s === "mergecommit" || s === "squash" || s === "rebase"
    );

  const canMergeNow = canMerge && !isMerged && !isLoading && !hasConflicts && supportedStrategies.length > 0;

  return (
    <div className="border rounded-lg bg-card p-4 space-y-4">
      <div className="flex items-center gap-2">
        <GitMerge className="h-4 w-4 text-muted-foreground" />
        <span className="text-sm font-medium">Merge pull request</span>
      </div>

      {/* Merge info */}
      <div className="space-y-1 text-sm">
        <div className="flex items-center gap-2">
          <span className="font-medium">{head}</span>
          <span className="text-muted-foreground">into</span>
          <span className="font-medium">{base}</span>
        </div>

        {/* Status badges */}
        <div className="flex flex-wrap gap-2 pt-1">
          {analysis?.can_fast_forward && (
            <span className="inline-flex items-center gap-1 text-xs bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 px-2 py-0.5 rounded">
              <Check className="h-3 w-3" /> Fast-forward available
            </span>
          )}
          {analysis?.is_up_to_date && (
            <span className="inline-flex items-center gap-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 px-2 py-0.5 rounded">
              Up to date
            </span>
          )}
          {hasConflicts && (
            <span className="inline-flex items-center gap-1 text-xs bg-red-100 dark:bg-red-900/30 text-red-700 dark:text-red-400 px-2 py-0.5 rounded">
              <AlertTriangle className="h-3 w-3" /> Conflicts detected
            </span>
          )}
          {isLoading && (
            <span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
              <Loader2 className="h-3 w-3 animate-spin" /> Checking...
            </span>
          )}
        </div>

        {/* Conflict files */}
        {hasConflicts && conflictData && conflictData.conflicted_files.length > 0 && (
          <div className="mt-2 p-2 bg-red-50 dark:bg-red-950/20 rounded border border-red-200 dark:border-red-800">
            <p className="text-xs font-medium text-red-600 dark:text-red-400 mb-1">
              {conflictData.conflicted_files.length} file(s) with conflicts:
            </p>
            <ul className="text-xs text-muted-foreground space-y-0.5">
              {conflictData.conflicted_files.slice(0, 5).map((f) => (
                <li key={f.path} className="font-mono">{f.path}</li>
              ))}
              {conflictData.conflicted_files.length > 5 && (
                <li className="text-muted-foreground italic">
                  ...and {conflictData.conflicted_files.length - 5} more
                </li>
              )}
            </ul>
          </div>
        )}
      </div>

      {/* Strategy selector */}
      {!isMerged && !isLoading && supportedStrategies.length > 0 && (
        <div className="space-y-1">
          <label className="text-xs font-medium text-muted-foreground">Merge strategy</label>
          <div className="relative">
            <button
              type="button"
              className="flex items-center justify-between w-full px-3 py-2 border rounded-md text-sm bg-background hover:bg-muted/50 transition-colors"
              onClick={() => setStrategyDropdownOpen(!strategyDropdownOpen)}
            >
              <span>
                {STRATEGY_LABELS[selectedStrategy] ?? selectedStrategy}
              </span>
              <ChevronDown className="h-4 w-4 text-muted-foreground" />
            </button>
            {strategyDropdownOpen && (
              <div className="absolute z-10 mt-1 w-full border rounded-md bg-background shadow-md">
                {supportedStrategies.map((s) => (
                  <button
                    key={s}
                    type="button"
                    className={`flex flex-col w-full px-3 py-2 text-left hover:bg-muted/50 transition-colors ${
                      s === selectedStrategy ? "bg-muted/30" : ""
                    }`}
                    onClick={() => {
                      setSelectedStrategy(s);
                      setStrategyDropdownOpen(false);
                    }}
                  >
                    <span className="text-sm font-medium">{STRATEGY_LABELS[s]}</span>
                    <span className="text-xs text-muted-foreground">{STRATEGY_DESCRIPTIONS[s]}</span>
                  </button>
                ))}
              </div>
            )}
          </div>
        </div>
      )}

      {/* Merge button */}
      <div className="pt-2">
        <Button
          className="w-full"
          onClick={() => mergeMutation.mutate()}
          disabled={!canMergeNow || mergeMutation.isPending}
        >
          {mergeMutation.isPending ? (
            <>
              <Loader2 className="h-4 w-4 mr-2 animate-spin" />
              Merging...
            </>
          ) : (
            <>
              <GitMerge className="h-4 w-4 mr-2" />
              Merge
            </>
          )}
        </Button>
        {!canMerge && !isMerged && (
          <p className="text-xs text-muted-foreground text-center mt-1">
            You need repo admin permission to merge
          </p>
        )}
        {isMerged && (
          <p className="text-xs text-muted-foreground text-center mt-1">
            This pull request has been merged
          </p>
        )}
      </div>
    </div>
  );
}
