import React, { useState, useRef, useEffect, Suspense } from "react";
import dynamic from "next/dynamic";
const RichTextEditor = dynamic(() => import("./RichTextEditor"), { ssr: false });
import { Repeat, X, ChevronDown, Link } from "lucide-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faGoogle, faMicrosoft, faApple } from "@fortawesome/free-brands-svg-icons";
import { faServer, faFolder, IconDefinition } from "@fortawesome/free-solid-svg-icons";
import MdiIcon from "@mdi/react";
import { allIcons } from "./iconRegistry";
import { Task, KanbanStage, getPriorityBadge } from "./WeeklyView";

interface GridTaskBlockProps {
    task: Task;
    date: Date;
    activeDate: Date;
    cellDuration: number;
    darkMode: boolean;
    isProtected: boolean;
    editingTaskId: string | null;
    setEditingTaskId: (id: string | null) => void;
    updateTask: (id: string, title: string) => void;
    updateTaskNotes: (id: string, notes: string) => void;
    updateTaskUrl: (id: string, url: string) => void;
    updateTaskDuration: (id: string, duration: number) => void;
    toggleTask: (id: string) => void;
    deleteTask: (id: string) => void;
    toggleTaskRolling: (id: string) => void;
    setSelectedTaskForNotes: (task: Task) => void;
    setSelectedTaskForRecurrence: (task: Task) => void;
    handleDragStart: (e: React.DragEvent, task: Task) => void;
    handleDragEnd: (e: React.DragEvent) => void;
    getSlotHeight: (duration: number) => number;
    draggedTask: Task | null;
    addSubTask: (parentId: string, title: string) => void;
    toggleSubTask: (id: string) => void;
    updateSubTask: (id: string, title: string) => void;
    deleteSubTask: (id: string) => void;
    onSetEditingTaskId?: (id: string | null) => void;
    workingHoursStart: number;
    showTaskCheckboxes?: boolean;
    showProjectIcons?: boolean;
    showPriorityIcons?: boolean;
    priorityStyle?: string;
    projects?: any[];
    onProjectAssign?: (taskId: string, projectId: string | null) => void;
    kanbanStages?: KanbanStage[];
    weatherEnabled?: boolean;
    onMoveTask?: (taskId: string, targetDate: Date, targetTime: string) => void;
}

