import { useState, useEffect, useCallback, useRef } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { trpc } from '@/lib/trpc';
import { BriefChatHeader } from './BriefChatHeader';
import { TaskBriefChat } from './TaskBriefChat';
import { CanvasPlaceholder } from './CanvasPlaceholder';
import { CarouselControls } from './CarouselControls';
import { Skeleton } from '@/components/ui/skeleton';
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@/components/ui/resizable';

interface BriefingResult {
  briefingMarkdown: string;
  canvasDraft: string | null;
  canvasKind: string | null;
}

interface Task {
  id: string;
  title: string;
  priority: string;
  dueDate?: number | null;
  projectId?: string | null;
  projectName?: string | null;
}

interface TaskCarouselProps {
  tasks: Task[];
  initialTaskId?: string;
}

// Session-level briefing cache (survives carousel navigation, cleared on overlay close)
const briefingSessionCache = new Map<string, BriefingResult>();

export function clearCarouselBriefingCache() {
  briefingSessionCache.clear();
}

const SLIDE_VARIANTS = {
  enter: (dir: number) => ({ x: dir > 0 ? 60 : -60, opacity: 0 }),
  center: { x: 0, opacity: 1 },
  exit: (dir: number) => ({ x: dir > 0 ? -60 : 60, opacity: 0 }),
};

const SLIDE_TRANSITION = { type: 'spring' as const, stiffness: 400, damping: 40 };

