import { useEffect, useRef, useState } from 'react';
import { Modal, Button, Checkbox, Input, TextField } from '@heroui/react';
import { CloudArrowUpIcon, PaperClipIcon, TrashIcon, ClipboardDocumentListIcon, TagIcon, CheckCircleIcon } from '@heroicons/react/24/solid';
import { Field } from '@/Components/ui/Field';
import { SelectField } from '@/Components/ui/SelectField';
import { ConfirmDialog } from '@/Components/ui/ConfirmDialog';
import { AttachmentPreviewModal, AttachmentThumb } from '@/Components/Board/AttachmentPreviewModal';
import { useAll, useDelete, useList, useUpdate } from '@/hooks/useResource';
import { useAuth } from '@/hooks/useAuth';
import { api } from '@/lib/api';
import { ROLE_TEXT } from '@/lib/roleColors';
import { useMutation, useQueryClient } from '@tanstack/react-query';

interface UserOpt { id: number; name: string; }
interface Label { id: number; name: string; color: string; }
interface Comment { id: number; body: string; created_at: string; user: { id: number; name: string; role?: string }; parent_id: number | null; parent?: { id: number; user: { id: number; name: string } } | null; }
interface Attachment { id: number; original_name: string; url: string; user: { id: number; name: string }; }
interface ChecklistItem { id: number; title: string; is_done: boolean; position: number; }

interface TaskDetail {
    id: number;
    title: string;
    description: string | null;
    assigned_to: number | null;
    created_by: number | null;
    start_date: string | null;
    due_date: string | null;
    labels: Label[];
    comments: Comment[];
    attachments: Attachment[];
    checklist_items: ChecklistItem[];
}

// Groups replies under their parent so the thread reads like Instagram: each
// reply nests one level under whichever comment it answers, indenting deeper
// for a reply-to-a-reply instead of flattening everything to one level.
function groupByParent(comments: Comment[]): Map<number | null, Comment[]> {
    const byParent = new Map<number | null, Comment[]>();
    for (const c of comments) {
        const key = c.parent_id ?? null;
        if (!byParent.has(key)) byParent.set(key, []);
        byParent.get(key)!.push(c);
    }
    return byParent;
}

function CommentThread({
    comment, depth, byParent, onReply, onDelete,
}: {
    comment: Comment;
    depth: number;
    byParent: Map<number | null, Comment[]>;
    onReply: (c: Comment) => void;
    onDelete: (id: number) => void;
}) {
    const replies = byParent.get(comment.id) ?? [];

    return (
        <div className={depth > 0 ? 'pl-3 border-l-2 border-gray-100' : ''}>
            <div className="bg-white border border-gray-200 rounded-lg p-2 flex justify-between items-start gap-2">
                <div>
                    {comment.parent && (
                        <p className="text-[11px] text-sky-600 mb-0.5">
                            Membalas <span className="font-medium">@{comment.parent.user.name}</span>
                        </p>
                    )}
                    <p className={`text-xs font-semibold ${ROLE_TEXT[comment.user.role ?? ''] ?? 'text-gray-700'}`}>{comment.user.name}</p>
                    <p className="text-sm text-gray-600">{comment.body}</p>
                </div>
                <div className="flex items-center gap-2 shrink-0">
                    <button onClick={() => onReply(comment)} className="text-[11px] text-gray-400 hover:text-sky-600">
                        Balas
                    </button>
                    <button onClick={() => onDelete(comment.id)} className="text-gray-300 hover:text-red-600">
                        <TrashIcon className="w-3.5 h-3.5" />
                    </button>
                </div>
            </div>
            {replies.length > 0 && (
                <div className="flex flex-col gap-2 mt-2">
                    {replies.map((r) => (
                        <CommentThread key={r.id} comment={r} depth={depth + 1} byParent={byParent} onReply={onReply} onDelete={onDelete} />
                    ))}
                </div>
            )}
        </div>
    );
}

