import { useState, type FormEvent } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { client, type IssueCommentResponse, type IssueAuthor } from "@/client";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { cn } from "@/lib/utils";
import { useToast } from "@/hooks/use-toast";
import { workspaceColor, workspaceInitial } from "@/components/shell/shared";
import {
  MessageSquare,
  Pencil,
  Trash2,
  Smile,
} from "lucide-react";

const REACTION_EMOJIS = ["👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀"];

function formatRelative(date: string) {
  const now = Date.now();
  const diff = now - new Date(date).getTime();
  const mins = Math.floor(diff / 60000);
  if (mins < 1) return "just now";
  if (mins < 60) return `${mins}m ago`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}h ago`;
  const days = Math.floor(hrs / 24);
  if (days < 30) return `${days}d ago`;
  if (days < 365) return `${Math.floor(days / 30)}mo ago`;
  return `${Math.floor(days / 365)}y ago`;
}

function AuthorAvatar({ author }: { author: IssueAuthor }) {
  const name = author.display_name ?? author.username;
  return (
    <span
      className={cn(
        "grid size-5 shrink-0 place-items-center overflow-hidden rounded-full bg-gradient-to-br text-[10px] font-bold text-white",
        workspaceColor(name),
      )}
    >
      {author.avatar_url ? (
        <img alt="" className="size-full object-cover" src={author.avatar_url} />
      ) : (
        workspaceInitial(name)
      )}
    </span>
  );
}

function CommentReactions({
  comment,
  projectName,
  issueNumber,
  queryKey,
}: {
  comment: IssueCommentResponse & { reactions?: Array<{ id: string; reaction: string; user: IssueAuthor; created_at: string }> };
  projectName: string;
  issueNumber: number;
  queryKey: unknown[];
}) {
  const qc = useQueryClient();
  const [open, setOpen] = useState(false);
  const { toast } = useToast();

  const reactions = (comment as any).reactions ?? [];

  const addReaction = useMutation({
    mutationFn: async (reaction: string) => {
      await client.issuesAddCommentReaction(projectName, issueNumber, String(comment.id), { reaction });
    },
    onSuccess: () => { qc.invalidateQueries({ queryKey }); setOpen(false); },
    onError: (e: any) => toast({ title: "Failed to add reaction", description: String(e?.message ?? e), variant: "destructive" }),
  });

  const removeReaction = useMutation({
    mutationFn: async (reaction: string) => {
      await client.issuesRemoveCommentReaction(projectName, issueNumber, String(comment.id), { data: { reaction } } as any);
    },
    onSuccess: () => qc.invalidateQueries({ queryKey }),
    onError: (e: any) => toast({ title: "Failed to remove reaction", description: String(e?.message ?? e), variant: "destructive" }),
  });

  // Group reactions by emoji
  const grouped = new Map<string, string[]>();
  for (const r of reactions) {
    if (!grouped.has(r.reaction)) grouped.set(r.reaction, []);
    grouped.get(r.reaction)!.push(r.id);
  }

  return (
    <div className="flex items-center gap-1.5 mt-1.5">
      {[...grouped.entries()].map(([emoji, ids]) => (
        <button
          key={emoji}
          className="inline-flex items-center gap-0.5 rounded-full border border-border bg-muted/50 px-1.5 py-0.5 text-[11px] leading-none hover:bg-muted transition-colors cursor-pointer"
          onClick={() => removeReaction.mutate(emoji)}
        >
          {emoji} <span className="font-mono text-[10px] text-muted-foreground">{ids.length}</span>
        </button>
      ))}
      <button
        className="inline-flex items-center rounded-full border border-transparent px-1 py-0.5 text-[11px] text-muted-foreground hover:border-border hover:bg-muted/50 transition-colors cursor-pointer"
        onClick={() => setOpen(!open)}
      >
        <Smile className="size-3" />
      </button>
      {open && (
        <div className="absolute z-10 mt-6 flex items-center gap-1 rounded-md border border-border bg-popover p-1 shadow-md">
          {REACTION_EMOJIS.map((emoji) => (
            <button
              key={emoji}
              className="grid size-6 place-items-center rounded text-[13px] hover:bg-muted cursor-pointer"
              onClick={() => addReaction.mutate(emoji)}
            >
              {emoji}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function CommentItem({
  comment,
  projectName,
  issueNumber,
  queryKey,
  currentUsername,
}: {
  comment: IssueCommentResponse & { reactions?: Array<{ id: string; reaction: string; user: IssueAuthor; created_at: string }> };
  projectName: string;
  issueNumber: number;
  queryKey: unknown[];
  currentUsername?: string;
}) {
  const [editing, setEditing] = useState(false);
  const [editBody, setEditBody] = useState(comment.body);
  const [saving, setSaving] = useState(false);
  const qc = useQueryClient();
  const { toast } = useToast();
  const isOwn = currentUsername ? comment.author.username === currentUsername : false;

  const updateMutation = useMutation({
    mutationFn: async () => {
      await client.issuesUpdateComment(projectName, issueNumber, String(comment.id), { body: editBody });
    },
    onSuccess: () => { qc.invalidateQueries({ queryKey }); setEditing(false); },
    onError: (e: any) => toast({ title: "Failed to update comment", description: String(e?.message ?? e), variant: "destructive" }),
    onSettled: () => setSaving(false),
  });

  const deleteMutation = useMutation({
    mutationFn: async () => {
      await client.issuesDeleteComment(projectName, issueNumber, String(comment.id));
    },
    onSuccess: () => qc.invalidateQueries({ queryKey }),
    onError: (e: any) => toast({ title: "Failed to delete comment", description: String(e?.message ?? e), variant: "destructive" }),
  });

  return (
    <div className="group border-b border-border py-3 last:border-b-0">
      <div className="flex items-center gap-2">
        <AuthorAvatar author={comment.author} />
        <span className="font-heading text-[13px] font-medium text-foreground">
          {comment.author.display_name ?? comment.author.username}
        </span>
        <span className="font-mono text-[11px] text-muted-foreground">
          {formatRelative(comment.created_at)}
        </span>
        {isOwn && (
          <div className="ml-auto flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
            <button
              className="grid size-6 place-items-center rounded text-muted-foreground hover:text-foreground hover:bg-muted cursor-pointer"
              onClick={() => { setEditing(true); setEditBody(comment.body); }}
            >
              <Pencil className="size-3" />
            </button>
            <AlertDialog>
              <AlertDialogTrigger asChild>
                <button className="grid size-6 place-items-center rounded text-muted-foreground hover:text-destructive hover:bg-muted cursor-pointer">
                  <Trash2 className="size-3" />
                </button>
              </AlertDialogTrigger>
              <AlertDialogContent>
                <AlertDialogHeader>
                  <AlertDialogTitle>Delete comment?</AlertDialogTitle>
                  <AlertDialogDescription>This action cannot be undone.</AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                  <AlertDialogCancel>Cancel</AlertDialogCancel>
                  <AlertDialogAction onClick={() => deleteMutation.mutate()}>Delete</AlertDialogAction>
                </AlertDialogFooter>
              </AlertDialogContent>
            </AlertDialog>
          </div>
        )}
      </div>

      {editing ? (
        <div className="mt-2 ml-7 space-y-2">
          <Textarea
            className="min-h-[80px] text-[13px]"
            value={editBody}
            onChange={(e) => setEditBody(e.target.value)}
          />
          <div className="flex items-center gap-2">
            <Button className="h-7 px-3 text-[12px]" disabled={saving} onClick={() => { setSaving(true); updateMutation.mutate(); }}>
              {saving ? "Saving..." : "Update comment"}
            </Button>
            <Button className="h-7 px-3 text-[12px]" variant="outline" onClick={() => setEditing(false)}>Cancel</Button>
          </div>
        </div>
      ) : (
        <div className="mt-1.5 ml-7 text-[13px] text-foreground leading-relaxed whitespace-pre-wrap">
          {comment.body}
        </div>
      )}

      <div className="ml-7 relative">
        <CommentReactions
          comment={comment}
          projectName={projectName}
          issueNumber={issueNumber}
          queryKey={queryKey}
        />
      </div>
    </div>
  );
}

export default function CommentSection({
  projectName,
  issueNumber,
  currentUsername,
  queryKey,
}: {
  projectName: string;
  issueNumber: number;
  currentUsername?: string;
  queryKey: unknown[];
}) {
  const qc = useQueryClient();
  const { toast } = useToast();
  const [body, setBody] = useState("");
  const [submitting, setSubmitting] = useState(false);

  const { data: comments = [], isLoading } = useQuery({
    queryKey: [...queryKey, "comments"],
    queryFn: async () => {
      const res = await client.issuesListComments(projectName, issueNumber);
      return (res.data ?? []) as (IssueCommentResponse & { reactions?: Array<{ id: string; reaction: string; user: IssueAuthor; created_at: string }> })[];
    },
    retry: false,
  });

  const createComment = async (e: FormEvent) => {
    e.preventDefault();
    if (!body.trim()) return;
    setSubmitting(true);
    try {
      await client.issuesCreateComment(projectName, issueNumber, { body: body.trim() });
      setBody("");
      qc.invalidateQueries({ queryKey: [...queryKey, "comments"] });
    } catch (err: any) {
      toast({ title: "Failed to post comment", description: String(err?.message ?? err), variant: "destructive" });
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="mt-5">
      <div className="flex items-center gap-2 mb-3">
        <MessageSquare className="size-4 text-muted-foreground" />
        <h2 className="font-heading text-[13px] font-semibold text-foreground">
          Comments {comments.length > 0 && <span className="font-mono text-[11px] text-muted-foreground">({comments.length})</span>}
        </h2>
      </div>

      <form className="mb-4" onSubmit={(e) => void createComment(e)}>
        <Textarea
          className="min-h-[80px] text-[13px]"
          placeholder="Write a comment..."
          value={body}
          onChange={(e) => setBody(e.target.value)}
        />
        <div className="mt-2 flex items-center justify-between">
          <span className="text-[11px] text-muted-foreground">Markdown is supported</span>
          <Button className="h-8 px-4 text-[12px]" disabled={submitting || !body.trim()} type="submit">
            {submitting ? "Posting..." : "Comment"}
          </Button>
        </div>
      </form>

      {isLoading ? (
        <div className="space-y-3 py-2">
          {Array.from({ length: 3 }).map((_, i) => (
            <div key={i} className="h-16 animate-pulse rounded bg-muted/50" />
          ))}
        </div>
      ) : comments.length > 0 ? (
        <div className="rounded-md border border-border overflow-hidden">
          {comments.map((comment) => (
            <CommentItem
              key={comment.id}
              comment={comment}
              projectName={projectName}
              issueNumber={issueNumber}
              queryKey={[...queryKey, "comments"]}
              currentUsername={currentUsername}
            />
          ))}
        </div>
      ) : (
        <div className="rounded-md border border-border px-4 py-6 text-center text-[12px] text-muted-foreground">
          No comments yet. Start the discussion!
        </div>
      )}
    </div>
  );
}
