import { useState, useCallback, useMemo } from 'react';
import { useNavigate } from '@tanstack/react-router';
import { FileText, FolderOpen, Sparkles } from 'lucide-react';
import { trpc } from '@/lib/trpc';
import { useNotify } from '@/hooks/useNotify';
import { TaskRow } from '@/components/tasks/TaskRow';
import type { TaskItem } from '@/components/tasks/task-types';
import { TaskDetailSheet } from '@/components/tasks/TaskDetailSheet';
import { EditTaskDialog } from '@/components/tasks/EditTaskDialog';
import { Item, ItemMedia, ItemContent, ItemTitle, ItemDescription } from '@/components/ui/item';
import { ChatTimelineBlock } from './ChatTimelineBlock';
import { useFormatPrefs, formatDate } from '@/lib/date';
import type { EntityRefBlockData } from '../../../../../shared/api-types';

export function ChatEntityBlock({ data }: { data: EntityRefBlockData }) {
  const { entity, ids } = data;

  switch (entity) {
    case 'task':
      return <TaskEntityBlock ids={ids} />;
    case 'project':
      return <ProjectEntityBlock ids={ids} />;
    case 'note':
      return <NoteEntityBlock ids={ids} />;
    case 'timeline':
      return <TimelineEntityBlock ids={ids} />;
    case 'timelineEvent':
      return <TimelineEventEntityBlock ids={ids} />;
    default:
      return null;
  }
}

// ---------------------------------------------------------------------------
// Tasks
// ---------------------------------------------------------------------------

function TaskEntityBlock({ ids }: { ids: string[] }) {
  const utils = trpc.useUtils();
  const { data: tasksList } = trpc.tasks.byIds.useQuery({ ids }, { enabled: ids.length > 0 });

  const { notify, notifyError } = useNotify();

  const updateTask = trpc.tasks.update.useMutation({
    onSuccess: () => {
      void utils.tasks.byIds.invalidate({ ids });
      void utils.tasks.list.invalidate();
    },
    onError: (err) => notifyError('toast.task.updateError', err),
  });
  const deleteTask = trpc.tasks.delete.useMutation({
    onSuccess: () => {
      notify('warning', 'toast.task.deleted');
      void utils.tasks.byIds.invalidate({ ids });
      void utils.tasks.list.invalidate();
    },
    onError: (err) => notifyError('toast.task.deleteError', err),
  });

  const [viewTask, setViewTask] = useState<TaskItem | null>(null);
  const [editTask, setEditTask] = useState<TaskItem | null>(null);

  const handleToggle = useCallback(
    (taskId: string, currentStatus: string | null) => {
      const nextStatus =
        currentStatus === 'todo' ? 'in_progress' :
        currentStatus === 'in_progress' ? 'done' : 'todo';
      updateTask.mutate({ id: taskId, status: nextStatus });
    },
    [updateTask],
  );

  if (!tasksList?.length) return null;

  return (
    <>
      <EntityWrapper label="Tasks">
        {tasksList.map((task) => (
          <TaskRow
            key={task.id}
            task={task}
            onToggle={handleToggle}
            onClick={setViewTask}
          />
        ))}
      </EntityWrapper>

      <TaskDetailSheet
        task={viewTask}
        open={!!viewTask}
        onOpenChange={(open) => { if (!open) setViewTask(null); }}
        onEdit={(task) => { setViewTask(null); setEditTask(task); }}
        onDelete={(id) => { deleteTask.mutate({ id }); setViewTask(null); }}
      />
      <EditTaskDialog
        task={editTask}
        open={!!editTask}
        onOpenChange={(open: boolean) => { if (!open) setEditTask(null); }}
      />
    </>
  );
}

// ---------------------------------------------------------------------------
// Projects
// ---------------------------------------------------------------------------

