import React, { useState, useMemo, useCallback } from 'react';
import { Line, Bar } from 'react-chartjs-2';
import { chartColors, createBaseOptions } from '../config/chartConfig';
import { useLanguage } from '../contexts/LanguageContext';
import {
  filterDataByDateRange,
  calculateMetrics,
  formatCompact,
  formatCompactCurrency,
  getUniqueChannels,
  getUniqueMuseums
} from '../services/dataService';
import JSZip from 'jszip';
import type {
  MuseumRecord,
  SlideConfig,
  ChartTypeOption,
  MetricOption,
  MetricFieldInfo,
  SlidesProps
} from '../types';

interface SlideEditorProps {
  slide: SlideConfig;
  onUpdate: (updates: Partial<SlideConfig>) => void;
  channels: string[];
  museums: string[];
  data: MuseumRecord[];
  chartTypes: ChartTypeOption[];
  metrics: MetricOption[];
}

interface SlidePreviewProps {
  slide: SlideConfig;
  data: MuseumRecord[];
  channels: string[];
  museums: string[];
  metrics: MetricOption[];
}

interface PreviewModeProps {
  slides: SlideConfig[];
  data: MuseumRecord[];
  channels: string[];
  museums: string[];
  currentSlide: number;
  setCurrentSlide: React.Dispatch<React.SetStateAction<number>>;
  onExit: () => void;
  metrics: MetricOption[];
}