export function GridTaskBlock({
    task,
    date,
    activeDate,
    cellDuration,
    darkMode,
    isProtected,
    editingTaskId,
    setEditingTaskId,
    updateTask,
    updateTaskNotes,
    updateTaskUrl,
    updateTaskDuration,
    toggleTask,
    deleteTask,
    toggleTaskRolling,
    setSelectedTaskForNotes,
    setSelectedTaskForRecurrence,
    handleDragStart,
    handleDragEnd,
    getSlotHeight,
    draggedTask,
    addSubTask,
    toggleSubTask,
    updateSubTask,
    deleteSubTask,
    onSetEditingTaskId,
    workingHoursStart,
    showTaskCheckboxes,
    showProjectIcons,
    showPriorityIcons = true,
    priorityStyle = "eisenhower",
    projects,
    onProjectAssign,
    kanbanStages = [],
    weatherEnabled = false,
    onMoveTask,
}: GridTaskBlockProps) {
    const [isNotesOpen, setIsNotesOpen] = useState(false);
    const [notesValue, setNotesValue] = useState(task.markdownContent || "");
    const [isUrlOpen, setIsUrlOpen] = useState(false);
    const [urlValue, setUrlValue] = useState(task.url || "");
    const urlInputRef = useRef<HTMLInputElement>(null);
    const [isSubTasksOpen, setIsSubTasksOpen] = useState(false);
    const [isSubTaskInputOpen, setIsSubTaskInputOpen] = useState(false);
    const [newSubTaskTitle, setNewSubTaskTitle] = useState("");
    const [showProjectPicker, setShowProjectPicker] = useState(false);
    const [showMoveDialog, setShowMoveDialog] = useState(false);
    const [moveDate, setMoveDate] = useState('');
    const [moveTime, setMoveTime] = useState('');
    const notesRef = useRef<HTMLTextAreaElement>(null);
    const subTaskInputRef = useRef<HTMLInputElement>(null);
    const projectPickerRef = useRef<HTMLDivElement>(null);
    const moveDialogRef = useRef<HTMLDivElement>(null);

    // Touch: tap-to-reveal actions
    const [touchActive, setTouchActive] = useState(false);
    const blockRef = useRef<HTMLDivElement>(null);
    useEffect(() => {
        if (!touchActive) return;
        const handler = (e: Event) => {
            if (blockRef.current && !blockRef.current.contains(e.target as Node)) setTouchActive(false);
        };
        document.addEventListener("touchstart", handler);
        document.addEventListener("mousedown", handler);
        return () => { document.removeEventListener("touchstart", handler); document.removeEventListener("mousedown", handler); };
    }, [touchActive]);

    // Close project picker on outside click
    useEffect(() => {
        if (!showProjectPicker) return;
        const handler = (e: Event) => {
            if (projectPickerRef.current && !projectPickerRef.current.contains(e.target as Node)) {
                setShowProjectPicker(false);
            }
        };
        document.addEventListener("mousedown", handler);
        return () => document.removeEventListener("mousedown", handler);
    }, [showProjectPicker]);

    // Resize State
    const [isResizing, setIsResizing] = useState(false);
    const [resizeHeight, setResizeHeight] = useState<number | null>(null);
    const resizeStartY = useRef<number>(0);
    const resizeStartHeight = useRef<number>(0);

    // Focus notes when opened
    useEffect(() => {
        if (isNotesOpen && notesRef.current) {
            notesRef.current.focus();
        }
    }, [isNotesOpen]);

    // Focus URL input when opened
    useEffect(() => {
        if (isUrlOpen) setTimeout(() => urlInputRef.current?.focus(), 50);
    }, [isUrlOpen]);

    // Sync urlValue if task.url changes externally
    useEffect(() => { setUrlValue(task.url || ""); }, [task.url]);

    const handleNotesBlur = () => {
        if (notesValue !== task.markdownContent) {
            updateTaskNotes(task.id, notesValue);
        }
    };

    const handleUrlSave = (val: string) => {
        setIsUrlOpen(false);
        if (val.trim() !== (task.url || "")) {
            updateTaskUrl(task.id, val.trim());
        }
    };

    const insertMarkdown = (prefix: string, suffix: string = "") => {
        if (!notesRef.current) return;
        const start = notesRef.current.selectionStart;
        const end = notesRef.current.selectionEnd;
        const text = notesValue;
        const before = text.substring(0, start);
        const selection = text.substring(start, end);
        const after = text.substring(end);
        const newText = `${before}${prefix}${selection}${suffix}${after}`;
        setNotesValue(newText);
        setTimeout(() => {
            if (notesRef.current) {
                notesRef.current.focus();
                const newCursorPos = start + prefix.length + selection.length + suffix.length;
                notesRef.current.setSelectionRange(newCursorPos, newCursorPos);
            }
        }, 0);
    };

    const pixelsPerMinute = getSlotHeight(cellDuration) / cellDuration;

    useEffect(() => {
        if (!task.startTime) return;

        const handleResizeMove = (e: MouseEvent) => {
            if (!isResizing) return;
            const deltaY = e.clientY - resizeStartY.current;
            let newHeight = resizeStartHeight.current + deltaY;
            const minHeight = 15 * pixelsPerMinute;
            if (newHeight < minHeight) newHeight = minHeight;
            setResizeHeight(newHeight);
        };

        const handleResizeEnd = () => {
            if (!isResizing) return;
            setIsResizing(false);
            document.body.style.cursor = "";
            if (resizeHeight !== null) {
                const newDurationMins = Math.round(resizeHeight / pixelsPerMinute / 15) * 15;
                updateTaskDuration(task.id, newDurationMins);
            }
            setResizeHeight(null);
        };

        if (isResizing) {
            window.addEventListener("mousemove", handleResizeMove);
            window.addEventListener("mouseup", handleResizeEnd);
        }

        return () => {
            window.removeEventListener("mousemove", handleResizeMove);
            window.removeEventListener("mouseup", handleResizeEnd);
        };
    }, [isResizing, resizeHeight, pixelsPerMinute, task.id, updateTaskDuration, task.startTime]);

    // Conditional rendering should only happen after hooks
    if (!task.startTime) return null;

    const [startHour, startMinute] = task.startTime.split(":").map(Number);
    const startMinutes = startHour * 60 + startMinute;
    const topOffset = startMinutes * pixelsPerMinute;
    const duration = task.duration || 15;
    const baseHeight = duration * pixelsPerMinute;
    const currentHeight = isResizing && resizeHeight !== null ? resizeHeight : baseHeight;

    const onResizeStart = (e: React.MouseEvent) => {
        e.stopPropagation();
        e.preventDefault();
        setIsResizing(true);
        resizeStartY.current = e.clientY;
        resizeStartHeight.current = baseHeight;
        document.body.style.cursor = "ns-resize";
    };

    const onResizeKeyDown = (e: React.KeyboardEvent) => {
        if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;
        e.preventDefault();
        e.stopPropagation();
        const step = 15;
        const newDuration = e.key === 'ArrowUp'
            ? Math.min(duration + step, 480)
            : Math.max(duration - step, 15);
        if (newDuration !== duration) {
            updateTaskDuration(task.id, newDuration);
        }
    };

    return (
        <div
            ref={blockRef}
            className={`time-slot-task ${task.completed && !showTaskCheckboxes ? "completed" : ""} ${draggedTask?.id === task.id ? "dragging" : ""} ${touchActive ? "touch-active" : ""} ${showProjectPicker ? "picker-open" : ""}`}
            style={{
                position: "absolute",
                top: `${topOffset}px`,
                left: 0,
                right: 0,
                minHeight: `${Math.max(currentHeight, 20)}px`,
                height: isSubTasksOpen ? "auto" : `${currentHeight}px`,
                zIndex: isResizing || isNotesOpen || isSubTasksOpen ? 10 : 5,
                background: (isNotesOpen || isSubTasksOpen || isResizing) ? (darkMode ? "#2a2a2a" : "#ffffff") : "transparent",
                border: (isNotesOpen || isSubTasksOpen || isResizing) ? `1px solid ${darkMode ? "#404040" : "#e0e0e0"}` : "none",
                borderLeft: (() => {
                    const stageColor = task.kanbanStage ? kanbanStages.find(s => s.id === task.kanbanStage)?.color : null;
                    if (stageColor) return `4px solid ${stageColor}`;
                    if (task.project?.color) return `4px solid ${task.project.color}`;
                    return `4px solid transparent`;
                })(),
                borderRadius: (isNotesOpen || isSubTasksOpen || isResizing) ? "4px" : "0",
                padding: weatherEnabled ? "2px 30px 2px 8px" : "2px 4px 2px 8px",
                boxShadow: (isNotesOpen || isSubTasksOpen || isResizing) ? "0 1px 3px rgba(0,0,0,0.05)" : "none",
                display: "flex",
                flexDirection: "column",
                overflow: "visible !important",
            }}
            draggable={!editingTaskId && !isResizing}
            onDragStart={(e) => handleDragStart(e, task)}
            onDragEnd={handleDragEnd}
            onMouseLeave={(e) => {
                if (showProjectPicker) {
                    // Don't close if mouse moved into the project picker dropdown
                    const related = e.relatedTarget as HTMLElement | null;
                    if (related && projectPickerRef.current?.contains(related)) return;
                    setShowProjectPicker(false);
                }
            }}
            onClick={(e) => {
                e.stopPropagation();
                // Touch: toggle action toolbar on tap instead of toggling completion
                if (window.matchMedia("(pointer: coarse)").matches && editingTaskId !== task.id) {
                    const target = e.target as HTMLElement;
                    if (target.closest(".task-actions") || target.closest("button")) return;
                    setTouchActive(!touchActive);
                    return;
                }
                if (editingTaskId !== task.id) toggleTask(task.id);
            }}
        >
            <div style={{ display: "flex", alignItems: "center", gap: "0.25rem", width: "100%", justifyContent: "space-between" }}>
                {editingTaskId === task.id ? (
                    <form
                        onSubmit={(e) => {
                            e.preventDefault();
                            const input = e.currentTarget.elements.namedItem("title") as HTMLTextAreaElement;
                            updateTask(task.id, input.value || "");
                        }}
                        onClick={(e) => e.stopPropagation()}
                        style={{ width: "100%", paddingRight: "20px" }}
                    >
                        <textarea
                            name="title"
                            aria-label={`Edit task title: ${task.title}`}
                            autoFocus
                            defaultValue={task.title}
                            onBlur={(e) => updateTask(task.id, e.target.value)}
                            onKeyDown={(e) => {
                                if (e.key === "Escape") setEditingTaskId(null);
                                if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); e.currentTarget.blur(); }
                            }}
                            rows={(task.title?.split("\n").length) || 1}
                            className="weekly-task-text"
                            style={{ width: "100%", background: "transparent", border: "none", borderBottom: "1px solid var(--weekly-border)", outline: "none", resize: "none", overflow: "hidden", fontFamily: "inherit", lineHeight: "inherit" }}
                        />
                    </form>
                ) : (
                    <span
                        style={{
                            display: "flex",
                            alignItems: "center",
                            gap: "3px",
                            overflow: "visible",
                            whiteSpace: "pre-wrap",
                            wordBreak: "break-word",
                            flex: 1,
                        }}
                        onDoubleClick={(e) => {
                            e.stopPropagation();
                            setEditingTaskId(task.id);
                        }}
                    >
                        {(showPriorityIcons || showProjectIcons) && (
                            <span style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", width: "14px", minWidth: "14px", flexShrink: 0, gap: "2px", opacity: task.completed && showTaskCheckboxes ? 0.5 : 1 }}>
                                {showPriorityIcons && (() => {
                                    const pb = getPriorityBadge(task, priorityStyle, 11);
                                    return pb ? (
                                        <span title={pb.label} style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", width: "12px", height: "12px" }}>
                                            {pb.node}
                                        </span>
                                    ) : null;
                                })()}
                                {showProjectIcons && task.project && (() => {
                                    const rawIcon = task.project!.icon || "";
                                    const normalised = rawIcon.startsWith("fa") && rawIcon.length > 2 && rawIcon[2] === rawIcon[2].toUpperCase()
                                        ? rawIcon.slice(2, 3).toLowerCase() + rawIcon.slice(3)
                                        : rawIcon;
                                    const found = allIcons.find(i => i.name === normalised || i.name === rawIcon);
                                    return (
                                        <span style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", width: "12px", height: "12px" }}>
                                            {found
                                                ? (found.type === "fa"
                                                    ? <FontAwesomeIcon icon={found.icon as IconDefinition} style={{ fontSize: "11px", color: task.project!.color || "#888" }} />
                                                    : <MdiIcon path={found.icon as string} size={0.5} color={task.project!.color || "#888"} style={{ display: "inline-block" }} />)
                                                : (task.project!.icon
                                                    ? <span style={{ fontSize: "11px" }}>{task.project!.icon}</span>
                                                    : <FontAwesomeIcon icon={faFolder} style={{ fontSize: "11px", color: task.project!.color || "#888" }} />)
                                            }
                                        </span>
                                    );
                                })()}
                            </span>
                        )}
                        {showTaskCheckboxes && (
                            <input
                                type="checkbox"
                                checked={task.completed}
                                aria-label={task.completed ? `Mark "${task.title}" incomplete` : `Mark "${task.title}" complete`}
                                onChange={(e) => { e.stopPropagation(); toggleTask(task.id); }}
                                onClick={(e) => e.stopPropagation()}
                                className="task-checkbox flex-shrink-0"
                                style={{ width: "12px", height: "12px", margin: 0, cursor: "pointer", flexShrink: 0, accentColor: "#FFF" }}
                            />
                        )}
                        <span style={task.completed && showTaskCheckboxes ? { opacity: 0.5, flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" } : { flex: 1, display: "flex", alignItems: "center", flexWrap: "wrap", rowGap: "2px" }}>
                            <span style={{ marginRight: "4px" }}>{task.title}</span>
                            {/* Subtask indicator */}
                            {task.subTasks && task.subTasks.length > 0 && (() => {
                                const completed = task.subTasks.filter(s => s.completed).length;
                                const total = task.subTasks.length;
                                const allDone = completed === total;
                                const expanded = isSubTasksOpen || isSubTaskInputOpen;
                                const pct = total > 0 ? (completed / total) * 100 : 0;
                                return (
                                    <button
                                        onClick={(e) => {
                                            e.stopPropagation();
                                            setIsSubTasksOpen(!isSubTasksOpen);
                                        }}
                                        className="subtask-indicator-badge"
                                        aria-label={expanded ? "Collapse subtasks" : `${completed} of ${total} subtasks done`}
                                        aria-expanded={expanded}
                                        style={{
                                            display: "inline-flex",
                                            alignItems: "center",
                                            gap: "4px",
                                            padding: "2px 8px 2px 4px",
                                            borderRadius: "12px",
                                            background: expanded ? "rgba(99,102,241,0.08)" : "transparent",
                                            color: allDone ? "var(--weekly-teal, #0d9488)" : "var(--weekly-text-light, #9ca3af)",
                                            border: "none",
                                            cursor: "pointer",
                                            fontSize: "0.7rem",
                                            fontWeight: 600,
                                            lineHeight: 1,
                                            flexShrink: 0,
                                            whiteSpace: "nowrap",
                                            transition: "all 0.15s",
                                        }}
                                    >
                                        <ChevronDown size={12} aria-hidden="true" style={{ transform: expanded ? "rotate(0deg)" : "rotate(-90deg)", transition: "transform 0.2s", flexShrink: 0 }} />
                                        <span style={{
                                            display: "inline-block",
                                            width: "36px",
                                            height: "5px",
                                            borderRadius: "3px",
                                            background: "var(--weekly-border, #e5e7eb)",
                                            position: "relative",
                                            overflow: "hidden",
                                            flexShrink: 0,
                                        }}>
                                            <span style={{
                                                position: "absolute",
                                                left: 0,
                                                top: 0,
                                                height: "100%",
                                                width: `${pct}%`,
                                                borderRadius: "3px",
                                                background: allDone ? "var(--weekly-teal, #0d9488)" : "var(--weekly-accent, #6366f1)",
                                                transition: "width 0.3s ease",
                                            }} />
                                        </span>
                                        <span style={{ opacity: 0.8 }}>{completed}/{total}</span>
                                    </button>
                                );
                            })()}

                            {/* URL indicator */}
                            {task.url && (
                                <a
                                    href={task.url}
                                    target="_blank"
                                    rel="noopener noreferrer"
                                    onClick={(e) => e.stopPropagation()}
                                    aria-label={`Open link: ${task.url}`}
                                    style={{
                                        display: "inline-flex",
                                        alignItems: "center",
                                        padding: "1px 3px",
                                        borderRadius: "3px",
                                        background: "rgba(37,99,235,0.10)",
                                        color: "#2563eb",
                                        cursor: "pointer",
                                        marginLeft: "3px",
                                        textDecoration: "none",
                                    }}
                                >
                                    <Link size={10} aria-hidden="true" />
                                </a>
                            )}
                            {/* Note indicator */}
                            {task.markdownContent && task.markdownContent.trim().length > 0 && (
                                <button
                                    onClick={(e) => {
                                        e.stopPropagation();
                                        setIsNotesOpen(!isNotesOpen);
                                    }}
                                    aria-label={isNotesOpen ? "Collapse note" : "Expand note"}
                                    aria-expanded={isNotesOpen}
                                    style={{
                                        display: "inline-flex",
                                        alignItems: "center",
                                        padding: "1px 3px",
                                        borderRadius: "3px",
                                        background: isNotesOpen ? "rgba(245, 158, 11, 0.12)" : "rgba(0,0,0,0.04)",
                                        color: isNotesOpen ? "#f59e0b" : (darkMode ? "#888" : "#999"),
                                        cursor: "pointer",
                                        marginLeft: "3px",
                                        border: "none",
                                    }}
                                >
                                    <svg viewBox="0 0 24 24" width="10" height="10" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
                                        <polyline points="14 2 14 8 20 8" />
                                    </svg>
                                </button>
                            )}
                        </span>
                    </span>
                )}
                {editingTaskId !== task.id && (() => {
                    const rolling = task.isRolling && !task.completed;
                    const provider = task.externalProvider || (task.externalId?.startsWith("synology::") ? "synology" : null);
                    if (!rolling && !provider) return null;
                    const iconMap: Record<string, { icon: any; color: string; label: string }> = {
                        google: { icon: faGoogle, color: "#4285F4", label: "Google" },
                        outlook: { icon: faMicrosoft, color: "#0078D4", label: "Microsoft" },
                        apple: { icon: faApple, color: "#555", label: "Apple" },
                        synology: { icon: faServer, color: "#007AFF", label: "Synology" },
                    };
                    return (
                        <span style={{ display: "flex", alignItems: "center", gap: "3px", flexShrink: 0 }}>
                            {rolling && (
                                <span title="Auto-rolling task" style={{ display: "inline-flex", alignItems: "center", color: "var(--weekly-teal, #009a9a)" }}>
                                    <svg viewBox="0 0 24 24" width="10" height="10" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                                        <polyline points="23 4 23 10 17 10" />
                                        <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
                                    </svg>
                                </span>
                            )}
                            {provider && (() => {
                                const info = iconMap[provider];
                                if (!info) return null;
                                return (
                                    <span className="flex-shrink-0" aria-label={`Synced with ${info.label}`} style={{ display: "inline-flex", alignItems: "center", opacity: 0.55 }}>
                                        <FontAwesomeIcon icon={info.icon} aria-hidden="true" style={{ width: 10, height: 10, color: info.color }} />
                                    </span>
                                );
                            })()}
                        </span>
                    );
                })()}
            </div>

            <div
                className="task-actions"
                onClick={(e) => e.stopPropagation()}
            >
                <button
                    className={`task-action-btn ${task.completed ? "active text-green-600 dark:text-green-500" : ""}`}
                    onClick={(e) => { e.stopPropagation(); toggleTask(task.id); }}
                    aria-label={task.completed ? `Mark "${task.title}" incomplete` : `Mark "${task.title}" complete`}
                >
                    <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                        <line x1="5" y1="12" x2="19" y2="12" />
                    </svg>
                </button>
                <button
                    className="task-action-btn"
                    onClick={(e) => { e.stopPropagation(); setEditingTaskId(task.id); }}
                    aria-label={`Edit "${task.title}"`}
                >
                    <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                        <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
                        <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
                    </svg>
                </button>
                <button
                    className={`task-action-btn ${isSubTaskInputOpen ? "active" : ""}`}
                    onClick={(e) => { e.stopPropagation(); setIsSubTaskInputOpen(!isSubTaskInputOpen); if (!isSubTaskInputOpen) { setIsSubTasksOpen(true); setTimeout(() => subTaskInputRef.current?.focus(), 50); } }}
                    aria-label="Add sub-task"
                    aria-expanded={isSubTaskInputOpen}
                >
                    <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                        <line x1="12" y1="5" x2="12" y2="19" />
                        <line x1="5" y1="12" x2="19" y2="12" />
                    </svg>
                </button>
                <button
                    className={`task-action-btn ${isNotesOpen ? "active" : ""}`}
                    onClick={(e) => { e.stopPropagation(); setIsNotesOpen(!isNotesOpen); }}
                    aria-label={isNotesOpen ? "Close notes" : "Open notes"}
                    aria-expanded={isNotesOpen}
                >
                    <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                        <line x1="3" y1="12" x2="21" y2="12" />
                        <line x1="3" y1="6" x2="21" y2="6" />
                        <line x1="3" y1="18" x2="21" y2="18" />
                    </svg>
                </button>
                {!task.completed && (
                    <button
                        className={`task-action-btn ${task.isRolling ? "active" : ""}`}
                        onClick={(e) => { e.stopPropagation(); toggleTaskRolling(task.id); }}
                        aria-label={task.isRolling ? "Disable rolling (task auto-rolls to next day)" : "Enable rolling (task auto-rolls to next day)"}
                        aria-pressed={task.isRolling}
                    >
                        <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                            <polyline points="23 4 23 10 17 10" />
                            <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
                        </svg>
                    </button>
                )}
                {!task.completed && (
                    <button
                        className={`task-action-btn ${task.isRecurring ? "active" : ""}`}
                        onClick={(e) => { e.stopPropagation(); setSelectedTaskForRecurrence(task); }}
                        aria-label={task.isRecurring ? "Edit recurrence" : "Make task recurring"}
                    >
                        <Repeat size={12} aria-hidden="true" />
                    </button>
                )}
                
                {/* Project Assignment */}
                {projects && projects.length > 0 && onProjectAssign && (
                    <div className="relative" ref={projectPickerRef}>
                        <button
                            className={`task-action-btn ${task.project ? "active" : ""}`}
                            onClick={(e) => {
                                e.stopPropagation();
                                setShowProjectPicker(!showProjectPicker);
                            }}
                            aria-label={task.project ? `Project: ${task.project.name} — change project` : "Assign to project"}
                            aria-expanded={showProjectPicker}
                            aria-haspopup="listbox"
                        >
                            {task.project ? (() => {
                                const rawIcon = task.project.icon || "";
                                const normalised = rawIcon.startsWith("fa") && rawIcon.length > 2 && rawIcon[2] === rawIcon[2].toUpperCase()
                                    ? rawIcon.slice(2, 3).toLowerCase() + rawIcon.slice(3)
                                    : rawIcon;
                                const found = allIcons.find(i => i.name === normalised || i.name === rawIcon);
                                if (found) {
                                    return found.type === "fa"
                                        ? <FontAwesomeIcon icon={found.icon as IconDefinition} aria-hidden="true" style={{ fontSize: "11px", color: task.project.color || "#888" }} />
                                        : <MdiIcon path={found.icon as string} size={0.5} color={task.project.color || "#888"} style={{ display: "inline-block" }} />;
                                }
                                return task.project.icon
                                    ? <span style={{ fontSize: "11px", color: task.project.color || "#888" }}>{task.project.icon}</span>
                                    : <FontAwesomeIcon icon={faFolder} aria-hidden="true" style={{ fontSize: "11px", color: task.project.color || "#888" }} />;
                            })() : <FontAwesomeIcon icon={faFolder} aria-hidden="true" style={{ fontSize: "11px" }} />}
                        </button>
                        {showProjectPicker && (
                            <div className="absolute z-[100] top-full left-1/2 -translate-x-1/2 mt-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg shadow-lg py-1 min-w-[140px]" style={{ whiteSpace: "nowrap" }}>
                                {task.projectId && (
                                    <button
                                        className="flex items-center gap-2 w-full px-3 py-1.5 text-xs hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-500"
                                        onClick={(e) => {
                                            e.stopPropagation();
                                            onProjectAssign(task.id, null);
                                            setShowProjectPicker(false);
                                        }}
                                    >
                                        <X size={10} /> Remove
                                    </button>
                                )}
                                {projects.map((p) => (
                                    <button
                                        key={p.id}
                                        className={`flex items-center gap-2 w-full px-3 py-1.5 text-xs hover:bg-gray-100 dark:hover:bg-gray-700 ${task.projectId === p.id ? "font-bold" : ""}`}
                                        onClick={(e) => {
                                            e.stopPropagation();
                                            onProjectAssign(task.id, task.projectId === p.id ? null : p.id);
                                            setShowProjectPicker(false);
                                        }}
                                    >
                                        {(() => {
                                            const rawIcon = p.icon || "";
                                            const normalised = rawIcon.startsWith("fa") && rawIcon.length > 2 && rawIcon[2] === rawIcon[2].toUpperCase()
                                                ? rawIcon.slice(2, 3).toLowerCase() + rawIcon.slice(3)
                                                : rawIcon;
                                            const found = allIcons.find(i => i.name === normalised || i.name === rawIcon);
                                            if (found) {
                                                return found.type === "fa"
                                                    ? <FontAwesomeIcon icon={found.icon as IconDefinition} style={{ fontSize: "10px", color: p.color || "#888" }} />
                                                    : <MdiIcon path={found.icon as string} size={0.45} color={p.color || "#888"} style={{ display: "inline-block" }} />;
                                            }
                                            return p.icon
                                                ? <span style={{ fontSize: "10px", color: p.color || "#888" }}>{p.icon}</span>
                                                : <FontAwesomeIcon icon={faFolder} style={{ fontSize: "10px", color: p.color || "#888" }} />;
                                        })()}
                                        {p.name}
                                    </button>
                                ))}
                            </div>
                        )}
                    </div>
                )}
                <button
                    className={`task-action-btn ${task.url || isUrlOpen ? "active" : ""}`}
                    onClick={(e) => { e.stopPropagation(); setIsUrlOpen(!isUrlOpen); }}
                    aria-label={task.url ? `Edit link: ${task.url}` : "Add link"}
                    aria-expanded={isUrlOpen}
                    style={task.url ? { color: "#2563eb" } : {}}
                >
                    <Link size={12} aria-hidden="true" />
                </button>
                <button
                    className="task-action-btn delete"
                    onClick={(e) => { e.stopPropagation(); deleteTask(task.id); }}
                    aria-label={`Delete "${task.title}"`}
                >
                    <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                        <polyline points="3 6 5 6 21 6"></polyline>
                        <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                    </svg>
                </button>
                {onMoveTask && (
                    <button
                        className={`task-action-btn ${showMoveDialog ? "active" : ""}`}
                        onClick={(e) => {
                            e.stopPropagation();
                            if (!showMoveDialog) {
                                // Pre-fill with current date/time
                                const d = task.scheduledDate ? new Date(task.scheduledDate) : date;
                                const yyyy = d.getFullYear();
                                const mm = String(d.getMonth() + 1).padStart(2, '0');
                                const dd = String(d.getDate()).padStart(2, '0');
                                setMoveDate(`${yyyy}-${mm}-${dd}`);
                                setMoveTime(task.startTime || '09:00');
                            }
                            setShowMoveDialog(!showMoveDialog);
                        }}
                        aria-label="Move task to different date/time"
                        aria-expanded={showMoveDialog}
                    >
                        <svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                            <polyline points="5 9 2 12 5 15" />
                            <polyline points="9 5 12 2 15 5" />
                            <line x1="2" y1="12" x2="22" y2="12" />
                            <line x1="12" y1="2" x2="12" y2="22" />
                        </svg>
                    </button>
                )}
            </div>

            <div style={{ paddingLeft: "4px", paddingRight: "4px", paddingBottom: "10px", marginTop: "4px" }}>
                {isUrlOpen && (
                    <div
                        className={`weekly-notes-popup ${topOffset > 180 ? "on-top" : ""}`}
                        onClick={(e) => e.stopPropagation()}
                        style={{
                            top: topOffset > 180 ? "auto" : "100%",
                            bottom: topOffset > 180 ? "100%" : "auto",
                            marginTop: topOffset > 180 ? "0" : "10px",
                            marginBottom: topOffset > 180 ? "10px" : "0",
                            left: "-10px",
                            right: "-10px",
                            width: "auto",
                            padding: "8px 10px",
                            display: "flex",
                            flexDirection: "column",
                            gap: "6px",
                        }}
                    >
                        <div style={{ display: "flex", alignItems: "center", gap: "6px" }}>
                            <Link size={13} aria-hidden="true" style={{ color: "#2563eb", flexShrink: 0 }} />
                            <input
                                ref={urlInputRef}
                                type="url"
                                aria-label="Task link URL"
                                value={urlValue}
                                onChange={(e) => setUrlValue(e.target.value)}
                                onKeyDown={(e) => {
                                    if (e.key === "Enter") { e.preventDefault(); handleUrlSave(urlValue); }
                                    if (e.key === "Escape") { setIsUrlOpen(false); setUrlValue(task.url || ""); }
                                }}
                                onBlur={() => handleUrlSave(urlValue)}
                                placeholder="https://..."
                                style={{
                                    flex: 1,
                                    fontSize: "0.78rem",
                                    border: "1px solid var(--weekly-border, #ddd)",
                                    borderRadius: "4px",
                                    padding: "3px 6px",
                                    background: "var(--weekly-bg, white)",
                                    color: "var(--weekly-text, #333)",
                                    outline: "none",
                                }}
                            />
                            {urlValue && (
                                <button
                                    onMouseDown={(e) => { e.preventDefault(); setUrlValue(""); updateTaskUrl(task.id, ""); setIsUrlOpen(false); }}
                                    aria-label="Remove link"
                                    style={{ background: "none", border: "none", cursor: "pointer", padding: "2px", color: "#999" }}
                                >
                                    <X size={12} aria-hidden="true" />
                                </button>
                            )}
                            {urlValue && (
                                <a
                                    href={urlValue.startsWith("http") ? urlValue : `https://${urlValue}`}
                                    target="_blank"
                                    rel="noopener noreferrer"
                                    onClick={(e) => e.stopPropagation()}
                                    aria-label="Open link in new tab"
                                    style={{ color: "#2563eb", flexShrink: 0, display: "inline-flex" }}
                                >
                                    <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                                        <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
                                        <polyline points="15 3 21 3 21 9" />
                                        <line x1="10" y1="14" x2="21" y2="3" />
                                    </svg>
                                </a>
                            )}
                        </div>
                    </div>
                )}
                {isNotesOpen && (
                    <div
                        className={`weekly-notes-popup ${topOffset > 180 ? "on-top" : ""}`}
                        onClick={(e) => e.stopPropagation()}
                        style={{
                            top: topOffset > 180 ? "auto" : "100%",
                            bottom: topOffset > 180 ? "100%" : "auto",
                            marginTop: topOffset > 180 ? "0" : "10px",
                            marginBottom: topOffset > 180 ? "10px" : "0",
                            left: "-10px",
                            right: "-10px",
                            width: "auto",
                            padding: "0",
                        }}
                    >
                        <div style={{ display: "flex", justifyContent: "flex-end", padding: "4px 6px 0", gap: "4px" }}>
                            <button
                                onMouseDown={(e) => { e.preventDefault(); setIsNotesOpen(false); }}
                                style={{ background: "none", border: "none", cursor: "pointer", fontSize: "1rem", lineHeight: 1, color: "#999", padding: "2px 4px" }}
                                aria-label="Close notes"
                            >×</button>
                        </div>
                        <div style={{ padding: "0 6px 8px" }}>
                            <RichTextEditor
                                value={notesValue}
                                onChange={(html) => {
                                    setNotesValue(html);
                                    updateTaskNotes(task.id, html);
                                }}
                                placeholder="Add notes..."
                                minHeight="100px"
                            />
                        </div>
                    </div>
                )}
                {isSubTasksOpen && task.subTasks && task.subTasks.length > 0 && (
                    <ul className="subtask-list mt-1" onClick={(e) => e.stopPropagation()}>
                        {task.subTasks.map((subTask: Task) => (
                            <li key={subTask.id} className={`subtask-item ${subTask.completed ? "completed" : ""}`}>
                                <button
                                    className="subtask-checkbox"
                                    onClick={() => toggleSubTask(subTask.id)}
                                    aria-label={subTask.completed ? `Mark subtask "${subTask.title}" incomplete` : `Mark subtask "${subTask.title}" complete`}
                                >
                                    {subTask.completed ? (
                                        <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12" /></svg>
                                    ) : (
                                        <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10" /></svg>
                                    )}
                                </button>
                                {onSetEditingTaskId && editingTaskId === subTask.id ? (
                                    <form onSubmit={(e) => { e.preventDefault(); const input = e.currentTarget.querySelector("input"); if (input) { updateSubTask(subTask.id, input.value); onSetEditingTaskId(null); } }} style={{ flex: 1 }}>
                                        <input type="text" defaultValue={subTask.title} autoFocus className="subtask-edit-input" onBlur={(e) => { updateSubTask(subTask.id, e.target.value); onSetEditingTaskId(null); }} onKeyDown={(e) => { if (e.key === "Escape") onSetEditingTaskId(null); }} />
                                    </form>
                                ) : (
                                    <span className={`subtask-title ${subTask.completed ? "completed" : ""}`} onClick={() => onSetEditingTaskId && onSetEditingTaskId(subTask.id)}>{subTask.title}</span>
                                )}
                                <button className="subtask-delete-btn" onClick={() => deleteSubTask(subTask.id)} aria-label={`Remove subtask "${subTask.title}"`}><svg viewBox="0 0 24 24" width="10" height="10" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg></button>
                            </li>
                        ))}
                    </ul>
                )}
                {isSubTaskInputOpen && (
                    <div className="subtask-add-row mt-1" onClick={(e) => e.stopPropagation()}>
                        <form onSubmit={(e) => { e.preventDefault(); if (newSubTaskTitle.trim()) { addSubTask(task.id, newSubTaskTitle.trim()); setNewSubTaskTitle(""); } }} style={{ display: "flex", alignItems: "center", gap: "0.25rem", flex: 1 }}>
                            <svg viewBox="0 0 24 24" width="12" height="12" stroke="var(--weekly-text-muted, #999)" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }} aria-hidden="true"><circle cx="12" cy="12" r="10" /></svg>
                            <input ref={subTaskInputRef} type="text" aria-label="New sub-task title" value={newSubTaskTitle} onChange={(e) => setNewSubTaskTitle(e.target.value)} onBlur={() => { if (!newSubTaskTitle.trim()) setIsSubTaskInputOpen(false); }} onKeyDown={(e) => { if (e.key === "Escape") { setNewSubTaskTitle(""); setIsSubTaskInputOpen(false); } }} placeholder="Add sub-task..." className="subtask-add-input" autoFocus />
                        </form>
                    </div>
                )}
            </div>
            {showMoveDialog && onMoveTask && (
                <div
                    ref={moveDialogRef}
                    role="dialog"
                    aria-modal="true"
                    aria-label={`Move task "${task.title}" to a new date and time`}
                    className="weekly-notes-popup"
                    onClick={(e) => e.stopPropagation()}
                    style={{
                        top: topOffset > 180 ? "auto" : "100%",
                        bottom: topOffset > 180 ? "100%" : "auto",
                        marginTop: topOffset > 180 ? "0" : "10px",
                        marginBottom: topOffset > 180 ? "10px" : "0",
                        left: "-10px",
                        right: "-10px",
                        padding: "10px 12px",
                        display: "flex",
                        flexDirection: "column",
                        gap: "8px",
                    }}
                >
                    <p style={{ margin: 0, fontSize: "0.78rem", fontWeight: 600, color: "var(--weekly-text, #333)" }}>
                        Move: <em>{task.title}</em>
                    </p>
                    <div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
                        <label htmlFor={`move-date-${task.id}`} style={{ fontSize: "0.75rem", whiteSpace: "nowrap" }}>Date</label>
                        <input
                            id={`move-date-${task.id}`}
                            type="date"
                            value={moveDate}
                            onChange={(e) => setMoveDate(e.target.value)}
                            autoFocus
                            style={{ flex: 1, fontSize: "0.78rem", border: "1px solid var(--weekly-border, #ddd)", borderRadius: "4px", padding: "3px 6px", background: "var(--weekly-bg, white)", color: "var(--weekly-text, #333)", outline: "none" }}
                        />
                    </div>
                    <div style={{ display: "flex", gap: "6px", alignItems: "center" }}>
                        <label htmlFor={`move-time-${task.id}`} style={{ fontSize: "0.75rem", whiteSpace: "nowrap" }}>Time</label>
                        <input
                            id={`move-time-${task.id}`}
                            type="time"
                            value={moveTime}
                            onChange={(e) => setMoveTime(e.target.value)}
                            step="900"
                            style={{ flex: 1, fontSize: "0.78rem", border: "1px solid var(--weekly-border, #ddd)", borderRadius: "4px", padding: "3px 6px", background: "var(--weekly-bg, white)", color: "var(--weekly-text, #333)", outline: "none" }}
                        />
                    </div>
                    <div style={{ display: "flex", gap: "6px", justifyContent: "flex-end" }}>
                        <button
                            onClick={() => setShowMoveDialog(false)}
                            style={{ fontSize: "0.75rem", padding: "3px 8px", borderRadius: "4px", border: "1px solid var(--weekly-border, #ddd)", background: "transparent", cursor: "pointer", color: "var(--weekly-text, #333)" }}
                        >
                            Cancel
                        </button>
                        <button
                            onClick={() => {
                                if (moveDate && moveTime) {
                                    const [y, m, d] = moveDate.split('-').map(Number);
                                    const targetDate = new Date(y, m - 1, d);
                                    // Round time to nearest 15 min
                                    const [h, min] = moveTime.split(':').map(Number);
                                    const rounded = Math.round(min / 15) * 15;
                                    const roundedMin = rounded === 60 ? 0 : rounded;
                                    const roundedH = rounded === 60 ? h + 1 : h;
                                    const roundedTime = `${String(roundedH).padStart(2, '0')}:${String(roundedMin).padStart(2, '0')}`;
                                    onMoveTask(task.id, targetDate, roundedTime);
                                    setShowMoveDialog(false);
                                }
                            }}
                            style={{ fontSize: "0.75rem", padding: "3px 8px", borderRadius: "4px", border: "none", background: "var(--weekly-accent, #6366f1)", color: "white", cursor: "pointer" }}
                        >
                            Move
                        </button>
                    </div>
                </div>
            )}
            <div
                className="resize-handle"
                onMouseDown={onResizeStart}
                onKeyDown={onResizeKeyDown}
                tabIndex={0}
                role="slider"
                aria-label={`Resize task duration, currently ${duration} minutes`}
                aria-valuemin={15}
                aria-valuemax={480}
                aria-valuenow={duration}
                aria-valuetext={`${duration} minutes`}
            />
        </div>
    );
}
