import React, { useState, useEffect } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import type { Presentation, SlideContent } from '../../types/presentation';
import type { Theme, SlideLayout } from '../../types/theme';
import { getPresentationById, updatePresentation } from '../../utils/presentationStorage';
import { getTheme } from '../../themes';
import { renderTemplateWithSampleData } from '../../utils/templateRenderer';
import { sanitizeSlideTemplate } from '../../utils/htmlSanitizer';
import './SlideEditor.css';

export const SlideEditor: React.FC = () => {
  const { presentationId, slideId } = useParams<{ 
    presentationId: string; 
    slideId: string; 
  }>();
  const navigate = useNavigate();
  
  const [presentation, setPresentation] = useState<Presentation | null>(null);
  const [theme, setTheme] = useState<Theme | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  
  const isEditingExisting = slideId !== 'new';
  
  // Editor state
  const [selectedLayout, setSelectedLayout] = useState<SlideLayout | null>(null);
  const [slideContent, setSlideContent] = useState<Record<string, string>>({});
  const [slideNotes, setSlideNotes] = useState('');
  const [currentStep, setCurrentStep] = useState<'layout' | 'content'>(isEditingExisting ? 'content' : 'layout');
  const existingSlide = isEditingExisting && presentation 
    ? presentation.slides.find(s => s.id === slideId)
    : null;

  useEffect(() => {
    const loadPresentationAndTheme = async () => {
      if (!presentationId) {
        setError('No presentation ID provided');
        setLoading(false);
        return;
      }

      try {
        setLoading(true);
        
        // Load presentation
        const presentationData = await getPresentationById(presentationId);
        if (!presentationData) {
          setError(`Presentation not found: ${presentationId}`);
          return;
        }
        
        setPresentation(presentationData);
        
        // Load theme
        const themeData = await getTheme(presentationData.metadata.theme);
        if (!themeData) {
          setError(`Theme not found: ${presentationData.metadata.theme}`);
          return;
        }
        
        setTheme(themeData);
        
        // If editing existing slide, populate data
        if (isEditingExisting && slideId !== 'new') {
          const slide = presentationData.slides.find(s => s.id === slideId);
          if (slide) {
            const layout = themeData.layouts.find(l => l.id === slide.layoutId);
            if (layout) {
              setSelectedLayout(layout);
              setSlideContent(slide.content);
              setSlideNotes(slide.notes || '');
              // No need to set currentStep here since it's already 'content' for existing slides
            }
          } else {
            setError(`Slide not found: ${slideId}`);
            return;
          }
        }
        
      } catch (err) {
        setError(err instanceof Error ? err.message : 'Failed to load presentation');
      } finally {
        setLoading(false);
      }
    };

    loadPresentationAndTheme();
  }, [presentationId, slideId, isEditingExisting]);

  // Load theme CSS for layout previews
  useEffect(() => {
    if (theme) {
      const themeStyleId = 'slide-editor-theme-style';
      const existingStyle = document.getElementById(themeStyleId);
      
      if (existingStyle) {
        existingStyle.remove();
      }

      const link = document.createElement('link');
      link.id = themeStyleId;
      link.rel = 'stylesheet';
      link.href = `${theme.basePath}/${theme.cssFile}`;
      document.head.appendChild(link);

      return () => {
        const styleToRemove = document.getElementById(themeStyleId);
        if (styleToRemove) {
          styleToRemove.remove();
        }
      };
    }
  }, [theme]);

  const selectLayout = (layout: SlideLayout) => {
    setSelectedLayout(layout);
    
    // Initialize content with empty values for all slots
    const initialContent: Record<string, string> = {};
    layout.slots.forEach(slot => {
      initialContent[slot.id] = slideContent[slot.id] || '';
    });
    setSlideContent(initialContent);
    
    // Automatically move to content editing after layout selection
    setCurrentStep('content');
  };

  const updateSlotContent = (slotId: string, content: string) => {
    setSlideContent(prev => ({
      ...prev,
      [slotId]: content
    }));
  };

  const saveSlide = async () => {
    if (!presentation || !selectedLayout) return;
    
    try {
      setSaving(true);
      setError(null);
      
      const slideData: SlideContent = {
        id: isEditingExisting ? slideId! : `slide_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        layoutId: selectedLayout.id,
        content: slideContent,
        notes: slideNotes,
        order: isEditingExisting 
          ? (existingSlide?.order ?? presentation.slides.length)
          : presentation.slides.length
      };
      
      const updatedPresentation = { ...presentation };
      
      if (isEditingExisting) {
        // Update existing slide
        const slideIndex = updatedPresentation.slides.findIndex(s => s.id === slideId);
        if (slideIndex !== -1) {
          updatedPresentation.slides[slideIndex] = slideData;
        }
      } else {
        // Add new slide
        updatedPresentation.slides.push(slideData);
      }
      
      await updatePresentation(updatedPresentation);
      
      // Navigate back to editor with the updated slide
      const slideNumber = isEditingExisting 
        ? (updatedPresentation.slides.findIndex(s => s.id === slideData.id) + 1)
        : updatedPresentation.slides.length;
      
      navigate(`/presentations/${presentationId}/edit/slides/${slideNumber}`);
      
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save slide');
      console.error('Error saving slide:', err);
    } finally {
      setSaving(false);
    }
  };

  const cancelEditing = () => {
    if (isEditingExisting) {
      const slideIndex = presentation?.slides.findIndex(s => s.id === slideId) ?? 0;
      const slideNumber = slideIndex + 1;
      navigate(`/presentations/${presentationId}/edit/slides/${slideNumber}`);
    } else {
      navigate(`/presentations/${presentationId}/edit/slides/1`);
    }
  };

  if (loading) {
    return (
      <div className="slide-editor">
        <div className="loading-content">
          <div className="loading-spinner">Loading slide editor...</div>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="slide-editor">
        <div className="error-content">
          <h2>Error Loading Slide Editor</h2>
          <p>{error}</p>
          <Link to="/themes" className="back-link">← Back to Themes</Link>
        </div>
      </div>
    );
  }

  if (!presentation || !theme) {
    return (
      <div className="slide-editor">
        <div className="not-found-content">
          <h2>Presentation Not Found</h2>
          <p>The requested presentation could not be found.</p>
          <Link to="/themes" className="back-link">← Back to Themes</Link>
        </div>
      </div>
    );
  }

  return (
    <div className="slide-editor">
      <header className="slide-editor-header">
        <div className="editor-info">
          <button 
            onClick={cancelEditing}
            className="back-button"
            type="button"
          >
            ← Back to Presentation
          </button>
          <div className="editor-title">
            <h1>{isEditingExisting ? 'Edit Slide' : 'Add New Slide'}</h1>
            <p>{presentation.metadata.name} • {theme.name} theme</p>
          </div>
        </div>
        
        <div className="editor-actions">
          <button 
            type="button"
            className="action-button primary"
            onClick={saveSlide}
            disabled={!selectedLayout || saving}
          >
            {saving ? 'Saving...' : (isEditingExisting ? 'Update Slide' : 'Add Slide')}
          </button>
        </div>
      </header>

      <main className="slide-editor-content">
        {currentStep === 'layout' && (
          <div className="layout-selection">
            <div className="step-header">
              <h2>Choose a Layout</h2>
              <p>Select the layout that best fits your content</p>
            </div>
            
            <div className="layouts-grid">
              {theme.layouts.map((layout) => (
                <div
                  key={layout.id}
                  className={`layout-card ${selectedLayout?.id === layout.id ? 'selected' : ''}`}
                  onClick={() => selectLayout(layout)}
                >
                  <div className="layout-preview">
                    <div 
                      className="layout-rendered"
                      dangerouslySetInnerHTML={{
                        __html: sanitizeSlideTemplate(renderTemplateWithSampleData(layout.htmlTemplate, layout))
                      }}
                    />
                  </div>
                  <div className="layout-info">
                    <h3>{layout.name}</h3>
                    <p>{layout.description}</p>
                    <div className="layout-meta">
                      <span className="slot-count">{layout.slots.length} slots</span>
                      <div className="slot-types">
                        {Array.from(new Set(layout.slots.map(slot => slot.type))).map(type => (
                          <span key={type} className={`slot-type-badge ${type}`}>
                            {type}
                          </span>
                        ))}
                      </div>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {currentStep === 'content' && selectedLayout && presentation && (
          <div className="content-editing">
            <div className="editing-layout">
              <div className="content-form">
                <div className="step-header">
                  <h2>Edit Slide Content</h2>
                  <p>Fill in the content for your {selectedLayout.name} slide</p>
                </div>
                
                <div className="content-fields">
                  {selectedLayout.slots.map((slot) => (
                    <div key={slot.id} className="content-field">
                      <label htmlFor={slot.id} className="field-label">
                        {slot.id.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase())}
                        {slot.required && <span className="required">*</span>}
                      </label>
                      
                      {slot.type === 'text' && slot.id.includes('content') ? (
                        <textarea
                          id={slot.id}
                          value={slideContent[slot.id] || ''}
                          onChange={(e) => updateSlotContent(slot.id, e.target.value)}
                          placeholder={slot.placeholder || `Enter ${slot.id}`}
                          className="field-textarea"
                          rows={4}
                        />
                      ) : (
                        <input
                          id={slot.id}
                          type={slot.type === 'image' ? 'url' : 'text'}
                          value={slideContent[slot.id] || ''}
                          onChange={(e) => updateSlotContent(slot.id, e.target.value)}
                          placeholder={slot.placeholder || `Enter ${slot.id}`}
                          className="field-input"
                        />
                      )}
                      
                      {slot.placeholder && (
                        <p className="field-hint">{slot.placeholder}</p>
                      )}
                    </div>
                  ))}
                  
                  <div className="content-field">
                    <label htmlFor="slide-notes" className="field-label">
                      Speaker Notes
                    </label>
                    <textarea
                      id="slide-notes"
                      value={slideNotes}
                      onChange={(e) => setSlideNotes(e.target.value)}
                      placeholder="Add notes for this slide (optional)"
                      className="field-textarea"
                      rows={3}
                    />
                  </div>
                  
                  <div className="content-actions">
                    <div className="action-links">
                      <button 
                        type="button"
                        className="cancel-link"
                        onClick={cancelEditing}
                        disabled={saving}
                      >
                        Cancel editing
                      </button>
                    </div>
                    <div className="action-buttons">
                      <button 
                        type="button"
                        className="action-button primary"
                        onClick={saveSlide}
                        disabled={saving}
                      >
                        {saving ? 'Saving...' : (isEditingExisting ? 'Update Slide' : 'Save Slide')}
                      </button>
                    </div>
                  </div>
                </div>
              </div>
              
              <div className="content-preview">
                <h3>Live Preview</h3>
                <p className="preview-description">
                  Updates automatically as you type
                </p>
                <div className="preview-container">
                  <div className="slide-preview-wrapper">
                    <div 
                      className={`slide-container ${presentation.metadata.aspectRatio ? `aspect-${presentation.metadata.aspectRatio.replace(':', '-')}` : 'aspect-16-9'}`}
                      dangerouslySetInnerHTML={{
                        __html: sanitizeSlideTemplate(renderTemplateWithContent(selectedLayout, slideContent))
                      }}
                    />
                  </div>
                  <div className="preview-meta">
                    <span className="layout-name">{selectedLayout.name}</span>
                    <span className="aspect-ratio-info">
                      {presentation.metadata.aspectRatio || '16:9'} aspect ratio
                    </span>
                    <span className="content-count">
                      {Object.values(slideContent).filter(v => v.trim()).length} / {selectedLayout.slots.length} slots filled
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        )}

        {error && (
          <div className="editor-error">
            <p>Error: {error}</p>
          </div>
        )}
      </main>
    </div>
  );
};

// Helper function to render template with actual content
const renderTemplateWithContent = (layout: SlideLayout, content: Record<string, string>): string => {
  let rendered = layout.htmlTemplate;
  
  // Replace content placeholders
  Object.entries(content).forEach(([slotId, value]) => {
    const placeholder = new RegExp(`\\{\\{${slotId}\\}\\}`, 'g');
    rendered = rendered.replace(placeholder, value || '');
  });
  
  // Clean up any remaining placeholders
  rendered = rendered.replace(/\{\{[^}]+\}\}/g, '');
  
  return rendered;
};