'use client';

import React, { createContext, useContext, useState, useEffect, useRef } from 'react';
import { RecordEvent, RecordingSession } from '@/types/record-mode';

interface RecordModeContextType {
  isActive: boolean;
  setIsActive: (active: boolean) => void;
  events: RecordEvent[];
  addEvent: (event: Omit<RecordEvent, 'id' | 'timestamp'>) => void;
  updateEvent: (id: string, event: Partial<RecordEvent>) => void;
  removeEvent: (id: string) => void;
  clearEvents: () => void;
  isPlaying: boolean;
  playEvents: () => void;
  stopPlayback: () => void;
  cursorPosition: { x: number; y: number };
  zoomLevel: number;
  isBlurry: boolean;
  currentSession: RecordingSession | null;
  saveSession: (name: string) => void;
  isFeedbackActive: boolean;
  setIsFeedbackActive: (active: boolean) => void;
}

const RecordModeContext = createContext<RecordModeContextType | null>(null);

export function useRecordMode(): RecordModeContextType {
  const context = useContext(RecordModeContext);
  if (!context) {
    // Return a fail-safe fallback for SSR/Static generation where provider might be missing
    return {
      isActive: false,
      setIsActive: () => { },
      events: [],
      addEvent: () => { },
      updateEvent: () => { },
      removeEvent: () => { },
      clearEvents: () => { },
      isPlaying: false,
      playEvents: () => { },
      stopPlayback: () => { },
      cursorPosition: { x: 0, y: 0 },
      zoomLevel: 1,
      isBlurry: false,
      currentSession: null,
      isFeedbackActive: false,
      setIsFeedbackActive: () => { },
      saveSession: () => { },
    };
  }
  return context;
}

export function RecordModeProvider({ children }: { children: React.ReactNode }) {
  const [isActive, setIsActiveState] = useState(false);
  const [events, setEvents] = useState<RecordEvent[]>([]);
  const [isPlaying, setIsPlaying] = useState(false);
  const [cursorPosition, setCursorPosition] = useState({ x: 0, y: 0 });
  const [zoomLevel, setZoomLevel] = useState(1);
  const [isBlurry, setIsBlurry] = useState(false);
  const [isFeedbackActive, setIsFeedbackActiveState] = useState(false);

  // Synchronous mutually exclusive setters
  const setIsActive = (active: boolean) => {
    setIsActiveState(active);
    if (active) setIsFeedbackActiveState(false);
  };

  const setIsFeedbackActive = (active: boolean) => {
    setIsFeedbackActiveState(active);
    if (active) setIsActiveState(false);
  };

  const playbackRequestRef = useRef<number>(0);
  const isPlayingRef = useRef(false);

  // Load draft from localStorage on mount
  useEffect(() => {
    const savedEvents = localStorage.getItem('klz-record-events');
    const savedActive = localStorage.getItem('klz-record-active');
    if (savedEvents) setEvents(JSON.parse(savedEvents));
    if (savedActive) setIsActive(JSON.parse(savedActive));
  }, []);

  // Sync events to localStorage
  useEffect(() => {
    localStorage.setItem('klz-record-events', JSON.stringify(events));
  }, [events]);

  // Sync active state to localStorage
  useEffect(() => {
    localStorage.setItem('klz-record-active', JSON.stringify(isActive));
    if (isActive && isFeedbackActive) {
      setIsFeedbackActive(false);
    }
  }, [isActive, isFeedbackActive]);

  useEffect(() => {
    if (isFeedbackActive && isActive) {
      setIsActive(false);
    }
  }, [isFeedbackActive, isActive]);

  const addEvent = (event: Omit<RecordEvent, 'id' | 'timestamp'>) => {
    const newEvent: RecordEvent = {
      ...event,
      id: Math.random().toString(36).substr(2, 9),
      timestamp: Date.now(),
    };
    setEvents((prev) => [...prev, newEvent]);
  };

  const updateEvent = (id: string, updatedFields: Partial<RecordEvent>) => {
    setEvents((prev) =>
      prev.map((event) => (event.id === id ? { ...event, ...updatedFields } : event))
    );
  };

  const removeEvent = (id: string) => {
    setEvents((prev) => prev.filter((event) => event.id !== id));
  };

  const clearEvents = () => {
    if (confirm('Clear all recorded events?')) {
      setEvents([]);
    }
  };

  const currentSession: RecordingSession | null = events.length > 0 ? {
    id: 'draft',
    name: 'Draft Session',
    events,
    createdAt: new Date().toISOString(),
  } : null;

  const saveSession = (name: string) => {
    // In a real app, this would be an API call
    console.log('Saving session:', name, events);
  };

  const playEvents = async () => {
    if (events.length === 0 || isPlayingRef.current) return;

    setIsPlaying(true);
    isPlayingRef.current = true;

    // Sort events by timestamp just in case
    const sortedEvents = [...events].sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0));

    for (const event of sortedEvents) {
      if (!isPlayingRef.current) break;

      // 1. Move Cursor
      if (event.rect) {
        setCursorPosition({
          x: event.rect.x + event.rect.width / 2,
          y: event.rect.y + event.rect.height / 2,
        });
      }

      // 2. Handle Action
      if (event.selector) {
        const el = document.querySelector(event.selector) as HTMLElement;
        if (el) {
          if (event.type === 'scroll') {
            el.scrollIntoView({ behavior: 'smooth', block: 'center' });
          } else if (event.type === 'click') {
            // Precise industrial click sequence: mousedown -> mouseup -> click
            const eventCoords = {
              clientX: event.rect ? event.rect.x + event.rect.width / 2 : 0,
              clientY: event.rect ? event.rect.y + event.rect.height / 2 : 0
            };

            const dispatchMouse = (type: string) => {
              el.dispatchEvent(new MouseEvent(type, {
                view: window,
                bubbles: true,
                cancelable: true,
                ...eventCoords
              }));
            };

            dispatchMouse('mousedown');
            dispatchMouse('mouseup');
            dispatchMouse('click');

            // Fallback for native elements
            el.click();
          }
        }
      }

      // 3. Zoom/Blur
      if (event.zoom) setZoomLevel(event.zoom);
      if (event.motionBlur) setIsBlurry(true);

      // 4. Wait
      await new Promise((resolve) => setTimeout(resolve, event.duration || 1000));
      setIsBlurry(false);
    }

    setIsPlaying(false);
    isPlayingRef.current = false;
    setZoomLevel(1);
  };

  const stopPlayback = () => {
    setIsPlaying(false);
    isPlayingRef.current = false;
    setZoomLevel(1);
    setIsBlurry(false);
  };

  return (
    <RecordModeContext.Provider
      value={{
        isActive,
        setIsActive,
        events,
        addEvent,
        updateEvent,
        removeEvent,
        clearEvents,
        isPlaying,
        playEvents,
        stopPlayback,
        cursorPosition,
        zoomLevel,
        isBlurry,
        currentSession,
        saveSession,
        isFeedbackActive,
        setIsFeedbackActive,
      }}
    >
      {children}
    </RecordModeContext.Provider>
  );
}
