import React, { useState, useEffect} from 'react';
import { useParams, useNavigate } from 'react-router-dom';

import { renderTemplateWithSampleData } from '../../utils/templateRenderer.ts';
import { sanitizeSlideTemplate } from '../../utils/htmlSanitizer.ts';
import { renderSlideMarkdown, isMarkdownContent } from '../../utils/markdownProcessor.ts';
import { highlightCode } from '../../utils/codeHighlighter.ts';
import { renderDiagram } from '../../utils/diagramProcessor.ts';
import { loggers } from '../../utils/logger.ts';
import './PresentationMode.css';
import {usePresentationLoader} from "./hooks/usePresentationLoader.ts";
import type { SlideContent } from '../../types/presentation.ts';
import {useKeyboardNavigation} from "./hooks/useKeyboardNavigation.ts";

export const PresentationMode: React.FC = () => {
  const { presentationId, slideNumber } = useParams<{ 
    presentationId: string; 
    slideNumber: string; 
  }>();
  const navigate = useNavigate();

  const [currentSlideIndex, setCurrentSlideIndex] = useState(
    slideNumber ? parseInt(slideNumber, 10) - 1 : 0
  );
  const [renderedSlideContent, setRenderedSlideContent] = useState<string>('');
  const [isRenderingSlide, setIsRenderingSlide] = useState(false);

  // Load presentation and theme
  const { presentation, theme, loading, error } = usePresentationLoader(presentationId);
  // Navigate to specific slide and update URL
  const goToSlide = (slideIndex: number) => {
    if (!presentation) return;
    
    const clampedIndex = Math.max(0, Math.min(slideIndex, presentation.slides.length - 1));
    setCurrentSlideIndex(clampedIndex);
    navigate(`/presentations/${presentationId}/present/${clampedIndex + 1}`, { replace: true });
  };


  // Keyboard navigation handler

  useKeyboardNavigation({
    totalSlides: presentation?.slides.length || 0,
    currentSlideIndex,
    onNavigate: goToSlide
  });

  // Sync current slide index with URL parameter
  useEffect(() => {
    if (slideNumber) {
      const newIndex = parseInt(slideNumber, 10) - 1;
      if (newIndex >= 0 && newIndex !== currentSlideIndex) {
        setCurrentSlideIndex(newIndex);
      }
    }
  }, [slideNumber]);

  // Render current slide content when slide changes
  useEffect(() => {
    const renderCurrentSlide = async () => {
      if (!presentation || !theme || currentSlideIndex < 0 || currentSlideIndex >= presentation.slides.length) {
        setRenderedSlideContent('');
        return;
      }

      setIsRenderingSlide(true);
      try {
        const slide = presentation.slides[currentSlideIndex];
        const rendered = await renderSlideContent(slide);
        setRenderedSlideContent(rendered);
      } catch (error) {
        console.error('Failed to render slide:', error);
        setRenderedSlideContent('<div class="error">Failed to render slide</div>');
      } finally {
        setIsRenderingSlide(false);
      }
    };

    renderCurrentSlide();
  }, [presentation, theme, currentSlideIndex]);

  const renderSlideContent = async (slide: SlideContent): Promise<string> => {
    if (!theme) return '';
    
    const layout = theme.layouts.find(l => l.id === slide.layoutId);
    if (!layout) {
      loggers.ui.warn(`Layout ${slide.layoutId} not found in theme ${theme.name}`);
      return '<div class="error">Layout not found</div>';
    }
    
    let renderedTemplate = layout.htmlTemplate;
    
    // Replace template variables with slide content
    for (const [slotId, content] of Object.entries(slide.content)) {
      const regex = new RegExp(`\\{\\{${slotId}\\}\\}`, 'g');
      
      // Find the corresponding slot to determine processing type
      const slot = layout.slots.find(s => s.id === slotId);
      
      let processedContent = content;
      
      // Process based on slot type
      if (slot?.type === 'code') {
        // Handle code highlighting
        const language = slot.attributes?.['data-language'] || 'javascript';
        processedContent = highlightCode(content, language);
      } else if (slot?.type === 'diagram') {
        // Handle diagram rendering
        processedContent = await renderDiagram(content);
      } else if (slot?.type === 'markdown' || (slot?.type === 'text' && isMarkdownContent(content))) {
        // Handle markdown processing
        processedContent = renderSlideMarkdown(content, slot?.type);
      }
      
      renderedTemplate = renderedTemplate.replace(regex, processedContent);
    }
    
    // Handle conditional blocks and clean up remaining variables
    renderedTemplate = renderTemplateWithSampleData(renderedTemplate, layout);
    
    return sanitizeSlideTemplate(renderedTemplate);
  };
  
  if (loading) {
    return (
      <div className="presentation-mode loading">
        <div className="loading-spinner">Loading presentation...</div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="presentation-mode error">
        <div className="error-content">
          <h2>Error Loading Presentation</h2>
          <p>{error}</p>
          <button onClick={() => navigate(-1)} className="exit-button">
            Exit Presentation Mode
          </button>
        </div>
      </div>
    );
  }

  if (!presentation || !theme) {
    return (
      <div className="presentation-mode error">
        <div className="error-content">
          <h2>Presentation Not Found</h2>
          <button onClick={() => navigate(-1)} className="exit-button">
            Exit Presentation Mode
          </button>
        </div>
      </div>
    );
  }

  if (presentation.slides.length === 0) {
    return (
      <div className="presentation-mode error">
        <div className="error-content">
          <h2>No Slides Available</h2>
          <p>This presentation is empty.</p>
          <button onClick={() => navigate(-1)} className="exit-button">
            Exit Presentation Mode
          </button>
        </div>
      </div>
    );
  }

  const totalSlides = presentation.slides.length;

  return (
    <div className="presentation-mode fullscreen">
      <div className="slide-container">
        {isRenderingSlide && (
          <div className="slide-loading">
            <div className="loading-spinner"></div>
            <span>Rendering slide...</span>
          </div>
        )}
        <div 
          className={`slide-content ${presentation.metadata.aspectRatio ? `aspect-${presentation.metadata.aspectRatio.replace(':', '-')}` : 'aspect-16-9'}`}
          dangerouslySetInnerHTML={{ __html: renderedSlideContent }}
          style={{ opacity: isRenderingSlide ? 0.5 : 1 }}
        />
      </div>
      
      {/* Navigation indicator */}
      <div className="navigation-indicator">
        <span className="slide-counter">
          {currentSlideIndex + 1} / {totalSlides}
        </span>
        
        <div className="navigation-hints">
          <span>← → Space: Navigate</span>
          <span>Esc: Exit</span>
        </div>
      </div>
    </div>
  );
};