import { useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
  reviewCommentList,
  reviewList,
  reviewRequestList,
  reviewRequestCreate,
  reviewRequestDelete,
  type ReviewCommentListResponse,
  type ReviewResponse,
  type ReviewRequestResponse,
} from "@/client";
import { PRCommentInput } from "./PRCommentInput";
import { PRInlineComment } from "./PRInlineComment";
import { ContentRenderer } from "@/components/shared/ContentRenderer";
import { useTypingIndicator } from "@/hooks/useTypingIndicator";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { toast } from "sonner";
import {
  Check,
  GitPullRequest,
  MessageSquare,
  UserPlus,
  Users,
  X,
} from "lucide-react";

interface PRConversationProps {
  namespace: string;
  repoName: string;
  prNumber: number;
  /** Current user UID (for permission checks) */
  currentUserUid?: string;
  /** Whether the current user can modify comments */
  canModify?: boolean;
}

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)}m ago`;
  if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
  if (diffInSeconds < 2592000) return `${Math.floor(diffInSeconds / 86400)}d ago`;
  return `${Math.floor(diffInSeconds / 2592000)}mo ago`;
};

export function PRConversation({
  namespace,
  repoName,
  prNumber,
  canModify = false,
}: PRConversationProps) {
  const queryClient = useQueryClient();
  const [reviewState, setReviewState] = useState<string>("");
  const [_reviewBody, setReviewBody] = useState("");
  const [reviewDialogOpen, setReviewDialogOpen] = useState(false);
  const [addReviewerOpen, setAddReviewerOpen] = useState(false);
  const [newReviewerUid, setNewReviewerUid] = useState("");

  // Typing indicator for comment input
  const { typingUsers, sendTypingStart, sendTypingStop } = useTypingIndicator({});

  // Fetch review comments (general comments only — no path)
  const { data: commentsData, isLoading: commentsLoading } = useQuery({
    queryKey: ["pr-comments-general", namespace, repoName, prNumber],
    queryFn: async () => {
      const resp = await reviewCommentList({
        path: { namespace, repo: repoName, pr_number: prNumber },
        query: { file_only: false },
      });
      return resp.data?.data as ReviewCommentListResponse;
    },
    enabled: !!namespace && !!repoName && !!prNumber,
    staleTime: 30 * 1000,
  });

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

  // Fetch review requests
  const { data: reviewRequestsData } = useQuery({
    queryKey: ["pr-review-requests", namespace, repoName, prNumber],
    queryFn: async () => {
      const resp = await reviewRequestList({
        path: { namespace, repo: repoName, pr_number: prNumber },
      });
      return resp.data?.data;
    },
    enabled: !!namespace && !!repoName && !!prNumber,
    staleTime: 30 * 1000,
  });

  // Create general comment
  const createCommentMutation = useMutation({
    mutationFn: async (body: string) => {
      await reviewCommentList /* reuse endpoint */ ({
        path: { namespace, repo: repoName, pr_number: prNumber },
        query: {},
      });
      // Use reviewCommentCreate for general comments
      const { reviewCommentCreate } = await import("@/client");
      await reviewCommentCreate({
        path: { namespace, repo: repoName, pr_number: prNumber },
        body: { body, path: null, side: null, line: null, old_line: null },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pr-comments-general", namespace, repoName, prNumber] });
      toast.success("Comment posted");
    },
    onError: () => toast.error("Failed to post comment"),
  });

  // Submit review
  const submitReviewMutation = useMutation({
    mutationFn: async ({ state, body }: { state: string; body: string }) => {
      const { reviewSubmit } = await import("@/client");
      await reviewSubmit({
        path: { namespace, repo: repoName, pr_number: prNumber },
        body: { state, body: body || undefined },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pr-reviews", namespace, repoName, prNumber] });
      queryClient.invalidateQueries({ queryKey: ["pr-comments-general", namespace, repoName, prNumber] });
      setReviewDialogOpen(false);
      setReviewState("");
      setReviewBody("");
      toast.success("Review submitted");
    },
    onError: () => toast.error("Failed to submit review"),
  });

  // Add reviewer
  const addReviewerMutation = useMutation({
    mutationFn: async (reviewerUid: string) => {
      await reviewRequestCreate({
        path: { namespace, repo: repoName, pr_number: prNumber },
        body: { reviewer: reviewerUid },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pr-review-requests", namespace, repoName, prNumber] });
      setAddReviewerOpen(false);
      setNewReviewerUid("");
      toast.success("Review requested");
    },
    onError: () => toast.error("Failed to request review"),
  });

  // Remove reviewer
  const removeReviewerMutation = useMutation({
    mutationFn: async (reviewerUid: string) => {
      await reviewRequestDelete({
        path: { namespace, repo: repoName, pr_number: prNumber, reviewer: reviewerUid },
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["pr-review-requests", namespace, repoName, prNumber] });
      toast.success("Review request removed");
    },
    onError: () => toast.error("Failed to remove review request"),
  });

  // Separate general comments (no path) from file comments
  const comments = commentsData?.comments;
  const generalComments = Array.isArray(comments) ? comments.filter(
    (c) => !c.path
  ) : [];

  const reviews = reviewsData?.reviews ?? [];
  const reviewRequests = reviewRequestsData?.requests ?? [];

  return (
    <div className="space-y-6">
      {/* Review requests section */}
      <div>
        <div className="flex items-center justify-between mb-3">
          <h3 className="text-sm font-semibold flex items-center gap-2">
            <Users className="h-4 w-4" />
            Review Requests
          </h3>
          <Dialog open={addReviewerOpen} onOpenChange={setAddReviewerOpen}>
            <DialogTrigger className="shrink-0 justify-center border border-transparent bg-clip-padding font-medium inline-flex items-center rounded-lg text-sm whitespace-nowrap transition-all outline-none select-none h-7 gap-1 px-2.5 hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground border-input bg-transparent">
              <UserPlus className="h-4 w-4 mr-1" />
              Request review
            </DialogTrigger>
            <DialogContent>
              <DialogHeader>
                <DialogTitle>Request a review</DialogTitle>
              </DialogHeader>
              <div className="space-y-3 py-2">
                <div>
                  <Label>Reviewer User ID</Label>
                  <Input
                    placeholder="Enter user ID (UUID)"
                    value={newReviewerUid}
                    onChange={(e) => setNewReviewerUid(e.target.value)}
                    className="mt-1"
                  />
                </div>
                <div className="flex justify-end gap-2">
                  <Button
                    variant="outline"
                    onClick={() => setAddReviewerOpen(false)}
                  >
                    Cancel
                  </Button>
                  <Button
                    onClick={() => {
                      if (newReviewerUid.trim()) {
                        addReviewerMutation.mutate(newReviewerUid.trim());
                      }
                    }}
                    disabled={!newReviewerUid.trim() || addReviewerMutation.isPending}
                  >
                    Request Review
                  </Button>
                </div>
              </div>
            </DialogContent>
          </Dialog>
        </div>

        {reviewRequests.length === 0 ? (
          <p className="text-sm text-muted-foreground italic">No review requests.</p>
        ) : (
          <div className="space-y-1">
            {reviewRequests.map((req: ReviewRequestResponse) => (
              <div
                key={req.reviewer}
                className="flex items-center justify-between p-2 rounded-md border bg-card"
              >
                <div className="flex items-center gap-2">
                  <div className="w-6 h-6 rounded-full bg-muted flex items-center justify-center text-xs">
                    {req.reviewer_username?.[0]?.toUpperCase() ?? "?"}
                  </div>
                  <div>
                    <span className="text-sm font-medium">
                      {req.reviewer_username ?? req.reviewer}
                    </span>
                    <span className="text-xs text-muted-foreground ml-2">
                      requested by {req.requested_by_username ?? req.requested_by}
                      {" · "}
                      {getRelativeTime(req.requested_at)}
                    </span>
                  </div>
                  {req.dismissed_at && (
                    <span className="text-xs bg-muted px-1.5 py-0.5 rounded text-muted-foreground">
                      dismissed
                    </span>
                  )}
                </div>
                <Button
                  variant="ghost"
                  size="sm"
                  className="text-muted-foreground hover:text-red-600"
                  onClick={() => removeReviewerMutation.mutate(req.reviewer)}
                  disabled={removeReviewerMutation.isPending}
                >
                  <X className="h-4 w-4" />
                </Button>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Reviews section */}
      {reviews.length > 0 && (
        <div>
          <h3 className="text-sm font-semibold flex items-center gap-2 mb-3">
            <GitPullRequest className="h-4 w-4" />
            Reviews
          </h3>
          <div className="space-y-3">
            {reviews.map((review: ReviewResponse) => (
              <div key={review.reviewer} className="p-3 border rounded-md bg-card">
                <div className="flex items-center gap-2 mb-2">
                  <div className="w-6 h-6 rounded-full bg-muted flex items-center justify-center text-xs">
                    {review.reviewer_username?.[0]?.toUpperCase() ?? "?"}
                  </div>
                  <span className="text-sm font-medium">
                    {review.reviewer_username ?? review.reviewer}
                  </span>
                  <span
                    className={`text-xs px-1.5 py-0.5 rounded font-medium ${
                      review.state === "approved"
                        ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400"
                        : review.state === "changes_requested"
                        ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
                        : "bg-muted text-muted-foreground"
                    }`}
                  >
                    {review.state}
                  </span>
                  <span className="text-xs text-muted-foreground">
                    {getRelativeTime(review.submitted_at ?? review.created_at)}
                  </span>
                </div>
                {review.body && (
                  <ContentRenderer content={review.body} className="text-sm text-muted-foreground" />
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* General comments section */}
      <div>
        <h3 className="text-sm font-semibold flex items-center gap-2 mb-3">
          <MessageSquare className="h-4 w-4" />
          Comments ({generalComments.length})
        </h3>

        {/* Add general comment */}
        <div className="mb-4">
          <PRCommentInput
            placeholder="Leave a comment..."
            buttonLabel="Comment"
            onSubmit={(body) => createCommentMutation.mutate(body)}
            onTypingStart={sendTypingStart}
            onTypingStop={sendTypingStop}
          />
          {typingUsers.length > 0 && (
            <div className="mt-1.5 flex items-center gap-1.5 animate-in fade-in slide-in-from-top-1 duration-200">
              <div className="flex -space-x-1.5">
                {typingUsers.slice(0, 3).map((u) => (
                  <Avatar key={u.userId} className="h-5 w-5 border border-background">
                    {u.avatarUrl ? (
                      <img src={u.avatarUrl} alt={u.username} className="h-5 w-5 rounded-full object-cover" />
                    ) : (
                      <AvatarFallback className="text-[10px]">{u.username[0]?.toUpperCase()}</AvatarFallback>
                    )}
                  </Avatar>
                ))}
              </div>
              <span className="text-xs text-muted-foreground">
                {typingUsers.length === 1
                  ? `${typingUsers[0].username} is typing…`
                  : typingUsers.length === 2
                  ? `${typingUsers[0].username} and ${typingUsers[1].username} are typing…`
                  : `${typingUsers.length} people are typing…`}
              </span>
              <span className="flex gap-0.5 ml-1">
                <span className="h-1 w-1 rounded-full bg-muted-foreground animate-bounce" style={{ animationDelay: '0ms' }} />
                <span className="h-1 w-1 rounded-full bg-muted-foreground animate-bounce" style={{ animationDelay: '150ms' }} />
                <span className="h-1 w-1 rounded-full bg-muted-foreground animate-bounce" style={{ animationDelay: '300ms' }} />
              </span>
            </div>
          )}
        </div>

        {/* Comment list */}
        {commentsLoading ? (
          <p className="text-sm text-muted-foreground">Loading comments...</p>
        ) : generalComments.length === 0 ? (
          <p className="text-sm text-muted-foreground italic">
            No comments yet.
          </p>
        ) : (
          <div className="space-y-4">
            {generalComments.map((comment) => (
              <PRInlineComment
                key={comment.id}
                comment={comment}
                namespace={namespace}
                repoName={repoName}
                prNumber={prNumber}
                canModify={canModify}
                onRefresh={() =>
                  queryClient.invalidateQueries({
                    queryKey: ["pr-comments-general", namespace, repoName, prNumber],
                  })
                }
              />
            ))}
          </div>
        )}
      </div>

      {/* Submit review button */}
      <div className="border-t pt-4">
        <Dialog open={reviewDialogOpen} onOpenChange={setReviewDialogOpen}>
          <DialogTrigger className="group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none h-8 gap-1.5 px-2.5 hover:bg-primary/80 bg-primary text-primary-foreground">
            Submit Review
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Submit Review</DialogTitle>
            </DialogHeader>
            <div className="space-y-4 py-2">
              {/* Review state buttons */}
              <div className="flex gap-2">
                {[
                  { value: "approved", label: "Approve", icon: Check, color: "text-green-600" },
                  { value: "changes_requested", label: "Request changes", icon: X, color: "text-red-600" },
                  { value: "comment", label: "Comment only", icon: MessageSquare, color: "text-muted-foreground" },
                ].map(({ value, label, icon: Icon, color }) => (
                  <Button
                    key={value}
                    type="button"
                    variant={reviewState === value ? "default" : "outline"}
                    size="sm"
                    onClick={() => setReviewState(value)}
                    className={`flex-1 ${reviewState === value ? "" : color}`}
                  >
                    <Icon className="h-4 w-4 mr-1" />
                    {label}
                  </Button>
                ))}
              </div>
              {/* Review body */}
              <PRCommentInput
                placeholder="Leave a comment about this pull request..."
                buttonLabel="Submit Review"
                onSubmit={async (body) => {
                  await submitReviewMutation.mutateAsync({
                    state: reviewState || "comment",
                    body,
                  });
                }}
                onCancel={() => setReviewDialogOpen(false)}
                loading={submitReviewMutation.isPending}
                showPreviewToggle={false}
                minRows={4}
              />
            </div>
          </DialogContent>
        </Dialog>
      </div>
    </div>
  );
}
