import { generatePrDescription, pullRequestClose, pullRequestGet, pullRequestReopen, pullRequestUpdate, triggerCodeReview } from "@/client";
import { RepoHeader } from "@/components/repository/header";
import { PRConversation } from "@/components/repository/PRConversation";
import { PRDiffViewer } from "@/components/repository/PRDiffViewer";
import { PRMergeBox } from "@/components/repository/PRMergeBox";
import { PRCommitList } from "@/components/repository/PRCommitList";
import { Button } from "@/components/ui/button";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { Calendar, Check, GitBranch, GitMerge, GitPullRequest, Loader2, Sparkles, X } from "lucide-react";
import { useState } from "react";
import { useParams } from "react-router-dom";
import { toast } from "sonner";

const getRelativeTime = (dateString: string | null | undefined) => {
  if (!dateString) return "";
  const date = new Date(dateString);
  const now = new Date();
  const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
  if (diffInSeconds < 60) return "just now";
  if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)} minutes ago`;
  if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)} hours ago`;
  if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)} days ago`;
  if (diffInSeconds < 31536000) return `${Math.floor(diffInSeconds / 2592000)} months ago`;
  return `${Math.floor(diffInSeconds / 31536000)} years ago`;
};

const getStatusColor = (status: string) => {
  switch (status.toLowerCase()) {
    case "open":
      return "text-green-600 bg-green-100 dark:bg-green-900/30";
    case "merged":
      return "text-purple-600 bg-purple-100 dark:bg-purple-900/30";
    case "closed":
      return "text-red-600 bg-red-100 dark:bg-red-900/30";
    default:
      return "text-muted-foreground bg-muted";
  }
};

export const RepoPullRequestDetail = () => {
  const { namespace, repoName, prNumber } = useParams<{
    namespace: string;
    repoName: string;
    prNumber: string;
  }>();
  const queryClient = useQueryClient();

  const [generatedBody, setGeneratedBody] = useState<string | null>(null);

  const { data: pr, isLoading, error } = useQuery({
    queryKey: ["pull-request", namespace, repoName, prNumber],
    queryFn: async () => {
      if (!namespace || !repoName || !prNumber) return null;
      const resp = await pullRequestGet({
        path: { namespace, repo: repoName, number: parseInt(prNumber, 10) },
      });
      return resp.data?.data ?? null;
    },
    enabled: !!namespace && !!repoName && !!prNumber,
    staleTime: 30 * 1000,
  });

  const closeMutation = useMutation({
    mutationFn: async () => {
      if (!namespace || !repoName || !prNumber) return;
      await pullRequestClose({
        path: { namespace, repo: repoName, number: parseInt(prNumber, 10) },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pull-request", namespace, repoName, prNumber] });
      toast.success("Pull request closed");
    },
    onError: () => {
      toast.error("Failed to close pull request");
    },
  });

  const reopenMutation = useMutation({
    mutationFn: async () => {
      if (!namespace || !repoName || !prNumber) return;
      await pullRequestReopen({
        path: { namespace, repo: repoName, number: parseInt(prNumber, 10) },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pull-request", namespace, repoName, prNumber] });
      toast.success("Pull request reopened");
    },
    onError: () => {
      toast.error("Failed to reopen pull request");
    },
  });

  const generateDescMutation = useMutation({
    mutationFn: async () => {
      if (!namespace || !repoName || !prNumber) return;
      const resp = await generatePrDescription({
        path: { namespace, repo: repoName },
        body: { pr_number: parseInt(prNumber, 10) },
      });
      return resp.data?.markdown_body ?? null;
    },
    onSuccess: (body) => {
      if (body) {
        setGeneratedBody(body);
        toast.success("Description generated");
      }
    },
    onError: () => {
      toast.error("Failed to generate description");
    },
  });

  const triggerReviewMutation = useMutation({
    mutationFn: async () => {
      if (!namespace || !repoName || !prNumber) return;
      await triggerCodeReview({
        path: { namespace, repo: repoName },
        body: { pr_number: parseInt(prNumber, 10) },
      });
    },
    onSuccess: () => {
      toast.success("AI review requested");
    },
    onError: () => {
      toast.error("Failed to request AI review");
    },
  });

  const applyDescMutation = useMutation({
    mutationFn: async (body: string) => {
      if (!namespace || !repoName || !prNumber) return;
      await pullRequestUpdate({
        path: { namespace, repo: repoName, number: parseInt(prNumber, 10) },
        body: { body },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pull-request", namespace, repoName, prNumber] });
      setGeneratedBody(null);
      toast.success("Description updated");
    },
    onError: () => {
      toast.error("Failed to update description");
    },
  });

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <Loader2 className="h-6 w-6 animate-spin" />
      </div>
    );
  }

  if (error || !pr) {
    return (
      <div className="p-6">
        <div className="rounded-md border border-red-300 bg-red-50 dark:bg-red-950/30 p-4">
          <h2 className="text-lg font-semibold text-red-600 dark:text-red-400 mb-2">Error loading pull request</h2>
          <p className="text-sm text-red-500">{(error as Error).message || "Pull request not found"}</p>
        </div>
      </div>
    );
  }

  const isOpen = pr.status?.toLowerCase() === "open";
  const isMerged = pr.status?.toLowerCase() === "merged";
  const isClosed = pr.status?.toLowerCase() === "closed";

  return (
    <>
      <div className="p-6 pb-0 max-w-5xl mx-auto space-y-6">
        <RepoHeader />
      </div>
      <div className="p-6 pt-0 max-w-5xl mx-auto space-y-6">
        {/* PR Header */}
        <div className="border rounded-lg bg-card p-6">
          <div className="flex items-start justify-between gap-4">
            <div className="flex-1 min-w-0">
              <div className="flex items-center gap-3 mb-2">
                {isOpen ? (
                  <GitPullRequest className="h-6 w-6 text-green-600" />
                ) : isMerged ? (
                  <GitMerge className="h-6 w-6 text-purple-600" />
                ) : (
                  <X className="h-6 w-6 text-red-600" />
                )}
                <span className={`px-2 py-0.5 rounded-full text-xs font-medium ${getStatusColor(pr.status)}`}>
                  {pr.status}
                </span>
              </div>
              <h1 className="text-2xl font-bold mb-2">{pr.title}</h1>
              <div className="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm text-muted-foreground">
                <span>#{pr.number}</span>
                <span>
                  {isOpen ? "opened" : isMerged ? "merged" : "closed"} by{" "}
                  <span className="font-medium text-foreground">{pr.author}</span>
                </span>
                <span className="flex items-center gap-1">
                  <Calendar className="h-3.5 w-3.5" />
                  {getRelativeTime(pr.created_at)}
                </span>
                {pr.merged_at && (
                  <span>
                    Merged {getRelativeTime(pr.merged_at)}
                    {pr.merged_by && ` by ${pr.merged_by}`}
                  </span>
                )}
              </div>
            </div>

            <div className="flex items-center gap-2">
              <Button
                variant="outline"
                size="sm"
                onClick={() => triggerReviewMutation.mutate()}
                disabled={triggerReviewMutation.isPending || !isOpen}
                title="Request AI code review"
              >
                {triggerReviewMutation.isPending ? (
                  <Loader2 className="h-4 w-4 mr-1 animate-spin" />
                ) : (
                  <Sparkles className="h-4 w-4 mr-1" />
                )}
                AI Review
              </Button>
              {isOpen && (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => closeMutation.mutate()}
                  disabled={closeMutation.isPending}
                >
                  <X className="h-4 w-4 mr-1" />
                  Close
                </Button>
              )}
              {isClosed && !isMerged && (
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => reopenMutation.mutate()}
                  disabled={reopenMutation.isPending}
                >
                  <Check className="h-4 w-4 mr-1" />
                  Reopen
                </Button>
              )}
            </div>
          </div>

          {/* Branch info */}
          <div className="flex items-center gap-2 mt-4 p-3 bg-muted/50 rounded-md">
            <GitBranch className="h-4 w-4 text-muted-foreground" />
            <span className="text-sm">
              <span className="font-medium">{pr.head}</span>
              <span className="mx-2 text-muted-foreground">→</span>
              <span className="font-medium">{pr.base}</span>
            </span>
          </div>

          {/* Description */}
          <div className="mt-4">
            <div className="flex items-center justify-between mb-2">
              <h3 className="text-sm font-medium">Description</h3>
              <Button
                variant="ghost"
                size="sm"
                onClick={() => generateDescMutation.mutate()}
                disabled={generateDescMutation.isPending || !isOpen}
                className="h-7 text-xs gap-1"
              >
                {generateDescMutation.isPending ? (
                  <Loader2 className="h-3 w-3 animate-spin" />
                ) : (
                  <Sparkles className="h-3 w-3" />
                )}
                Generate with AI
              </Button>
            </div>

            {generatedBody ? (
              <div className="space-y-2">
                <div className="text-sm bg-primary/5 border border-primary/20 rounded-md p-3 whitespace-pre-wrap text-muted-foreground">
                  {generatedBody}
                </div>
                <div className="flex gap-2">
                  <Button
                    size="sm"
                    onClick={() => applyDescMutation.mutate(generatedBody)}
                    disabled={applyDescMutation.isPending}
                    className="h-7 text-xs"
                  >
                    {applyDescMutation.isPending ? <Loader2 className="h-3 w-3 mr-1 animate-spin" /> : null}
                    Apply to PR
                  </Button>
                  <Button
                    variant="ghost"
                    size="sm"
                    onClick={() => setGeneratedBody(null)}
                    className="h-7 text-xs"
                  >
                    Discard
                  </Button>
                </div>
              </div>
            ) : pr.body ? (
              <div className="text-sm text-muted-foreground whitespace-pre-wrap">{pr.body}</div>
            ) : (
              <div className="text-sm text-muted-foreground italic">
                No description provided. Click "Generate with AI" to create one.
              </div>
            )}
          </div>
        </div>

        {/* Merge box + branch info */}
        <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
          <div className="lg:col-span-2">
            {/* Branch info */}
            <div className="border rounded-lg bg-card p-4">
              <div className="flex items-center gap-2">
                <GitBranch className="h-4 w-4 text-muted-foreground" />
                <span className="text-sm">
                  <span className="font-medium">{pr.head}</span>
                  <span className="mx-2 text-muted-foreground">→</span>
                  <span className="font-medium">{pr.base}</span>
                </span>
              </div>
            </div>
          </div>
          <div>
            <PRMergeBox
              namespace={namespace ?? ""}
              repoName={repoName ?? ""}
              prNumber={parseInt(prNumber ?? "0", 10)}
              base={pr.base}
              head={pr.head}
              canMerge={false}
              isMerged={isMerged}
            />
          </div>
        </div>

        {/* Tabs */}
        <Tabs defaultValue="conversation">
          <TabsList>
            <TabsTrigger value="conversation">Conversation</TabsTrigger>
            <TabsTrigger value="files">Files Changed</TabsTrigger>
            <TabsTrigger value="commits">Commits</TabsTrigger>
            <TabsTrigger value="checks">Checks</TabsTrigger>
          </TabsList>

          <TabsContent value="conversation" className="mt-4">
            <div className="border rounded-lg bg-card p-4">
              <PRConversation
                namespace={namespace ?? ""}
                repoName={repoName ?? ""}
                prNumber={parseInt(prNumber ?? "0", 10)}
              />
            </div>
          </TabsContent>

          <TabsContent value="files" className="mt-4">
            <PRDiffViewer
              namespace={namespace ?? ""}
              repoName={repoName ?? ""}
              prNumber={parseInt(prNumber ?? "0", 10)}
              base={pr.base}
              head={pr.head}
            />
          </TabsContent>

          <TabsContent value="commits" className="mt-4">
            <PRCommitList
              namespace={namespace ?? ""}
              repoName={repoName ?? ""}
              prNumber={parseInt(prNumber ?? "0", 10)}
            />
          </TabsContent>

          <TabsContent value="checks" className="mt-4">
            <div className="border rounded-lg bg-card">
              <div className="p-8 text-center text-muted-foreground">
                <Check className="h-12 w-12 mx-auto mb-4 opacity-50" />
                <h3 className="text-lg font-medium mb-2">Checks</h3>
                <p className="text-sm">
                  CI/CD checks and status will be displayed here.
                </p>
              </div>
            </div>
          </TabsContent>
        </Tabs>
      </div>
    </>
  );
};