export function TaskCarousel({ tasks, initialTaskId }: TaskCarouselProps) {
  const initialIndex = initialTaskId
    ? Math.max(0, tasks.findIndex((t) => t.id === initialTaskId))
    : 0;

  const [activeIndex, setActiveIndex] = useState(initialIndex);
  const [slideDir, setSlideDir] = useState(1);
  // Per-task canvas drafts derived from briefings
  const [canvasData, setCanvasData] = useState<Map<string, BriefingResult>>(new Map(briefingSessionCache));

  const activeTask = tasks[activeIndex];

  // Per-task DB briefing query
  const dbBriefingQuery = trpc.ai.getTaskBriefing.useQuery(
    { taskId: activeTask?.id ?? '' },
    {
      enabled: !!activeTask && !briefingSessionCache.has(activeTask.id),
      staleTime: Infinity,
    },
  );

  // Resolve initial briefing from session cache → DB → null (triggers research)
  const getCachedBriefing = (taskId: string): BriefingResult | null => {
    if (briefingSessionCache.has(taskId)) return briefingSessionCache.get(taskId)!;
    if (dbBriefingQuery.data && dbBriefingQuery.data.taskId === taskId) {
      return {
        briefingMarkdown: dbBriefingQuery.data.briefingMarkdown,
        canvasDraft: dbBriefingQuery.data.canvasDraft ?? null,
        canvasKind: dbBriefingQuery.data.canvasKind ?? null,
      };
    }
    return null;
  };

  // Promote DB briefings to session cache so navigating back doesn't re-research
  useEffect(() => {
    if (!dbBriefingQuery.data || !activeTask) return;
    if (dbBriefingQuery.data.taskId !== activeTask.id) return;
    if (briefingSessionCache.has(activeTask.id)) return;
    const result: BriefingResult = {
      briefingMarkdown: dbBriefingQuery.data.briefingMarkdown,
      canvasDraft: dbBriefingQuery.data.canvasDraft ?? null,
      canvasKind: dbBriefingQuery.data.canvasKind ?? null,
    };
    briefingSessionCache.set(activeTask.id, result);
    setCanvasData((prev) => new Map(prev).set(activeTask.id, result));
  }, [dbBriefingQuery.data, activeTask]);

  const handleBriefingReady = useCallback((result: BriefingResult) => {
    if (!activeTask) return;
    briefingSessionCache.set(activeTask.id, result);
    setCanvasData((prev) => new Map(prev).set(activeTask.id, result));
  }, [activeTask]);

  const goTo = useCallback((index: number) => {
    if (index < 0 || index >= tasks.length) return;
    setSlideDir(index > activeIndex ? 1 : -1);
    setActiveIndex(index);
  }, [activeIndex, tasks.length]);

  const lastWheelNavRef = useRef<number>(0);
  const handleWheel = useCallback((e: React.WheelEvent) => {
    if (Math.abs(e.deltaX) <= Math.abs(e.deltaY)) return;
    const now = Date.now();
    if (now - lastWheelNavRef.current < 600) return;
    if (e.deltaX > 30) { lastWheelNavRef.current = now; goTo(activeIndex + 1); }
    else if (e.deltaX < -30) { lastWheelNavRef.current = now; goTo(activeIndex - 1); }
  }, [activeIndex, goTo]);

  // Keyboard navigation
  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === 'ArrowLeft') goTo(activeIndex - 1);
      if (e.key === 'ArrowRight') goTo(activeIndex + 1);
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [activeIndex, goTo]);

  // Prefetch next slide's briefing from DB so it's warm
  const nextTaskId = tasks[activeIndex + 1]?.id;
  trpc.ai.getTaskBriefing.useQuery(
    { taskId: nextTaskId ?? '' },
    { enabled: !!nextTaskId && !briefingSessionCache.has(nextTaskId), staleTime: Infinity },
  );

  if (!activeTask) return null;

  // True while DB is still being checked — prevents TaskBriefChat mounting
  // with undefined initialBriefing and firing unnecessary research
  const isDbCheckPending = !briefingSessionCache.has(activeTask.id) && dbBriefingQuery.isFetching;

  const initialBriefing = getCachedBriefing(activeTask.id);
  const activeCanvas = canvasData.get(activeTask.id) ?? initialBriefing;

  return (
    <div className="flex flex-col h-full" onWheel={handleWheel}>
      {/* Carousel slide area */}
      <div className="flex-1 min-h-0 overflow-hidden">
        <AnimatePresence initial={false} custom={slideDir} mode="wait">
          <motion.div
            key={activeTask.id}
            custom={slideDir}
            variants={SLIDE_VARIANTS}
            initial="enter"
            animate="center"
            exit="exit"
            transition={SLIDE_TRANSITION}
            className="h-full w-full"
          >
            {activeCanvas?.canvasDraft ? (
              <ResizablePanelGroup orientation="horizontal" className="h-full">
                {/* Left: Chat panel */}
                <ResizablePanel defaultSize={40} minSize={25}>
                  <div className="flex flex-col h-full">
                    <BriefChatHeader
                      title={activeTask.title}
                      projectName={activeTask.projectName}
                      priority={activeTask.priority}
                      dueDate={activeTask.dueDate}
                    />
                    <div className="flex-1 min-h-0">
                      {isDbCheckPending ? (
                        <div className="px-5 py-5 space-y-3">
                          <Skeleton className="h-4 w-3/4" />
                          <Skeleton className="h-4 w-1/2" />
                          <Skeleton className="h-4 w-2/3" />
                        </div>
                      ) : (
                        <TaskBriefChat
                          key={activeTask.id}
                          taskId={activeTask.id}
                          projectId={activeTask.projectId}
                          initialBriefing={initialBriefing}
                          onBriefingReady={handleBriefingReady}
                        />
                      )}
                    </div>
                  </div>
                </ResizablePanel>

                <ResizableHandle withHandle />

                {/* Right: Canvas */}
                <ResizablePanel defaultSize={60} minSize={30}>
                  <CanvasPlaceholder
                    content={activeCanvas.canvasDraft}
                    kind={activeCanvas.canvasKind ?? null}
                  />
                </ResizablePanel>
              </ResizablePanelGroup>
            ) : (
              /* No canvas: chat centered */
              <div className="flex flex-col h-full w-full max-w-2xl mx-auto">
                <BriefChatHeader
                  title={activeTask.title}
                  projectName={activeTask.projectName}
                  priority={activeTask.priority}
                  dueDate={activeTask.dueDate}
                />
                <div className="flex-1 min-h-0">
                  {isDbCheckPending ? (
                    <div className="px-5 py-5 space-y-3">
                      <Skeleton className="h-4 w-3/4" />
                      <Skeleton className="h-4 w-1/2" />
                      <Skeleton className="h-4 w-2/3" />
                    </div>
                  ) : (
                    <TaskBriefChat
                      key={activeTask.id}
                      taskId={activeTask.id}
                      projectId={activeTask.projectId}
                      initialBriefing={initialBriefing}
                      onBriefingReady={handleBriefingReady}
                    />
                  )}
                </div>
              </div>
            )}
          </motion.div>
        </AnimatePresence>
      </div>

      {/* Bottom controls */}
      <div className="shrink-0">
        <CarouselControls
          count={tasks.length}
          activeIndex={activeIndex}
          onPrev={() => goTo(activeIndex - 1)}
          onNext={() => goTo(activeIndex + 1)}
        />
      </div>
    </div>
  );
}
