import { useState, useRef } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import {
    AlertTriangle,
    ArrowLeft,
    Check,
    Edit,
    Lightbulb,
    MessageSquare,
    Pencil,
    SquarePen,
    Trash2,
    User,
    X,
} from 'lucide-react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { toast } from 'sonner';
import {
    issueClose,
    issueCommentCreate,
    issueCommentDelete,
    issueCommentList,
    issueCommentUpdate,
    issueGet,
    issueLabelAddBulk,
    issueReopen,
    issueRepoList,
    triageIssue,
} from '@/client';
import type { IssueCommentResponse } from '@/client/types.gen';
import { useProject } from '@/contexts';
import { Button } from '@/components/ui/button';
import { Spinner } from '@/components/ui/spinner';
import { Textarea } from '@/components/ui/textarea';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import {getApiErrorMessage} from '@/lib/api-error';
import { ContentRenderer } from '@/components/shared/ContentRenderer';
import { useTypingIndicator } from '@/hooks/useTypingIndicator';

const StatusBadge = ({ status }: { status: string }) => {
    const styles =
        status === 'open'
            ? 'bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-950/40 dark:text-emerald-400 dark:border-emerald-800'
            : 'bg-violet-50 text-violet-700 border-violet-200 dark:bg-violet-950/40 dark:text-violet-400 dark:border-violet-800';
    return (
        <span className={`inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium border ${styles}`}>
            {status === 'open' ? 'Open' : 'Closed'}
        </span>
    );
};

type TimelineItem =
    | { type: 'issue'; created_at: string; number: number; title: string; state: string; author: string; author_username?: string | null }
    | { type: 'comment'; id: number; author: string; author_username: string; body: string; created_at: string; updated_at: string };

const formatDate = (dateStr: string) =>
    new Date(dateStr).toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
    });

