'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;
  setEvents: (events: RecordEvent[]) => 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;
  reorderEvents: (startIndex: number, endIndex: number) => void;
  hoveredEventId: string | null;
  setHoveredEventId: (id: string | null) => 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: () => { },
      reorderEvents: () => { },
      hoveredEventId: null,
      setHoveredEventId: () => { },
      setEvents: () => { },
    };
  }
  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);
  const [hoveredEventId, setHoveredEventId] = useState<string | null>(null);
  const [isEmbedded, setIsEmbedded] = useState(false);

  useEffect(() => {
    const embedded = typeof window !== 'undefined' &&
      (window.location.search.includes('embedded=true') ||
        window.name === 'record-mode-iframe' ||
        window.self !== window.top);
    setIsEmbedded(embedded);
  }, []);

  // 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]);

  // GUEST LISTENERS: Execute events coming from host
  useEffect(() => {
    if (!isEmbedded) return;

    const handlePlaybackMessage = (e: MessageEvent) => {
      if (e.data.type === 'PLAY_EVENT') {
        const { event } = e.data;
        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 === 'mouse') {
              const currentRect = el.getBoundingClientRect();

              // Calculate Point based on Origin
              let targetX = currentRect.left + currentRect.width / 2;
              let targetY = currentRect.top + currentRect.height / 2;

              if (event.clickOrigin === 'top-left') {
                targetX = currentRect.left + 5;
                targetY = currentRect.top + 5;
              } else if (event.clickOrigin === 'top-right') {
                targetX = currentRect.right - 5;
                targetY = currentRect.top + 5;
              } else if (event.clickOrigin === 'bottom-left') {
                targetX = currentRect.left + 5;
                targetY = currentRect.bottom - 5;
              } else if (event.clickOrigin === 'bottom-right') {
                targetX = currentRect.right - 5;
                targetY = currentRect.bottom - 5;
              }

              const eventCoords = {
                clientX: targetX,
                clientY: targetY
              };

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

              if (event.interactionType === 'click') {
                dispatchMouse('mousedown');
                dispatchMouse('mouseup');
                dispatchMouse('click');

                if (event.realClick) {
                  el.click();
                }
              } else {
                // Hover Interaction
                dispatchMouse('mousemove');
                dispatchMouse('mouseover');
                dispatchMouse('mouseenter');
              }
            }
          }
        }
      }
    };

    window.addEventListener('message', handlePlaybackMessage);
    return () => window.removeEventListener('message', handlePlaybackMessage);
  }, [isEmbedded]);

  // Sync Hover Preview to Iframe
  useEffect(() => {
    if (isEmbedded || !isActive) return;

    const event = events.find(e => e.id === hoveredEventId);
    const iframe = document.querySelector('iframe[name="record-mode-iframe"]') as HTMLIFrameElement;
    if (iframe?.contentWindow) {
      iframe.contentWindow.postMessage({
        type: 'SET_HOVER_SELECTOR',
        selector: event?.selector || null
      }, '*');
    }
  }, [hoveredEventId, events, isActive, isEmbedded]);

  const reorderEvents = (startIndex: number, endIndex: number) => {
    const result = Array.from(events);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    setEvents(result);
  };

  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 (Host logic)
      if (event.rect && !isEmbedded) {
        const iframe = document.querySelector('iframe[name="record-mode-iframe"]') as HTMLIFrameElement;
        const iframeRect = iframe?.getBoundingClientRect();

        // Add iframe offset to guest-relative coordinates
        setCursorPosition({
          x: (iframeRect?.left || 0) + event.rect.x + event.rect.width / 2,
          y: (iframeRect?.top || 0) + event.rect.y + event.rect.height / 2,
        });
      }

      // 2. Handle Action
      if (event.selector) {
        if (!isEmbedded) {
          // HOST: Delegate to Iframe
          const iframe = document.querySelector('iframe[name="record-mode-iframe"]') as HTMLIFrameElement;
          if (iframe?.contentWindow) {
            iframe.contentWindow.postMessage({ type: 'PLAY_EVENT', event }, '*');
          }
        } else {
          // GUEST (Self-execution failsafe)
          const el = document.querySelector(event.selector) as HTMLElement;
          if (el) {
            if (event.type === 'scroll') {
              el.scrollIntoView({ behavior: 'smooth', block: 'center' });
            } else if (event.type === 'mouse') {
              const currentRect = el.getBoundingClientRect();

              // Calculate Point based on Origin (same as above for parity)
              let targetX = currentRect.left + currentRect.width / 2;
              let targetY = currentRect.top + currentRect.height / 2;

              if (event.clickOrigin === 'top-left') {
                targetX = currentRect.left + 5;
                targetY = currentRect.top + 5;
              } else if (event.clickOrigin === 'top-right') {
                targetX = currentRect.right - 5;
                targetY = currentRect.top + 5;
              } else if (event.clickOrigin === 'bottom-left') {
                targetX = currentRect.left + 5;
                targetY = currentRect.bottom - 5;
              } else if (event.clickOrigin === 'bottom-right') {
                targetX = currentRect.right - 5;
                targetY = currentRect.bottom - 5;
              }

              const eventCoords = {
                clientX: targetX,
                clientY: targetY
              };

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

              if (event.interactionType === 'click') {
                dispatchMouse('mousedown');
                dispatchMouse('mouseup');
                dispatchMouse('click');

                if (event.realClick) {
                  el.click();
                }
              } else {
                // Hover Interaction
                dispatchMouse('mousemove');
                dispatchMouse('mouseover');
                dispatchMouse('mouseenter');
              }
            }
          }
        }
      }

      // 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,
        setEvents,
        isPlaying,
        playEvents,
        stopPlayback,
        cursorPosition,
        zoomLevel,
        isBlurry,
        currentSession,
        saveSession,
        isFeedbackActive,
        setIsFeedbackActive,
        reorderEvents,
        hoveredEventId,
        setHoveredEventId,
      }}
    >
      {children}
    </RecordModeContext.Provider>
  );
}