export function TaskModal({ boardId, taskId, isOpen, onOpenChange }: { boardId: number; taskId: number | null; isOpen: boolean; onOpenChange: (open: boolean) => void }) {
    const qc = useQueryClient();
    const { user, canWrite, canDelete, canEdit: checkCanEdit } = useAuth();
    const { data: board } = useAll<{ labels: Label[] }>(`board-${boardId}`, `/boards/${boardId}`);
    const { data: usersPage } = useList<UserOpt>('users-all', '/users', { per_page: 1000 });
    const users = usersPage?.data ?? [];
    const { data: task } = useAll<TaskDetail>(`task-${taskId}`, taskId ? `/tasks/${taskId}` : '', {}, !!taskId);

    const updateTask = useUpdate<TaskDetail>(`board-${boardId}`, '/tasks');
    const deleteTask = useDelete(`board-${boardId}`, '/tasks');
    const fileRef = useRef<HTMLInputElement>(null);

    const [title, setTitle] = useState('');
    const [description, setDescription] = useState('');
    const [assignedTo, setAssignedTo] = useState<number | null>(null);
    const [startDate, setStartDate] = useState('');
    const [dueDate, setDueDate] = useState('');
    const [commentBody, setCommentBody] = useState('');
    const [replyTo, setReplyTo] = useState<Comment | null>(null);
    const [newChecklistTitle, setNewChecklistTitle] = useState('');
    const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
    const [isDragOver, setIsDragOver] = useState(false);
    const [attachmentProgress, setAttachmentProgress] = useState(0);
    const [previewFile, setPreviewFile] = useState<Attachment | null>(null);

    useEffect(() => {
        if (task) {
            setTitle(task.title);
            setDescription(task.description ?? '');
            setAssignedTo(task.assigned_to);
            setStartDate(task.start_date ?? '');
            setDueDate(task.due_date ?? '');
        }
    }, [task]);

    const addComment = useMutation({
        mutationFn: () => api.post(`/tasks/${taskId}/comments`, { body: commentBody, parent_id: replyTo?.id ?? null }),
        onSuccess: () => { setCommentBody(''); setReplyTo(null); qc.invalidateQueries({ queryKey: [`task-${taskId}`] }); },
    });

    const deleteComment = useMutation({
        mutationFn: (id: number) => api.delete(`/task-comments/${id}`),
        onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }),
    });

    const uploadAttachment = useMutation({
        mutationFn: (file: File) => {
            const fd = new FormData();
            fd.append('file', file);
            return api.post(`/tasks/${taskId}/attachments`, fd, {
                onUploadProgress: (e) => setAttachmentProgress(e.total ? Math.round((e.loaded / e.total) * 100) : 0),
            });
        },
        onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }),
        onSettled: () => setAttachmentProgress(0),
    });

    const deleteAttachment = useMutation({
        mutationFn: (id: number) => api.delete(`/task-attachments/${id}`),
        onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }),
    });

    const addChecklistItem = useMutation({
        mutationFn: () => api.post(`/tasks/${taskId}/checklist-items`, { title: newChecklistTitle }),
        onSuccess: () => { setNewChecklistTitle(''); qc.invalidateQueries({ queryKey: [`task-${taskId}`] }); },
    });

    const toggleChecklistItem = useMutation({
        mutationFn: ({ id, is_done }: { id: number; is_done: boolean }) => api.patch(`/checklist-items/${id}`, { is_done }),
        onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }),
    });

    const deleteChecklistItem = useMutation({
        mutationFn: (id: number) => api.delete(`/checklist-items/${id}`),
        onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }),
    });

    const toggleLabel = useMutation({
        mutationFn: (labelIds: number[]) => api.put(`/tasks/${taskId}/labels`, { label_ids: labelIds }),
        onSuccess: () => { qc.invalidateQueries({ queryKey: [`task-${taskId}`] }); qc.invalidateQueries({ queryKey: [`board-${boardId}`] }); },
    });

    function handleSubmit() {
        if (!taskId) return;
        updateTask.mutate(
            { id: taskId, data: { title, description, assigned_to: assignedTo, start_date: startDate || null, due_date: dueDate || null } },
            { onSuccess: () => qc.invalidateQueries({ queryKey: [`task-${taskId}`] }) },
        );
    }

    if (!task) return null;

    const allowBoardEdit = checkCanEdit('board');
    const canEdit = allowBoardEdit || task.created_by === user?.id;
    const canDeleteTask = canDelete('board') && (allowBoardEdit || task.created_by === user?.id);
    const userOptions = users.map((u) => ({ id: u.id, label: u.name }));
    const selectedLabelIds = new Set(task.labels.map((l) => l.id));

    return (
        <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
            <Modal.Backdrop>
                <Modal.Container>
                    <Modal.Dialog className="max-w-2xl w-full bg-gray-50">
                        <Modal.Header className="flex-row! items-center gap-3 pb-3 mb-2 border-b border-gray-200">
                            <Modal.Icon className="bg-sky-100 text-sky-600">
                                <ClipboardDocumentListIcon className="w-5 h-5" />
                            </Modal.Icon>
                            <Modal.Heading>Detail Tugas</Modal.Heading>
                        </Modal.Header>
                        <Modal.CloseTrigger />
                        <Modal.Body>
                            <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-4 gap-y-4 max-h-[65vh] overflow-y-auto pl-2 pr-3 py-1">
                                {!canEdit && (
                                    <p className="sm:col-span-2 text-xs text-amber-700 bg-amber-50 border border-amber-100 rounded-lg px-3 py-2">
                                        Hanya pembuat tugas ini (atau Admin/Koordinator) yang bisa mengubah detailnya. Anda tetap bisa mengisi checklist, lampiran, dan komentar.
                                    </p>
                                )}
                                <Field label="Judul" value={title} onChange={setTitle} required disabled={!canEdit} />
                                <SelectField
                                    label="Penanggung Jawab"
                                    items={userOptions}
                                    selectedKey={assignedTo}
                                    onSelectionChange={(k) => setAssignedTo(k ? Number(k) : null)}
                                    placeholder="Belum ditugaskan"
                                    clearable
                                    isDisabled={!canEdit}
                                />
                                <div className="sm:col-span-2">
                                    <Field label="Deskripsi" value={description} onChange={setDescription} multiline placeholder="Detail tugas..." disabled={!canEdit} />
                                </div>

                                <Field label="Mulai (opsional)" type="date" value={startDate} onChange={setStartDate} disabled={!canEdit} />
                                <Field label="Tenggat (opsional)" type="date" value={dueDate} onChange={setDueDate} disabled={!canEdit} />

                                <div className="sm:col-span-2">
                                    <p className="text-sm font-medium text-gray-700 mb-1.5 flex items-center gap-1"><TagIcon className="w-4 h-4 text-gray-400" /> Label</p>
                                    <div className="flex flex-wrap gap-1.5">
                                        {(board?.labels ?? []).map((l) => {
                                            const active = selectedLabelIds.has(l.id);
                                            return (
                                                <button
                                                    key={l.id}
                                                    type="button"
                                                    disabled={!canEdit}
                                                    onClick={() => {
                                                        const next = active ? [...selectedLabelIds].filter((id) => id !== l.id) : [...selectedLabelIds, l.id];
                                                        toggleLabel.mutate(next);
                                                    }}
                                                    className="text-xs font-semibold px-2 py-1 rounded-full border transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
                                                    style={active ? { backgroundColor: l.color, color: '#fff', borderColor: l.color } : { backgroundColor: '#fff', borderColor: '#e5e7eb', color: '#6b7280' }}
                                                >
                                                    {l.name}
                                                </button>
                                            );
                                        })}
                                        {(board?.labels ?? []).length === 0 && <span className="text-xs text-gray-400">Belum ada label di papan ini.</span>}
                                    </div>
                                </div>

                                <div className="border-t border-gray-200 sm:col-span-2 pt-4">
                                    <p className="text-sm font-medium text-gray-700 mb-1.5 flex items-center gap-1"><CheckCircleIcon className="w-4 h-4 text-gray-400" /> Checklist</p>
                                    <div className="flex flex-col gap-1.5 mb-2">
                                        {task.checklist_items.map((item) => (
                                            <div key={item.id} className="flex items-center justify-between gap-2 bg-white border border-gray-200 rounded-lg px-2.5 py-1.5">
                                                <Checkbox
                                                    isSelected={item.is_done}
                                                    onChange={(v) => toggleChecklistItem.mutate({ id: item.id, is_done: v })}
                                                >
                                                    <Checkbox.Content className="gap-2">
                                                        <Checkbox.Control>
                                                            <Checkbox.Indicator />
                                                        </Checkbox.Control>
                                                        <span className={`text-sm ${item.is_done ? 'line-through text-gray-400' : 'text-gray-700'}`}>{item.title}</span>
                                                    </Checkbox.Content>
                                                </Checkbox>
                                                <button onClick={() => deleteChecklistItem.mutate(item.id)} className="text-gray-300 hover:text-red-600 shrink-0">
                                                    <TrashIcon className="w-3.5 h-3.5" />
                                                </button>
                                            </div>
                                        ))}
                                        {task.checklist_items.length === 0 && <p className="text-xs text-gray-400">Belum ada checklist.</p>}
                                    </div>
                                    <div className="flex gap-2">
                                        <TextField
                                            value={newChecklistTitle}
                                            onChange={setNewChecklistTitle}
                                            aria-label="Tambah item checklist"
                                            className="flex-1"
                                        >
                                            <Input
                                                placeholder="Tambah item checklist..."
                                                fullWidth
                                                onKeyDown={(e) => { if (e.key === 'Enter' && newChecklistTitle.trim()) addChecklistItem.mutate(); }}
                                            />
                                        </TextField>
                                        <Button variant="outline" onPress={() => newChecklistTitle.trim() && addChecklistItem.mutate()}>Tambah</Button>
                                    </div>
                                </div>

                                <div className="border-t border-gray-200 sm:col-span-2 pt-4 flex flex-col gap-4">
                                    <div>
                                        <p className="text-sm font-medium text-gray-700 mb-1.5 flex items-center gap-1"><PaperClipIcon className="w-4 h-4 text-gray-400" /> Lampiran</p>
                                        <div className="flex flex-col gap-1.5 mb-2">
                                            {task.attachments.map((a) => (
                                                <div key={a.id} className="flex items-center gap-2 bg-white border border-gray-200 rounded-lg px-2.5 py-1.5">
                                                    <button type="button" onClick={() => setPreviewFile(a)} className="shrink-0">
                                                        <AttachmentThumb file={a} />
                                                    </button>
                                                    <button
                                                        type="button"
                                                        onClick={() => setPreviewFile(a)}
                                                        className="text-xs text-sky-600 truncate hover:underline text-left flex-1 min-w-0"
                                                    >
                                                        {a.original_name}
                                                    </button>
                                                    <button onClick={() => deleteAttachment.mutate(a.id)} className="text-gray-300 hover:text-red-600 shrink-0">
                                                        <TrashIcon className="w-3.5 h-3.5" />
                                                    </button>
                                                </div>
                                            ))}
                                            {task.attachments.length === 0 && <p className="text-xs text-gray-400">Belum ada lampiran.</p>}
                                        </div>
                                        <div
                                            role="button"
                                            aria-busy={uploadAttachment.isPending}
                                            tabIndex={uploadAttachment.isPending ? -1 : 0}
                                            onClick={() => !uploadAttachment.isPending && fileRef.current?.click()}
                                            onKeyDown={(e) => !uploadAttachment.isPending && e.key === 'Enter' && fileRef.current?.click()}
                                            onDragOver={(e) => { e.preventDefault(); if (!uploadAttachment.isPending) setIsDragOver(true); }}
                                            onDragLeave={() => setIsDragOver(false)}
                                            onDrop={(e) => {
                                                e.preventDefault();
                                                setIsDragOver(false);
                                                if (uploadAttachment.isPending) return;
                                                const f = e.dataTransfer.files[0];
                                                if (f) uploadAttachment.mutate(f);
                                            }}
                                            onPaste={(e) => {
                                                if (uploadAttachment.isPending) return;
                                                const f = Array.from(e.clipboardData.items).find((item) => item.kind === 'file')?.getAsFile();
                                                if (f) uploadAttachment.mutate(f);
                                            }}
                                            className={`flex flex-col items-center justify-center gap-1 rounded-xl border-2 border-dashed px-4 py-4 text-center transition-colors ${
                                                uploadAttachment.isPending
                                                    ? 'cursor-wait border-sky-300 bg-sky-50/60'
                                                    : isDragOver
                                                    ? 'cursor-pointer border-sky-500 bg-sky-50'
                                                    : 'cursor-pointer border-gray-300 bg-white hover:border-sky-300 hover:bg-gray-50'
                                            }`}
                                        >
                                            {uploadAttachment.isPending ? (
                                                <div className="w-full max-w-[200px] space-y-1">
                                                    <div className="flex items-center justify-between text-xs font-medium text-sky-700">
                                                        <span>Mengunggah...</span>
                                                        <span>{attachmentProgress}%</span>
                                                    </div>
                                                    <div className="h-1.5 w-full overflow-hidden rounded-full bg-sky-100">
                                                        <div
                                                            className="h-full rounded-full bg-sky-500 transition-[width] duration-150"
                                                            style={{ width: `${attachmentProgress}%` }}
                                                        />
                                                    </div>
                                                </div>
                                            ) : (
                                                <>
                                                    <CloudArrowUpIcon className="w-5 h-5 text-gray-400" />
                                                    <p className="text-xs text-gray-600">
                                                        <span className="font-medium text-sky-600">Klik untuk unggah</span> atau seret file
                                                    </p>
                                                </>
                                            )}
                                        </div>
                                        <input
                                            ref={fileRef}
                                            type="file"
                                            disabled={uploadAttachment.isPending}
                                            className="hidden"
                                            onChange={(e) => { const f = e.target.files?.[0]; if (f) uploadAttachment.mutate(f); e.target.value = ''; }}
                                        />
                                    </div>

                                    <div>
                                        <p className="text-sm font-medium text-gray-700 mb-1.5">Komentar</p>
                                        <div className="flex flex-col gap-2 mb-2 max-h-48 overflow-y-auto">
                                            {(() => {
                                                const byParent = groupByParent(task.comments);
                                                const roots = byParent.get(null) ?? [];

                                                return roots.map((c) => (
                                                    <CommentThread key={c.id} comment={c} depth={0} byParent={byParent} onReply={setReplyTo} onDelete={(id) => deleteComment.mutate(id)} />
                                                ));
                                            })()}
                                            {task.comments.length === 0 && <p className="text-xs text-gray-400">Belum ada komentar.</p>}
                                        </div>
                                        {replyTo && (
                                            <div className="flex items-center justify-between text-xs text-sky-600 bg-sky-50 rounded-lg px-2 py-1 mb-1.5">
                                                <span>Membalas <span className="font-medium">@{replyTo.user.name}</span></span>
                                                <button onClick={() => setReplyTo(null)} className="text-sky-400 hover:text-sky-700">
                                                    <TrashIcon className="w-3 h-3" />
                                                </button>
                                            </div>
                                        )}
                                        <div className="flex gap-2">
                                            <TextField
                                                value={commentBody}
                                                onChange={setCommentBody}
                                                aria-label="Tulis komentar"
                                                className="flex-1"
                                            >
                                                <Input
                                                    placeholder={replyTo ? `Balas ${replyTo.user.name}...` : 'Tulis komentar...'}
                                                    fullWidth
                                                    onKeyDown={(e) => { if (e.key === 'Enter' && commentBody.trim()) addComment.mutate(); }}
                                                />
                                            </TextField>
                                            <Button variant="outline" onPress={() => commentBody.trim() && addComment.mutate()}>Kirim</Button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </Modal.Body>
                        <Modal.Footer className="border-t border-gray-200 pt-3 mt-2 justify-between!">
                            {canDeleteTask ? (
                                <Button variant="outline" onPress={() => setConfirmDeleteOpen(true)}>
                                    Hapus Tugas
                                </Button>
                            ) : <span />}
                            <div className="flex gap-2">
                                <Button variant="outline" onPress={() => onOpenChange(false)}>Tutup</Button>
                                {canEdit && (
                                    <Button variant="primary" onPress={handleSubmit} isDisabled={updateTask.isPending}>
                                        {updateTask.isPending ? 'Menyimpan...' : 'Simpan Perubahan'}
                                    </Button>
                                )}
                            </div>
                        </Modal.Footer>
                    </Modal.Dialog>
                </Modal.Container>
            </Modal.Backdrop>

            <ConfirmDialog
                isOpen={confirmDeleteOpen}
                onOpenChange={setConfirmDeleteOpen}
                title="Hapus tugas ini?"
                description={`"${task.title}" akan dihapus permanen beserta komentar dan lampirannya.`}
                onConfirm={() => { if (taskId) { deleteTask.mutate(taskId); onOpenChange(false); } }}
            />

            <AttachmentPreviewModal file={previewFile} onOpenChange={(open) => !open && setPreviewFile(null)} />
        </Modal>
    );
}
