import { useState, useEffect, useCallback } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { format, parseISO, isToday } from 'date-fns';
import {
  X, Pencil, Trash2, Save, Clock, Calendar, Flag, Tag, Repeat, CheckSquare, AlertCircle, AlignLeft,
} from 'lucide-react';
import api, { getErrorMessage } from '@/lib/api';
import type { Todo } from '@/types';
import { isTodoOverdue } from '@/lib/utils';
import { useConfirmAction } from '@/hooks/useConfirmAction';
import { formatUpdatedAt } from '@/components/shared/utils';
import CopyableField from '@/components/shared/CopyableField';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { DatePicker } from '@/components/ui/date-picker';
import { Textarea } from '@/components/ui/textarea';
import { Select } from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';

// --- Types ---

export interface TodoCreateDefaults {
  category?: string;
}

interface TodoDetailPanelProps {
  todo: Todo | null;
  isCreating?: boolean;
  createDefaults?: TodoCreateDefaults | null;
  onClose: () => void;
  onSaved?: () => void;
  onDeleted?: () => void;
}

interface EditState {
  title: string;
  description: string;
  priority: string;
  due_date: string;
  due_time: string;
  category: string;
  recurrence_rule: string;
}

const priorityColors: Record<string, string> = {
  none: 'bg-gray-500/20 text-gray-400',
  low: 'bg-green-500/20 text-green-400',
  medium: 'bg-yellow-500/20 text-yellow-400',
  high: 'bg-red-500/20 text-red-400',
};

const recurrenceLabels: Record<string, string> = {
  daily: 'Daily',
  weekly: 'Weekly',
  monthly: 'Monthly',
};

function todayLocal(): string {
  const d = new Date();
  const pad = (n: number) => n.toString().padStart(2, '0');
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
}