function ProjectEntityBlock({ ids }: { ids: string[] }) {
  const navigate = useNavigate();
  const { data: allProjects } = trpc.projects.list.useQuery();

  const filtered = useMemo(
    () => allProjects?.filter((p) => ids.includes(p.id)) ?? [],
    [allProjects, ids],
  );

  if (!filtered.length) return null;

  return (
    <EntityWrapper label="Projects">
      {filtered.map((p) => (
        <Item
          key={p.id}
          variant="outline"
          size="sm"
          className="cursor-pointer hover:bg-accent/50"
          onClick={() => void navigate({ to: '/projects', search: { projectId: p.id } })}
        >
          <ItemMedia variant="icon">
            <FolderOpen className="h-4 w-4 text-muted-foreground" />
          </ItemMedia>
          <ItemContent>
            <ItemTitle>{p.name}</ItemTitle>
          </ItemContent>
        </Item>
      ))}
    </EntityWrapper>
  );
}

// ---------------------------------------------------------------------------
// Notes
// ---------------------------------------------------------------------------

function NoteEntityBlock({ ids }: { ids: string[] }) {
  const navigate = useNavigate();
  const { data: allNotes } = trpc.notes.list.useQuery();

  const filtered = useMemo(
    () => allNotes?.filter((n) => ids.includes(n.id)) ?? [],
    [allNotes, ids],
  );

  if (!filtered.length) return null;

  return (
    <EntityWrapper label="Notes">
      {filtered.map((n) => (
        <Item
          key={n.id}
          variant="outline"
          size="sm"
          className="cursor-pointer hover:bg-accent/50"
          onClick={() => void navigate({ to: '/notes/$noteId', params: { noteId: n.id } })}
        >
          <ItemMedia variant="icon">
            <FileText className="h-4 w-4 text-muted-foreground" />
          </ItemMedia>
          <ItemContent>
            <ItemTitle>{n.title}</ItemTitle>
          </ItemContent>
        </Item>
      ))}
    </EntityWrapper>
  );
}

// ---------------------------------------------------------------------------
// Timeline Events
// ---------------------------------------------------------------------------

function TimelineEntityBlock({ ids }: { ids: string[] }) {
  const { data: allEvents } = trpc.timelineEvents.list.useQuery();

  const timelineData = useMemo(() => {
    const filtered = allEvents?.filter((e) => ids.includes(e.id)) ?? [];

    return {
      events: filtered
        .map((e) => {
          const date = new Date(e.date).getTime();
          const endDate = e.endDate ? new Date(e.endDate).getTime() : undefined;
          return {
            id: e.id,
            title: e.title,
            date,
            endDate,
            projectId: e.projectId,
            isCompleted: e.isCompleted,
            isAiSuggested: e.isAiSuggested,
          };
        })
        .filter((e) => Number.isFinite(e.date)),
    };
  }, [allEvents, ids]);

  if (!timelineData.events.length) return null;

  return <ChatTimelineBlock data={timelineData} />;
}

function TimelineEventEntityBlock({ ids }: { ids: string[] }) {
  const { data: allEvents } = trpc.timelineEvents.list.useQuery();
  const prefs = useFormatPrefs();

  const filtered = useMemo(
    () => allEvents?.filter((e) => ids.includes(e.id)) ?? [],
    [allEvents, ids],
  );

  if (!filtered.length) return null;

  return (
    <EntityWrapper label="Timeline Events">
      {filtered.map((e) => (
        <Item
          key={e.id}
          variant="outline"
          size="sm"
        >
          <ItemMedia variant="icon">
            {e.isAiSuggested ? (
              <Sparkles className="h-4 w-4 text-amber-500" />
            ) : (
              <div className="h-2 w-2 rounded-full bg-primary" />
            )}
          </ItemMedia>
          <ItemContent>
            <ItemTitle>{e.title}</ItemTitle>
            {e.date && (
              <ItemDescription>
                {formatDate(e.date, prefs)}
              </ItemDescription>
            )}
          </ItemContent>
        </Item>
      ))}
    </EntityWrapper>
  );
}

// ---------------------------------------------------------------------------
// Shared wrapper
// ---------------------------------------------------------------------------

function EntityWrapper({ label, children }: { label: string; children: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-2 rounded-lg bg-card p-3 w-full">
      <p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
        {label}
      </p>
      <div className="flex flex-col gap-1.5">
        {children}
      </div>
    </div>
  );
}