export function IssueDetail() {
    const { project } = useProject();
    const { issueNumber } = useParams<{ issueNumber: string }>();
    const navigate = useNavigate();

    const [newComment, setNewComment] = useState('');
    const [editingId, setEditingId] = useState<number | null>(null);
    const [editingContent, setEditingContent] = useState('');
    const typingStopTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

    const { typingUsers } = useTypingIndicator({});

    const no = Number(issueNumber || 0);

    const {
        data: issue,
        isLoading,
        isError,
        error,
        refetch: refetchIssue,
    } = useQuery({
        queryKey: ['projectIssueDetail', project?.name, no],
        queryFn: async () => {
            const resp = await issueGet({
                path: { project: project!.name, number: no },
            });
            return resp.data?.data ?? null;
        },
        enabled: !!project?.name && !!no,
    });

    const {
        data: commentsRaw,
        isLoading: commentsLoading,
        refetch: refetchComments,
    } = useQuery({
        queryKey: ['projectIssueComments', project?.name, no],
        queryFn: async () => {
            const resp = await issueCommentList({
                path: { project: project!.name, number: no },
            });
            return resp.data?.data ?? null;
        },
        enabled: !!project?.name && !!no,
    });

    const comments: IssueCommentResponse[] = (commentsRaw as { comments?: IssueCommentResponse[] })?.comments ?? [];

    const { data: linkedReposRaw } = useQuery({
        queryKey: ['issueLinkedRepos', project?.name, no],
        queryFn: async () => {
            const resp = await issueRepoList({
                path: { project: project!.name, number: no },
            });
            return resp.data?.data;
        },
        enabled: !!project?.name && !!no,
    });

    const linkedRepos = (linkedReposRaw as { repos?: { repo: string; repo_name: string }[] })?.repos ?? [];

    const [triageDismissed, setTriageDismissed] = useState(false);

    const { data: triageData } = useQuery({
        queryKey: ['issueTriage', project?.name, no],
        queryFn: async () => {
            const resp = await triageIssue({
                path: { project: project!.name },
                query: { issue_number: no },
            });
            return resp.data?.data ?? null;
        },
        enabled: !!project?.name && !!no && !triageDismissed,
    });

    const applyLabelsMutation = useMutation({
        mutationFn: async (names: string[]) => {
            await issueLabelAddBulk({
                path: { project: project!.name, number: no },
                body: { names },
            });
        },
        onSuccess: () => {
            toast.success('Labels applied');
            setTriageDismissed(true);
            refetchComments();
        },
        onError: (err: unknown) => {
            toast.error(getApiErrorMessage(err, 'Failed to apply labels'));
        },
    });

    const timeline: TimelineItem[] = [];

    if (issue) {
        timeline.push({
            type: 'issue',
            created_at: issue.created_at,
            number: issue.number,
            title: issue.title,
            state: issue.state,
            author: issue.author,
            author_username: issue.author_username,
        });
    }

    comments.forEach((c) => timeline.push({ type: 'comment' as const, id: c.id, author: c.author, author_username: c.author_username ?? '', body: c.body, created_at: c.created_at, updated_at: c.updated_at }));

    const createCommentMutation = useMutation({
        mutationFn: async (body: string) => {
            await issueCommentCreate({
                path: { project: project!.name, number: no },
                body: { body },
            });
        },
        onSuccess: () => {
            toast.success('Comment added');
            setNewComment('');
            refetchComments();
        },
        onError: (err: unknown) => {
            toast.error(getApiErrorMessage(err, 'Failed to add comment'));
        },
    });

    const deleteCommentMutation = useMutation({
        mutationFn: async (commentId: number) => {
            await issueCommentDelete({
                path: { project: project!.name, number: no, comment_id: commentId },
            });
        },
        onSuccess: () => {
            toast.success('Comment deleted');
            refetchComments();
        },
        onError: (err: unknown) => {
            toast.error(getApiErrorMessage(err, 'Failed to delete comment'));
        },
    });

    const updateCommentMutation = useMutation({
        mutationFn: async (vars: { commentId: number; body: string }) => {
            await issueCommentUpdate({
                path: { project: project!.name, number: no, comment_id: vars.commentId },
                body: { body: vars.body },
            });
        },
        onSuccess: () => {
            toast.success('Comment updated');
            setEditingId(null);
            setEditingContent('');
            refetchComments();
        },
        onError: (err: unknown) => {
            toast.error(getApiErrorMessage(err, 'Failed to update comment'));
        },
    });

    const toggleIssueMutation = useMutation({
        mutationFn: async () => {
            if (issue?.state === 'open') {
                await issueClose({ path: { project: project!.name, number: no } });
            } else {
                await issueReopen({ path: { project: project!.name, number: no } });
            }
        },
        onSuccess: () => {
            toast.success(issue?.state === 'open' ? 'Issue closed' : 'Issue reopened');
            refetchIssue();
        },
        onError: (err: unknown) => {
            toast.error(getApiErrorMessage(err, 'Failed to update issue'));
        },
    });

    if (!project) return null;

    if (isLoading) {
        return (
            <div className="flex items-center justify-center h-64">
                <Spinner />
            </div>
        );
    }

    if (isError || !issue) {
        return (
            <div className="p-6">
                <div className="rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-destructive text-sm flex items-center gap-2">
                    <AlertTriangle className="h-4 w-4 flex-shrink-0" />
                    <strong>Error:</strong>{' '}
                    {error instanceof Error ? error.message : 'Failed to load issue'}
                </div>
            </div>
        );
    }

    return (
        <div className="flex-1 overflow-auto">
            {/* ── Header ── */}
            <div className="border-b">
                <div className="flex items-center justify-between px-6 py-3">
                    <button
                        onClick={() => navigate(`/project/${project.name}/issues`)}
                        className="flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors"
                    >
                        <ArrowLeft className="h-4 w-4" />
                        Back to Issues
                    </button>
                    <div className="flex items-center gap-2">
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => toggleIssueMutation.mutate()}
                            disabled={toggleIssueMutation.isPending}
                        >
                            {issue.state === 'open' ? 'Close Issue' : 'Reopen Issue'}
                        </Button>
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => navigate(`/project/${project.name}/issues/${no}/edit`)}
                        >
                            <SquarePen className="mr-1.5 h-3.5 w-3.5" />
                            Edit
                        </Button>
                    </div>
                </div>
            </div>

            {/* ── Content ── */}
            <div className="max-w-5xl mx-auto px-6 py-6">
                <div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
                    {/* ── Main column ── */}
                    <div className="lg:col-span-3 space-y-0">
                        {/* Issue title */}
                        <div className="mb-6">
                            <h1 className="text-2xl font-semibold text-foreground leading-tight">
                                <span className="text-muted-foreground font-normal mr-2">#{issue.number}</span>
                                {issue.title}
                            </h1>
                            <div className="mt-2.5 flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
                                <StatusBadge status={issue.state} />
                                <span className="text-xs">
                                    Opened by <span className="font-medium text-foreground">{issue.author_username || issue.author}</span>
                                </span>
                                <span className="text-muted-foreground/40">·</span>
                                <span className="text-xs">{formatDate(issue.created_at)}</span>
                            </div>

                            {/* Description */}
                            {issue.body && (
                                <div className="mt-4 rounded-lg border bg-muted/30 p-4">
                                    <ContentRenderer content={issue.body} />
                                </div>
                            )}

                            {/* AI Triage Suggestions */}
                            {triageData?.suggestions && !triageDismissed && (
                                <div className="mt-4 rounded-lg border border-amber-200 bg-amber-50 dark:bg-amber-950/30 dark:border-amber-800 p-4">
                                    <div className="flex items-start gap-3">
                                        <Lightbulb className="h-5 w-5 text-amber-500 mt-0.5 flex-shrink-0" />
                                        <div className="flex-1 min-w-0">
                                            <div className="flex items-center gap-2 mb-1">
                                                <span className="text-sm font-medium text-amber-700 dark:text-amber-400">
                                                    AI Triage
                                                </span>
                                                <span className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${
                                                    triageData.suggestions.priority === 'high'
                                                        ? 'bg-red-100 text-red-700 dark:bg-red-950/50 dark:text-red-400'
                                                        : triageData.suggestions.priority === 'medium'
                                                        ? 'bg-orange-100 text-orange-700 dark:bg-orange-950/50 dark:text-orange-400'
                                                        : 'bg-green-100 text-green-700 dark:bg-green-950/50 dark:text-green-400'
                                                }`}>
                                                    {triageData.suggestions.priority} priority
                                                </span>
                                            </div>
                                            <p className="text-sm text-amber-800 dark:text-amber-300 mb-3">
                                                {triageData.suggestions.reasoning}
                                            </p>
                                            {triageData.suggestions.suggested_labels.length > 0 && (
                                                <div className="flex flex-wrap gap-1.5 mb-3">
                                                    {triageData.suggestions.suggested_labels.map((label) => (
                                                        <span
                                                            key={label}
                                                            className="inline-flex items-center px-2 py-0.5 rounded-md text-xs font-medium bg-amber-100 text-amber-800 dark:bg-amber-950/50 dark:text-amber-300"
                                                        >
                                                            {label}
                                                        </span>
                                                    ))}
                                                </div>
                                            )}
                                            <div className="flex items-center gap-2">
                                                <Button
                                                    size="sm"
                                                    variant="default"
                                                    className="h-7 px-3 text-xs bg-amber-600 hover:bg-amber-700 text-white"
                                                    onClick={() =>
                                                        applyLabelsMutation.mutate(
                                                            triageData.suggestions!.suggested_labels
                                                        )
                                                    }
                                                    disabled={applyLabelsMutation.isPending || triageData.suggestions.suggested_labels.length === 0}
                                                >
                                                    <Check className="mr-1 h-3 w-3" />
                                                    {applyLabelsMutation.isPending ? 'Applying…' : 'Accept'}
                                                </Button>
                                                <Button
                                                    size="sm"
                                                    variant="ghost"
                                                    className="h-7 px-3 text-xs text-amber-700 dark:text-amber-400"
                                                    onClick={() => setTriageDismissed(true)}
                                                >
                                                    <X className="mr-1 h-3 w-3" />
                                                    Ignore
                                                </Button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            )}
                        </div>

                        {/* ── Timeline ── */}
                        {commentsLoading ? (
                            <div className="flex items-center justify-center h-24">
                                <Spinner />
                            </div>
                        ) : (
                            <div className="relative">
                                {/* Vertical line */}
                                <div className="absolute left-3.5 top-0 bottom-0 w-px bg-border" />

                                {timeline.length === 0 ? (
                                    <div className="flex flex-col items-center justify-center py-12 text-center">
                                        <MessageSquare className="mb-3 h-8 w-8 text-muted-foreground/30" />
                                        <p className="text-sm text-muted-foreground">No activity yet.</p>
                                    </div>
                                ) : (
                                    <div className="space-y-0">
                                        {timeline.map((item, index) => {
                                            if (item.type === 'issue') {
                                                return (
                                                    <div key={`issue-${item.number}-${index}`} className="relative flex gap-4 pb-6">
                                                        <div className="flex-shrink-0 w-7 h-7 rounded-full bg-primary/10 border border-primary/20 flex items-center justify-center z-10">
                                                            <Edit className="h-3.5 w-3.5 text-primary" />
                                                        </div>
                                                        <div className="flex-1 pt-0.5">
                                                            <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm">
                                                                <span className="font-medium text-foreground">
                                                                    {item.author_username || item.author}
                                                                </span>
                                                                <span className="text-muted-foreground">opened this issue</span>
                                                                <span className="text-xs text-muted-foreground/60">
                                                                    {formatDate(item.created_at)}
                                                                </span>
                                                            </div>
                                                        </div>
                                                    </div>
                                                );
                                            }

                                            const comment = item;
                                            const isEditing = editingId === comment.id;

                                            return (
                                                <div key={`comment-${comment.id}-${index}`} className="relative flex gap-4 pb-6">
                                                    <div className="flex-shrink-0 w-7 h-7 rounded-full bg-muted border border-border flex items-center justify-center z-10">
                                                        <User className="h-3.5 w-3.5 text-muted-foreground" />
                                                    </div>
                                                    <div className="flex-1">
                                                        <div className="rounded-lg border bg-background overflow-hidden">
                                                            {/* Comment header */}
                                                            <div className="flex items-center gap-3 border-b bg-muted/40 px-4 py-2.5">
                                                                <span className="text-sm font-medium text-foreground">
                                                                    {comment.author_username || comment.author}
                                                                </span>
                                                                <span className="text-xs text-muted-foreground">
                                                                    commented {formatDate(comment.updated_at)}
                                                                </span>
                                                                {!isEditing && (
                                                                    <div className="ml-auto flex items-center gap-1">
                                                                        <button
                                                                            onClick={() => {
                                                                                setEditingId(comment.id);
                                                                                setEditingContent(comment.body);
                                                                            }}
                                                                            className="p-1 text-muted-foreground hover:text-foreground transition-colors"
                                                                            title="Edit comment"
                                                                        >
                                                                            <Pencil className="h-3.5 w-3.5" />
                                                                        </button>
                                                                        <button
                                                                            onClick={() => deleteCommentMutation.mutate(comment.id)}
                                                                            disabled={deleteCommentMutation.isPending}
                                                                            className="p-1 text-muted-foreground hover:text-destructive transition-colors"
                                                                            title="Delete comment"
                                                                        >
                                                                            <Trash2 className="h-3.5 w-3.5" />
                                                                        </button>
                                                                    </div>
                                                                )}
                                                            </div>

                                                            {/* Comment body */}
                                                            <div className="p-4">
                                                                {isEditing ? (
                                                                    <div className="space-y-3">
                                                                        <Textarea
                                                                            value={editingContent}
                                                                            onChange={(e) => setEditingContent(e.target.value)}
                                                                            rows={4}
                                                                            className="resize-none text-sm"
                                                                            autoFocus
                                                                        />
                                                                        <div className="flex justify-end gap-2">
                                                                            <Button
                                                                                variant="outline"
                                                                                size="sm"
                                                                                onClick={() => setEditingId(null)}
                                                                            >
                                                                                Cancel
                                                                            </Button>
                                                                            <Button
                                                                                size="sm"
                                                                                onClick={() =>
                                                                                    updateCommentMutation.mutate({
                                                                                        commentId: comment.id,
                                                                                        body: editingContent,
                                                                                    })
                                                                                }
                                                                                disabled={updateCommentMutation.isPending || !editingContent.trim()}
                                                                            >
                                                                                {updateCommentMutation.isPending ? 'Saving…' : 'Save'}
                                                                            </Button>
                                                                        </div>
                                                                    </div>
                                                                ) : (
                                                                    <ContentRenderer content={comment.body} />
                                                                )}
                                                            </div>
                                                        </div>
                                                    </div>
                                                </div>
                                            );
                                        })}
                                    </div>
                                )}
                            </div>
                        )}

                        {/* ── Add comment ── */}
                        <div className="mt-6 rounded-lg border bg-background overflow-hidden">
                            <div className="p-4">
                                <Textarea
                                    value={newComment}
                                    onChange={(e) => {
                                        const v = e.target.value;
                                        setNewComment(v);
                                        if (v && typingStopTimer.current) { clearTimeout(typingStopTimer.current); typingStopTimer.current = null; }
                                        if (v && !typingStopTimer.current) { typingStopTimer.current = setTimeout(() => { typingStopTimer.current = null; }, 1500); }
                                    }}
                                    placeholder="Leave a comment…"
                                    rows={4}
                                    className="resize-none mb-3 text-sm"
                                />
                                <div className="flex justify-end">
                                    <Button
                                        onClick={() => {
                                            if (!newComment.trim()) { toast.error('Comment cannot be empty'); return; }
                                            if (typingStopTimer.current) { clearTimeout(typingStopTimer.current); typingStopTimer.current = null; }
                                            createCommentMutation.mutate(newComment.trim());
                                        }}
                                        disabled={createCommentMutation.isPending || !newComment.trim()}
                                    >
                                        {createCommentMutation.isPending ? 'Posting…' : 'Comment'}
                                    </Button>
                                </div>
                                {typingUsers.length > 0 && (
                                    <div className="mt-1.5 flex items-center gap-1.5">
                                        <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>
                        </div>
                    </div>

                    {/* ── Sidebar ── */}
                    <div className="lg:col-span-1 space-y-5">
                        {/* Linked Repositories */}
                        {linkedRepos.length > 0 && (
                            <div>
                                <h3 className="mb-2.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                                    Linked Repositories
                                </h3>
                                <div className="rounded-lg border overflow-hidden">
                                    <div className="divide-y divide-border">
                                        {linkedRepos.map((repo) => (
                                            <button
                                                key={repo.repo}
                                                onClick={() =>
                                                    navigate(`/repository/${project.name}/${repo.repo_name}`)
                                                }
                                                className="w-full flex items-center gap-2 p-3 text-left hover:bg-muted/40 transition-colors"
                                            >
                                                <svg
                                                    className="h-4 w-4 flex-shrink-0 text-muted-foreground"
                                                    fill="none"
                                                    viewBox="0 0 24 24"
                                                    stroke="currentColor"
                                                >
                                                    <path
                                                        strokeLinecap="round"
                                                        strokeLinejoin="round"
                                                        strokeWidth={1.5}
                                                        d="M3 7v10a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-6l-2-2H5a2 2 0 0 0-2 2z"
                                                    />
                                                </svg>
                                                <span className="text-sm truncate text-foreground/80">{repo.repo_name}</span>
                                            </button>
                                        ))}
                                    </div>
                                </div>
                            </div>
                        )}

                        {/* Details */}
                        <div>
                            <h3 className="mb-2.5 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
                                Details
                            </h3>
                            <div className="rounded-lg border overflow-hidden divide-y divide-border">
                                <div className="flex items-center justify-between px-3 py-2.5">
                                    <span className="text-xs text-muted-foreground">Status</span>
                                    <StatusBadge status={issue.state} />
                                </div>
                                <div className="flex items-center justify-between px-3 py-2.5">
                                    <span className="text-xs text-muted-foreground">Author</span>
                                    <span className="text-xs font-medium text-foreground/80">
                                        {issue.author_username || issue.author}
                                    </span>
                                </div>
                                <div className="flex items-center justify-between px-3 py-2.5">
                                    <span className="text-xs text-muted-foreground">Created</span>
                                    <span className="text-xs text-foreground/80">
                                        {new Date(issue.created_at).toLocaleDateString()}
                                    </span>
                                </div>
                                {issue.updated_at && issue.updated_at !== issue.created_at && (
                                    <div className="flex items-center justify-between px-3 py-2.5">
                                        <span className="text-xs text-muted-foreground">Updated</span>
                                        <span className="text-xs text-foreground/80">
                                            {new Date(issue.updated_at).toLocaleDateString()}
                                        </span>
                                    </div>
                                )}
                                {issue.closed_at && (
                                    <div className="flex items-center justify-between px-3 py-2.5">
                                        <span className="text-xs text-muted-foreground">Closed</span>
                                        <span className="text-xs text-foreground/80">
                                            {new Date(issue.closed_at).toLocaleDateString()}
                                        </span>
                                    </div>
                                )}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
}