function nowTimeLocal(): string {
  const d = new Date();
  const pad = (n: number) => n.toString().padStart(2, '0');
  return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

const QUERY_KEYS = [['todos'], ['dashboard'], ['upcoming']] as const;

function buildEditState(todo: Todo): EditState {
  return {
    title: todo.title,
    description: todo.description || '',
    priority: todo.priority,
    due_date: todo.due_date ? todo.due_date.slice(0, 10) : '',
    due_time: todo.due_time ? todo.due_time.slice(0, 5) : '',
    category: todo.category || '',
    recurrence_rule: todo.recurrence_rule || '',
  };
}

function buildCreateState(defaults?: TodoCreateDefaults | null): EditState {
  return {
    title: '',
    description: '',
    priority: 'medium',
    due_date: todayLocal(),
    due_time: nowTimeLocal(),
    category: defaults?.category || '',
    recurrence_rule: '',
  };
}

// --- Component ---

export default function TodoDetailPanel({
  todo,
  isCreating = false,
  createDefaults,
  onClose,
  onSaved,
  onDeleted,
}: TodoDetailPanelProps) {
  const queryClient = useQueryClient();

  const [isEditing, setIsEditing] = useState(isCreating);
  const [editState, setEditState] = useState<EditState>(() =>
    isCreating ? buildCreateState(createDefaults) : todo ? buildEditState(todo) : buildCreateState()
  );

  // Reset state when todo changes
  useEffect(() => {
    setIsEditing(false);
    if (todo) setEditState(buildEditState(todo));
  }, [todo?.id]);

  // Enter edit mode when creating
  useEffect(() => {
    if (isCreating) {
      setIsEditing(true);
      setEditState(buildCreateState(createDefaults));
    }
  }, [isCreating, createDefaults]);

  const invalidateAll = useCallback(() => {
    QUERY_KEYS.forEach((key) => queryClient.invalidateQueries({ queryKey: [...key] }));
  }, [queryClient]);

  // --- Mutations ---

  const saveMutation = useMutation({
    mutationFn: async (data: EditState) => {
      const payload = {
        title: data.title,
        description: data.description || null,
        priority: data.priority,
        due_date: data.due_date || null,
        due_time: data.due_time || null,
        category: data.category || null,
        recurrence_rule: data.recurrence_rule || null,
      };
      if (todo && !isCreating) {
        return api.put(`/todos/${todo.id}`, payload);
      } else {
        return api.post('/todos', payload);
      }
    },
    onSuccess: () => {
      invalidateAll();
      toast.success(isCreating ? 'Todo created' : 'Todo updated');
      if (isCreating) {
        onClose();
      } else {
        setIsEditing(false);
      }
      onSaved?.();
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, isCreating ? 'Failed to create todo' : 'Failed to update todo'));
    },
  });

  const toggleMutation = useMutation({
    mutationFn: async () => {
      const { data } = await api.patch(`/todos/${todo!.id}/toggle`);
      return data;
    },
    onSuccess: () => {
      invalidateAll();
      toast.success(todo!.completed ? 'Todo marked incomplete' : 'Todo completed!');
    },
    onError: () => {
      toast.error('Failed to update todo');
    },
  });

  const deleteMutation = useMutation({
    mutationFn: async () => {
      await api.delete(`/todos/${todo!.id}`);
    },
    onSuccess: () => {
      invalidateAll();
      toast.success('Todo deleted');
      onClose();
      onDeleted?.();
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, 'Failed to delete todo'));
    },
  });

  const executeDelete = useCallback(() => deleteMutation.mutate(), [deleteMutation]);
  const { confirming: confirmingDelete, handleClick: handleDeleteClick } = useConfirmAction(executeDelete);

  // --- Handlers ---

  const handleEditStart = () => {
    if (todo) setEditState(buildEditState(todo));
    setIsEditing(true);
  };

  const handleEditCancel = () => {
    setIsEditing(false);
    if (isCreating) {
      onClose();
    } else if (todo) {
      setEditState(buildEditState(todo));
    }
  };

  const handleEditSave = () => {
    saveMutation.mutate(editState);
  };

  const updateField = <K extends keyof EditState>(key: K, value: EditState[K]) => {
    setEditState((s) => ({ ...s, [key]: value }));
  };

  // Empty state
  if (!todo && !isCreating) {
    return (
      <div className="flex flex-col items-center justify-center h-full text-muted-foreground">
        <CheckSquare className="h-8 w-8 mb-3 opacity-40" />
        <p className="text-sm">Select a todo to view details</p>
      </div>
    );
  }

  // View data
  const dueDate = todo?.due_date ? parseISO(todo.due_date) : null;
  const isDueToday = dueDate ? isToday(dueDate) : false;
  const isOverdue = todo ? isTodoOverdue(todo.due_date, todo.completed) : false;

  return (
    <div className="flex flex-col h-full bg-card border-l border-border overflow-hidden">
      {/* Header */}
      <div className="px-5 py-4 border-b border-border shrink-0">
        <div className="flex items-start justify-between gap-3">
          {isEditing && !isCreating ? (
            <Input
              value={editState.title}
              onChange={(e) => updateField('title', e.target.value)}
              className="h-8 text-base font-semibold flex-1"
              placeholder="Todo title"
              autoFocus
            />
          ) : isCreating ? (
            <h3 className="font-heading text-lg font-semibold">New Todo</h3>
          ) : (
            <div className="flex items-center gap-3 min-w-0 flex-1">
              <span onClick={(e) => e.stopPropagation()}>
                <Checkbox
                  checked={todo!.completed}
                  onChange={() => toggleMutation.mutate()}
                  disabled={toggleMutation.isPending}
                />
              </span>
              <h3 className={`font-heading text-lg font-semibold truncate ${todo!.completed ? 'line-through text-muted-foreground' : ''}`}>
                {todo!.title}
              </h3>
            </div>
          )}

          <div className="flex items-center gap-1 shrink-0">
            {(isEditing || isCreating) ? (
              <>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7 text-green-400 hover:text-green-300"
                  onClick={handleEditSave}
                  disabled={saveMutation.isPending}
                  title="Save"
                >
                  <Save className="h-3.5 w-3.5" />
                </Button>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7"
                  onClick={handleEditCancel}
                  title="Cancel"
                >
                  <X className="h-3.5 w-3.5" />
                </Button>
              </>
            ) : (
              <>
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7"
                  onClick={handleEditStart}
                  title="Edit todo"
                >
                  <Pencil className="h-3.5 w-3.5" />
                </Button>
                {confirmingDelete ? (
                  <Button
                    variant="ghost"
                    onClick={handleDeleteClick}
                    disabled={deleteMutation.isPending}
                    className="h-7 px-2 bg-destructive/20 text-destructive text-[11px] font-medium"
                    title="Confirm delete"
                  >
                    Sure?
                  </Button>
                ) : (
                  <Button
                    variant="ghost"
                    size="icon"
                    className="h-7 w-7 text-muted-foreground hover:text-destructive"
                    onClick={handleDeleteClick}
                    disabled={deleteMutation.isPending}
                    title="Delete todo"
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                  </Button>
                )}
                <Button
                  variant="ghost"
                  size="icon"
                  className="h-7 w-7"
                  onClick={onClose}
                  title="Close panel"
                >
                  <X className="h-3.5 w-3.5" />
                </Button>
              </>
            )}
          </div>
        </div>
      </div>

      {/* Body */}
      <div className="flex-1 overflow-y-auto px-5 py-4 space-y-3">
        {(isEditing || isCreating) ? (
          /* Edit / Create mode */
          <div className="space-y-4">
            {isCreating && (
              <div className="space-y-1">
                <Label htmlFor="todo-title" required>Title</Label>
                <Input
                  id="todo-title"
                  value={editState.title}
                  onChange={(e) => updateField('title', e.target.value)}
                  placeholder="Todo title"
                  required
                  autoFocus
                />
              </div>
            )}

            <div className="space-y-1">
              <Label htmlFor="todo-desc">Description</Label>
              <Textarea
                id="todo-desc"
                value={editState.description}
                onChange={(e) => updateField('description', e.target.value)}
                placeholder="Add a description..."
                rows={3}
                className="text-sm resize-none"
              />
            </div>

            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label htmlFor="todo-priority">Priority</Label>
                <Select
                  id="todo-priority"
                  value={editState.priority}
                  onChange={(e) => updateField('priority', e.target.value)}
                  className="text-xs"
                >
                  <option value="none">None</option>
                  <option value="low">Low</option>
                  <option value="medium">Medium</option>
                  <option value="high">High</option>
                </Select>
              </div>
              <div className="space-y-1">
                <Label htmlFor="todo-category">Category</Label>
                <Input
                  id="todo-category"
                  value={editState.category}
                  onChange={(e) => updateField('category', e.target.value)}
                  placeholder="e.g., Work"
                  className="text-xs"
                />
              </div>
            </div>

            <div className="grid grid-cols-2 gap-3">
              <div className="space-y-1">
                <Label htmlFor="todo-due-date">Due Date</Label>
                <DatePicker
                  variant="input"
                  id="todo-due-date"
                  mode="datetime"
                  value={editState.due_date ? (editState.due_date + 'T' + (editState.due_time || '00:00')) : ''}
                  onChange={(v) => {
                    updateField('due_date', v ? v.slice(0, 10) : '');
                    updateField('due_time', v ? v.slice(11, 16) : '');
                  }}
                  className="text-xs"
                />
              </div>
              <div className="space-y-1">
                <Label htmlFor="todo-recurrence">Recurrence</Label>
                <Select
                  id="todo-recurrence"
                  value={editState.recurrence_rule}
                  onChange={(e) => updateField('recurrence_rule', e.target.value)}
                  className="text-xs"
                >
                  <option value="">None</option>
                  <option value="daily">Daily</option>
                  <option value="weekly">Weekly</option>
                  <option value="monthly">Monthly</option>
                </Select>
              </div>
            </div>

            {/* Save / Cancel at bottom */}
            <div className="flex items-center justify-end gap-2 pt-2 border-t border-border">
              <Button variant="outline" size="sm" onClick={handleEditCancel}>
                Cancel
              </Button>
              <Button size="sm" onClick={handleEditSave} disabled={saveMutation.isPending}>
                {saveMutation.isPending ? 'Saving...' : isCreating ? 'Create' : 'Update'}
              </Button>
            </div>
          </div>
        ) : (
          /* View mode */
          <>
            {/* 2-column grid: Priority, Category, Due Date, Recurrence */}
            <div className="grid grid-cols-2 gap-3">
              {/* Priority */}
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <Flag className="h-3 w-3" />
                  Priority
                </div>
                <Badge className={`text-[9px] px-1.5 py-0.5 rounded-full ${priorityColors[todo!.priority] ?? ''}`}>
                  {todo!.priority}
                </Badge>
              </div>

              {/* Category */}
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <Tag className="h-3 w-3" />
                  Category
                </div>
                {todo!.category ? (
                  <Badge className="text-[9px] px-1.5 py-0.5 bg-blue-500/15 text-blue-400">
                    {todo!.category}
                  </Badge>
                ) : (
                  <p className="text-sm text-muted-foreground">—</p>
                )}
              </div>

              {/* Due Date */}
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  {isOverdue ? <AlertCircle className="h-3 w-3" /> : <Calendar className="h-3 w-3" />}
                  Due Date
                </div>
                {dueDate ? (
                  <CopyableField
                    value={`${isOverdue ? 'Overdue · ' : isDueToday ? 'Today · ' : ''}${format(dueDate, 'EEEE, MMMM d, yyyy')}${todo!.due_time ? ` at ${todo!.due_time.slice(0, 5)}` : ''}`}
                    icon={isOverdue ? AlertCircle : Calendar}
                    label="Due date"
                  />
                ) : todo!.due_time ? (
                  <CopyableField value={todo!.due_time.slice(0, 5)} icon={Clock} label="Due time" />
                ) : (
                  <p className="text-sm text-muted-foreground">—</p>
                )}
              </div>

              {/* Recurrence */}
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <Repeat className="h-3 w-3" />
                  Recurrence
                </div>
                {todo!.recurrence_rule ? (
                  <p className="text-sm">{recurrenceLabels[todo!.recurrence_rule] || todo!.recurrence_rule}</p>
                ) : (
                  <p className="text-sm text-muted-foreground">—</p>
                )}
              </div>
            </div>

            {/* Completion status — full width */}
            {todo!.completed && todo!.completed_at && (
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <CheckSquare className="h-3 w-3" />
                  Completed
                </div>
                <p className="text-sm text-green-400">
                  {format(parseISO(todo!.completed_at), 'MMM d, yyyy · h:mm a')}
                </p>
              </div>
            )}

            {/* Reset info — full width */}
            {todo!.completed && todo!.recurrence_rule && todo!.reset_at && (
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <Repeat className="h-3 w-3" />
                  Resets
                </div>
                <p className="text-sm text-purple-400">
                  {format(parseISO(todo!.reset_at), 'EEE, MMM d')}
                  {todo!.next_due_date && ` · Next due ${format(parseISO(todo!.next_due_date), 'MMM d')}`}
                </p>
              </div>
            )}

            {/* Description — full width */}
            {todo!.description && (
              <div className="space-y-1">
                <div className="flex items-center gap-1.5 text-[11px] text-muted-foreground uppercase tracking-wider">
                  <AlignLeft className="h-3 w-3" />
                  Description
                </div>
                <p className="text-sm whitespace-pre-wrap text-muted-foreground leading-relaxed">
                  {todo!.description}
                </p>
              </div>
            )}

            {/* Updated at */}
            <div className="pt-2 border-t border-border">
              <span className="text-[11px] text-muted-foreground">
                {formatUpdatedAt(todo!.updated_at)}
              </span>
            </div>
          </>
        )}
      </div>
    </div>
  );
}