function Slides({ data }: SlidesProps) {
  const { t } = useLanguage();

  const CHART_TYPES: ChartTypeOption[] = useMemo(() => [
    { id: 'trend', label: t('slides.revenueTrend'), icon: '📈' },
    { id: 'museum-bar', label: t('slides.byMuseum'), icon: '📊' },
    { id: 'kpi-cards', label: t('slides.kpiSummary'), icon: '🎯' },
    { id: 'comparison', label: t('slides.yoyComparison'), icon: '⚖️' }
  ], [t]);

  const METRICS: MetricOption[] = useMemo(() => [
    { id: 'revenue', label: t('metrics.revenue'), field: 'revenue_gross' },
    { id: 'visitors', label: t('metrics.visitors'), field: 'visits' },
    { id: 'tickets', label: t('metrics.tickets'), field: 'tickets' }
  ], [t]);
  const [slides, setSlides] = useState<SlideConfig[]>([]);
  const [editingSlide, setEditingSlide] = useState<number | null>(null);
  const [previewMode, setPreviewMode] = useState(false);
  const [currentPreviewSlide, setCurrentPreviewSlide] = useState(0);

  const channels = useMemo(() => getUniqueChannels(data), [data]);
  const museums = useMemo(() => getUniqueMuseums(data), [data]);

  const defaultSlideConfig: Omit<SlideConfig, 'id'> = {
    title: 'Slide Title',
    chartType: 'trend',
    metric: 'revenue',
    startDate: '2026-01-01',
    endDate: '2026-01-31',
    channel: 'all',
    museum: 'all',
    showComparison: false
  };

  const addSlide = () => {
    const newSlide: SlideConfig = {
      id: Date.now(),
      ...defaultSlideConfig,
      title: `Slide ${slides.length + 1}`
    };
    setSlides([...slides, newSlide]);
    setEditingSlide(newSlide.id);
  };

  const updateSlide = (id: number, updates: Partial<SlideConfig>) => {
    setSlides(slides.map(s => s.id === id ? { ...s, ...updates } : s));
  };

  const removeSlide = (id: number) => {
    setSlides(slides.filter(s => s.id !== id));
    if (editingSlide === id) setEditingSlide(null);
  };

  const moveSlide = (id: number, direction: number) => {
    const index = slides.findIndex(s => s.id === id);
    if ((direction === -1 && index === 0) || (direction === 1 && index === slides.length - 1)) return;
    const newSlides = [...slides];
    [newSlides[index], newSlides[index + direction]] = [newSlides[index + direction], newSlides[index]];
    setSlides(newSlides);
  };

  const duplicateSlide = (id: number) => {
    const slide = slides.find(s => s.id === id);
    if (slide) {
      const newSlide: SlideConfig = { ...slide, id: Date.now(), title: `${slide.title} (copy)` };
      const index = slides.findIndex(s => s.id === id);
      const newSlides = [...slides];
      newSlides.splice(index + 1, 0, newSlide);
      setSlides(newSlides);
    }
  };

  const exportAsHTML = async () => {
    const zip = new JSZip();

    // Generate HTML for each slide
    const slidesHTML = slides.map((slide, index) => {
      return generateSlideHTML(slide, index, data);
    }).join('\n');

    const fullHTML = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HiHala Data Presentation</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { font-family: 'Segoe UI', system-ui, sans-serif; background: #0f172a; }
    .slide {
      width: 100vw; height: 100vh;
      display: flex; flex-direction: column;
      justify-content: center; align-items: center;
      padding: 60px; background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
      page-break-after: always;
    }
    .slide-title {
      color: #f8fafc; font-size: 2.5rem; font-weight: 600;
      margin-bottom: 40px; text-align: center;
    }
    .slide-subtitle {
      color: #94a3b8; font-size: 1.1rem; margin-bottom: 30px;
    }
    .chart-container {
      width: 100%; max-width: 900px; height: 400px;
      background: rgba(255,255,255,0.03); border-radius: 16px;
      padding: 30px;
    }
    .kpi-grid {
      display: grid; grid-template-columns: repeat(3, 1fr);
      gap: 30px; width: 100%; max-width: 900px;
    }
    .kpi-card {
      background: rgba(255,255,255,0.05); border-radius: 16px;
      padding: 30px; text-align: center;
    }
    .kpi-value { color: #3b82f6; font-size: 2.5rem; font-weight: 700; }
    .kpi-label { color: #94a3b8; font-size: 1rem; margin-top: 8px; }
    .logo { position: absolute; bottom: 30px; right: 40px; opacity: 0.6; }
    .logo svg { height: 30px; }
    .slide-number {
      position: absolute; bottom: 30px; left: 40px;
      color: #475569; font-size: 0.9rem;
    }
    @media print {
      .slide { page-break-after: always; }
    }
  </style>
</head>
<body>
${slidesHTML}
<script>
// Chart.js initialization scripts will be here
${generateChartScripts(slides, data)}
</script>
</body>
</html>`;

    zip.file('presentation.html', fullHTML);

    const blob = await zip.generateAsync({ type: 'blob' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'hihala-presentation.zip';
    a.click();
    URL.revokeObjectURL(url);
  };

  if (previewMode) {
    return (
      <PreviewMode
        slides={slides}
        data={data}
        channels={channels}
        museums={museums}
        currentSlide={currentPreviewSlide}
        setCurrentSlide={setCurrentPreviewSlide}
        onExit={() => setPreviewMode(false)}
        metrics={METRICS}
      />
    );
  }

  return (
    <div className="slides-builder">
      <div className="page-title">
        <h1>{t('slides.title')}</h1>
        <p>{t('slides.subtitle')}</p>
      </div>

      <div className="slides-toolbar">
        <button className="btn-primary" onClick={addSlide}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
          </svg>
          {t('slides.addSlide')}
        </button>
        {slides.length > 0 && (
          <>
            <button className="btn-secondary" onClick={() => setPreviewMode(true)}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/>
              </svg>
              {t('slides.preview')}
            </button>
            <button className="btn-secondary" onClick={exportAsHTML}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
              </svg>
              {t('slides.exportHtml')}
            </button>
          </>
        )}
      </div>

      <div className="slides-workspace">
        <div className="slides-list">
          <h3>{t('slides.slidesCount')} ({slides.length})</h3>
          {slides.length === 0 ? (
            <div className="empty-slides">
              <p>{t('slides.noSlides')}</p>
              <button onClick={addSlide}>{t('slides.addFirst')}</button>
            </div>
          ) : (
            <div className="slides-thumbnails">
              {slides.map((slide, index) => (
                <div
                  key={slide.id}
                  className={`slide-thumbnail ${editingSlide === slide.id ? 'active' : ''}`}
                  onClick={() => setEditingSlide(slide.id)}
                >
                  <div className="slide-number">{index + 1}</div>
                  <div className="slide-icon">{CHART_TYPES.find(c => c.id === slide.chartType)?.icon}</div>
                  <div className="slide-title-preview">{slide.title}</div>
                  <div className="slide-actions">
                    <button onClick={(e) => { e.stopPropagation(); moveSlide(slide.id, -1); }} disabled={index === 0}>↑</button>
                    <button onClick={(e) => { e.stopPropagation(); moveSlide(slide.id, 1); }} disabled={index === slides.length - 1}>↓</button>
                    <button onClick={(e) => { e.stopPropagation(); duplicateSlide(slide.id); }}>⎘</button>
                    <button onClick={(e) => { e.stopPropagation(); removeSlide(slide.id); }} className="delete">×</button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        {editingSlide && (
          <SlideEditor
            slide={slides.find(s => s.id === editingSlide)!}
            onUpdate={(updates) => updateSlide(editingSlide, updates)}
            channels={channels}
            museums={museums}
            data={data}
            chartTypes={CHART_TYPES}
            metrics={METRICS}
          />
        )}
      </div>
    </div>
  );
}

function SlideEditor({ slide, onUpdate, channels, museums, data, chartTypes, metrics }: SlideEditorProps) {
  const { t } = useLanguage();

  return (
    <div className="slide-editor">
      <div className="editor-section">
        <label>{t('slides.slideTitle')}</label>
        <input
          type="text"
          value={slide.title}
          onChange={e => onUpdate({ title: e.target.value })}
          placeholder={t('slides.slideTitle')}
        />
      </div>

      <div className="editor-section">
        <label>{t('slides.chartType')}</label>
        <div className="chart-type-grid">
          {chartTypes.map((type: ChartTypeOption) => (
            <button
              key={type.id}
              className={`chart-type-btn ${slide.chartType === type.id ? 'active' : ''}`}
              onClick={() => onUpdate({ chartType: type.id })}
            >
              <span className="chart-icon">{type.icon}</span>
              <span>{type.label}</span>
            </button>
          ))}
        </div>
      </div>

      <div className="editor-section">
        <label>{t('slides.metric')}</label>
        <select value={slide.metric} onChange={e => onUpdate({ metric: e.target.value })}>
          {metrics.map((m: MetricOption) => <option key={m.id} value={m.id}>{m.label}</option>)}
        </select>
      </div>

      <div className="editor-row">
        <div className="editor-section">
          <label>{t('slides.startDate')}</label>
          <input type="date" value={slide.startDate} onChange={e => onUpdate({ startDate: e.target.value })} />
        </div>
        <div className="editor-section">
          <label>{t('slides.endDate')}</label>
          <input type="date" value={slide.endDate} onChange={e => onUpdate({ endDate: e.target.value })} />
        </div>
      </div>

      <div className="editor-row">
        <div className="editor-section">
          <label>{t('filters.channel')}</label>
          <select value={slide.channel} onChange={e => onUpdate({ channel: e.target.value, museum: 'all' })}>
            <option value="all">{t('filters.allChannels')}</option>
            {channels.map((d: string) => <option key={d} value={d}>{d}</option>)}
          </select>
        </div>
        <div className="editor-section">
          <label>{t('filters.museum')}</label>
          <select value={slide.museum} onChange={e => onUpdate({ museum: e.target.value })}>
            <option value="all">{t('filters.allMuseums')}</option>
            {museums.map((m: string) => <option key={m} value={m}>{m}</option>)}
          </select>
        </div>
      </div>

      {slide.chartType === 'comparison' && (
        <div className="editor-section">
          <label>
            <input
              type="checkbox"
              checked={slide.showComparison}
              onChange={e => onUpdate({ showComparison: e.target.checked })}
            />
            {t('slides.showYoY')}
          </label>
        </div>
      )}

      <div className="slide-preview-box">
        <h4>{t('slides.preview')}</h4>
        <SlidePreview slide={slide} data={data} channels={channels} museums={museums} metrics={metrics} />
      </div>
    </div>
  );
}

// Static field mapping for charts (Chart.js labels don't need i18n)
const METRIC_FIELDS: Record<string, MetricFieldInfo> = {
  revenue: { field: 'revenue_gross', label: 'Revenue' },
  visitors: { field: 'visits', label: 'Visitors' },
  tickets: { field: 'tickets', label: 'Tickets' }
};

function SlidePreview({ slide, data, channels, museums, metrics }: SlidePreviewProps) {
  const { t } = useLanguage();
  const filteredData = useMemo(() =>
    filterDataByDateRange(data, slide.startDate, slide.endDate, {
      channel: slide.channel,
      museum: slide.museum
    }),
    [data, slide.startDate, slide.endDate, slide.channel, slide.museum]
  );

  const metricsData = useMemo(() => calculateMetrics(filteredData), [filteredData]);
  const baseOptions = useMemo(() => createBaseOptions(false), []);

  const getMetricValue = useCallback((rows: MuseumRecord[], metric: string) => {
    const fieldMap: Record<string, string> = { revenue: 'revenue_gross', visitors: 'visits', tickets: 'tickets' };
    return rows.reduce((s: number, r: MuseumRecord) => s + parseFloat(String((r as unknown as Record<string, unknown>)[fieldMap[metric]] || 0)), 0);
  }, []);

  const trendData = useMemo(() => {
    const grouped: Record<string, MuseumRecord[]> = {};
    filteredData.forEach(row => {
      if (!row.date) return;
      const weekStart = row.date.substring(0, 10);
      if (!grouped[weekStart]) grouped[weekStart] = [];
      grouped[weekStart].push(row);
    });

    const sortedDates = Object.keys(grouped).sort();
    const metricLabel = metrics?.find((m: MetricOption) => m.id === slide.metric)?.label || METRIC_FIELDS[slide.metric]?.label || slide.metric;
    return {
      labels: sortedDates.map(d => d.substring(5)),
      datasets: [{
        label: metricLabel,
        data: sortedDates.map(d => getMetricValue(grouped[d], slide.metric)),
        borderColor: chartColors.primary,
        backgroundColor: chartColors.primary + '20',
        fill: true,
        tension: 0.4
      }]
    };
  }, [filteredData, slide.metric, getMetricValue, metrics]);

  const museumData = useMemo(() => {
    const byMuseum: Record<string, MuseumRecord[]> = {};
    filteredData.forEach(row => {
      if (!row.museum_name) return;
      if (!byMuseum[row.museum_name]) byMuseum[row.museum_name] = [];
      byMuseum[row.museum_name].push(row);
    });

    const museums = Object.keys(byMuseum).sort();
    const metricLabel = metrics?.find((m: MetricOption) => m.id === slide.metric)?.label || METRIC_FIELDS[slide.metric]?.label || slide.metric;
    return {
      labels: museums,
      datasets: [{
        label: metricLabel,
        data: museums.map(m => getMetricValue(byMuseum[m], slide.metric)),
        backgroundColor: chartColors.primary,
        borderRadius: 6
      }]
    };
  }, [filteredData, slide.metric, getMetricValue, metrics]);

  if (slide.chartType === 'kpi-cards') {
    return (
      <div className="preview-kpis">
        <div className="preview-kpi">
          <div className="kpi-value">{formatCompactCurrency(metricsData.revenue)}</div>
          <div className="kpi-label">{t('metrics.revenue')}</div>
        </div>
        <div className="preview-kpi">
          <div className="kpi-value">{formatCompact(metricsData.visitors)}</div>
          <div className="kpi-label">{t('metrics.visitors')}</div>
        </div>
        <div className="preview-kpi">
          <div className="kpi-value">{formatCompact(metricsData.tickets)}</div>
          <div className="kpi-label">{t('metrics.tickets')}</div>
        </div>
      </div>
    );
  }

  if (slide.chartType === 'museum-bar') {
    return (
      <div className="preview-chart">
        <Bar data={museumData} options={{ ...baseOptions, indexAxis: 'y' }} />
      </div>
    );
  }

  return (
    <div className="preview-chart">
      <Line data={trendData} options={baseOptions} />
    </div>
  );
}

function PreviewMode({ slides, data, channels, museums, currentSlide, setCurrentSlide, onExit, metrics }: PreviewModeProps) {
  const { t } = useLanguage();
  const handleKeyDown = useCallback((e: KeyboardEvent) => {
    if (e.key === 'ArrowRight' || e.key === ' ') {
      setCurrentSlide((prev: number) => Math.min(prev + 1, slides.length - 1));
    } else if (e.key === 'ArrowLeft') {
      setCurrentSlide((prev: number) => Math.max(prev - 1, 0));
    } else if (e.key === 'Escape') {
      onExit();
    }
  }, [slides.length, setCurrentSlide, onExit]);

  React.useEffect(() => {
    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [handleKeyDown]);

  const slide = slides[currentSlide];

  return (
    <div className="preview-fullscreen">
      <div className="preview-slide">
        <h1 className="preview-title">{slide?.title}</h1>
        <div className="preview-content">
          {slide && <SlidePreview slide={slide} data={data} channels={channels} museums={museums} metrics={metrics} />}
        </div>
        <div className="preview-footer">
          <span>{currentSlide + 1} / {slides.length}</span>
        </div>
      </div>
      <div className="preview-controls">
        <button onClick={() => setCurrentSlide((prev: number) => Math.max(prev - 1, 0))} disabled={currentSlide === 0}>←</button>
        <button onClick={() => setCurrentSlide((prev: number) => Math.min(prev + 1, slides.length - 1))} disabled={currentSlide === slides.length - 1}>→</button>
        <button onClick={onExit}>{t('slides.exit')}</button>
      </div>
    </div>
  );
}

// Helper functions for HTML export
function generateSlideHTML(slide: SlideConfig, index: number, data: MuseumRecord[]): string {
  const chartType = slide.chartType;
  const canvasId = `chart-${index}`;

  return `
  <div class="slide" id="slide-${index}">
    <h1 class="slide-title">${slide.title}</h1>
    <p class="slide-subtitle">${formatDateRange(slide.startDate, slide.endDate)}</p>
    ${chartType === 'kpi-cards' ? generateKPIHTML(slide, data) : `<div class="chart-container"><canvas id="${canvasId}"></canvas></div>`}
    <div class="slide-number">Slide ${index + 1}</div>
    <div class="logo">
      <svg width="120" height="24" viewBox="0 0 120 24">
        <text x="0" y="18" fill="#64748b" font-family="system-ui" font-size="14" font-weight="600">HiHala Data</text>
      </svg>
    </div>
  </div>`;
}

function generateKPIHTML(slide: SlideConfig, data: MuseumRecord[]): string {
  const filtered = filterDataByDateRange(data, slide.startDate, slide.endDate, {
    channel: slide.channel,
    museum: slide.museum
  });
  const metrics = calculateMetrics(filtered);

  return `
    <div class="kpi-grid">
      <div class="kpi-card">
        <div class="kpi-value">${formatCompactCurrency(metrics.revenue)}</div>
        <div class="kpi-label">Revenue</div>
      </div>
      <div class="kpi-card">
        <div class="kpi-value">${formatCompact(metrics.visitors)}</div>
        <div class="kpi-label">Visitors</div>
      </div>
      <div class="kpi-card">
        <div class="kpi-value">${formatCompact(metrics.tickets)}</div>
        <div class="kpi-label">Tickets</div>
      </div>
    </div>`;
}

function generateChartScripts(slides: SlideConfig[], data: MuseumRecord[]): string {
  return slides.map((slide: SlideConfig, index: number) => {
    if (slide.chartType === 'kpi-cards') return '';

    const filtered = filterDataByDateRange(data, slide.startDate, slide.endDate, {
      channel: slide.channel,
      museum: slide.museum
    });

    const chartConfig = generateChartConfig(slide, filtered);

    return `
    new Chart(document.getElementById('chart-${index}'), ${JSON.stringify(chartConfig)});
    `;
  }).join('\n');
}

function generateChartConfig(slide: SlideConfig, data: MuseumRecord[]): object {
  const fieldMap: Record<string, keyof MuseumRecord> = { revenue: 'revenue_gross', visitors: 'visits', tickets: 'tickets' };
  const field = fieldMap[slide.metric];

  if (slide.chartType === 'museum-bar') {
    const byMuseum: Record<string, number> = {};
    data.forEach((row: MuseumRecord) => {
      if (!row.museum_name) return;
      byMuseum[row.museum_name] = (byMuseum[row.museum_name] || 0) + parseFloat(String(row[field] || 0));
    });
    const museums = Object.keys(byMuseum).sort();

    return {
      type: 'bar',
      data: {
        labels: museums,
        datasets: [{
          data: museums.map(m => byMuseum[m]),
          backgroundColor: '#3b82f6',
          borderRadius: 6
        }]
      },
      options: { indexAxis: 'y', plugins: { legend: { display: false } } }
    };
  }

  // Default: trend line
  const grouped: Record<string, number> = {};
  data.forEach((row: MuseumRecord) => {
    if (!row.date) return;
    grouped[row.date] = (grouped[row.date] || 0) + parseFloat(String(row[field] || 0));
  });
  const dates = Object.keys(grouped).sort();

  return {
    type: 'line',
    data: {
      labels: dates.map(d => d.substring(5)),
      datasets: [{
        data: dates.map(d => grouped[d]),
        borderColor: '#3b82f6',
        backgroundColor: 'rgba(59,130,246,0.1)',
        fill: true,
        tension: 0.4
      }]
    },
    options: { plugins: { legend: { display: false } } }
  };
}

function formatDateRange(start: string, end: string): string {
  const s = new Date(start);
  const e = new Date(end);
  const opts: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric', year: 'numeric' };
  return `${s.toLocaleDateString('en-US', opts)} – ${e.toLocaleDateString('en-US', opts)}`;
}

export default Slides;
