import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { Modal } from '../../ui/Modal';
import { useEditor } from '../context/EditorContext';
import {
  exportKonvaStageToDataUrl,
  exportThreeCanvasToDataUrl,
  downloadDataUrl,
  downloadBlob,
  createRoomPdf,
  sanitizeFilename,
} from './exportUtils';
import { exportRoomToJson } from './roomFormat';
import { wallDirectionLabel } from '../utils/projectionMapping';
import type Konva from 'konva';
import styles from './export-dialog.module.css';

export type ExportFormat = 'png' | 'pdf' | 'json';
export type ExportScope = 'current-view' | 'room';

interface ExportDialogProps {
  readonly open: boolean;
  readonly onClose: () => void;
  readonly mainStageRef: React.RefObject<Konva.Stage | null>;
  readonly projectionStageRefs: React.RefObject<Map<string, Konva.Stage>>;
  readonly threeCanvasRef: React.RefObject<HTMLCanvasElement | null>;
  readonly is3DView: boolean;
  readonly viewMode?: '2d' | '3d' | 'projections';
}

export function ExportDialog({
  open,
  onClose,
  mainStageRef,
  projectionStageRefs,
  threeCanvasRef,
  is3DView,
  viewMode = '2d',
}: ExportDialogProps) {
  const { t } = useTranslation();
  const { state } = useEditor();
  const { room, walls } = state;

  const [format, setFormat] = useState<ExportFormat>('png');
  const [scope, setScope] = useState<ExportScope>('current-view');
  const [includeGrid, setIncludeGrid] = useState(false);
  const [pixelRatio, setPixelRatio] = useState(2);
  const [isExporting, setIsExporting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const handleExport = useCallback(async () => {
    setIsExporting(true);
    setError(null);

    try {
      const baseName = sanitizeFilename(room.name || 'room');

      if (format === 'png') {
        if (scope === 'current-view') {
          // Export the currently visible view
          if (viewMode === '3d') {
            let canvas = threeCanvasRef.current;
            if (!canvas) {
              canvas = document.querySelector('canvas[data-engine]') as HTMLCanvasElement | null;
            }
            if (!canvas) {
              setError(t('export.error.3dNotAvailable'));
              return;
            }
            const dataUrl = exportThreeCanvasToDataUrl(canvas);
            downloadDataUrl(dataUrl, `${baseName}_3d.png`);
          } else if (viewMode === 'projections') {
            const projMap = projectionStageRefs.current;
            if (projMap && projMap.size > 0) {
              for (const wall of walls) {
                const projStage = projMap.get(wall.id);
                if (projStage && projStage.width() > 0) {
                  const label = wallDirectionLabel(wall);
                  const safeName = sanitizeFilename(label);
                  const dataUrl = exportKonvaStageToDataUrl(projStage, { pixelRatio });
                  downloadDataUrl(dataUrl, `${baseName}_wall_${safeName}.png`);
                }
              }
            } else {
              setError(t('export.error.2dNotAvailable'));
            }
          } else {
            const stage = mainStageRef.current;
            if (!stage || stage.width() === 0) {
              setError(t('export.error.2dNotAvailable'));
              return;
            }
            const dataUrl = exportKonvaStageToDataUrl(stage, { pixelRatio, includeGrid });
            downloadDataUrl(dataUrl, `${baseName}_2d.png`);
          }
        } else {
          // Export all views for the room (2D + projections)
          const stage = mainStageRef.current;
          if (stage) {
            const dataUrl = exportKonvaStageToDataUrl(stage, { pixelRatio, includeGrid });
            downloadDataUrl(dataUrl, `${baseName}_2d.png`);
          }

          // Export projection views
          const projMap = projectionStageRefs.current;
          if (projMap) {
            for (const wall of walls) {
              const projStage = projMap.get(wall.id);
              if (projStage) {
                const label = wallDirectionLabel(wall);
                const safeName = sanitizeFilename(label);
                const dataUrl = exportKonvaStageToDataUrl(projStage, { pixelRatio });
                downloadDataUrl(dataUrl, `${baseName}_wall_${safeName}.png`);
              }
            }
          }
        }
      } else if (format === 'json') {
        // JSON export
        const jsonStr = exportRoomToJson(state);
        const blob = new Blob([jsonStr], { type: 'application/json' });
        downloadBlob(blob, `${baseName}.json`);
      } else {
        // PDF export
        // Capture 2D view — temporarily restore size if hidden
        let topDownDataUrl: string | null = null;
        const stage = mainStageRef.current;
        if (stage) {
          const wasHidden = stage.width() === 0;
          if (wasHidden) {
            // Temporarily make the stage visible for capture
            const container = stage.container();
            const parent = container?.parentElement;
            const origStyle = parent?.getAttribute('style') ?? '';
            if (parent) {
              parent.setAttribute('style', 'position:absolute;width:1200px;height:900px;overflow:hidden;pointer-events:none;opacity:0;');
            }
            stage.width(1200);
            stage.height(900);
            stage.batchDraw();
          }
          if (stage.width() > 0 && stage.height() > 0) {
            topDownDataUrl = exportKonvaStageToDataUrl(stage, { pixelRatio, includeGrid });
          }
          if (wasHidden) {
            // Restore hidden state
            const container = stage.container();
            const parent = container?.parentElement;
            if (parent) {
              parent.setAttribute('style', 'position:absolute;width:0;height:0;overflow:hidden;pointer-events:none;');
            }
            stage.width(0);
            stage.height(0);
          }
        }

        // Capture projection views — they may not be mounted if not in projection mode
        const projectionDataUrls: { label: string; dataUrl: string }[] = [];
        const projMap = projectionStageRefs.current;
        if (projMap) {
          for (const wall of walls) {
            const projStage = projMap.get(wall.id);
            if (projStage && projStage.width() > 0 && projStage.height() > 0) {
              const label = wallDirectionLabel(wall);
              const dataUrl = exportKonvaStageToDataUrl(projStage, { pixelRatio });
              projectionDataUrls.push({ label, dataUrl });
            }
          }
        }

        let view3dDataUrl: string | null = null;
        // Try the ref first, then fall back to querying the DOM
        let canvas3d = threeCanvasRef.current;
        if (!canvas3d) {
          canvas3d = document.querySelector('canvas[data-engine]') as HTMLCanvasElement | null;
        }
        if (canvas3d && canvas3d.width > 0 && canvas3d.height > 0) {
          view3dDataUrl = exportThreeCanvasToDataUrl(canvas3d);
        }

        const pdf = await createRoomPdf(room.name, topDownDataUrl, projectionDataUrls, view3dDataUrl);
        const blob = pdf.output('blob');
        downloadBlob(blob, `${baseName}.pdf`);
      }

      onClose();
    } catch (err: unknown) {
      const message = err instanceof Error ? err.message : t('export.error.failed');
      setError(message);
    } finally {
      setIsExporting(false);
    }
  }, [format, scope, includeGrid, pixelRatio, is3DView, state, room, walls, mainStageRef, projectionStageRefs, threeCanvasRef, onClose, t]);

  const footer = (
    <div className={styles.footerButtons}>
      <button className={styles.cancelBtn} onClick={onClose} type="button">
        {t('common.cancel')}
      </button>
      <button
        className={styles.exportBtn}
        onClick={handleExport}
        disabled={isExporting}
        type="button"
      >
        {isExporting ? t('export.exporting') : t('export.exportBtn')}
      </button>
    </div>
  );

  return (
    <Modal open={open} onClose={onClose} title={t('export.title')} footer={footer}>
      <div className={styles.content}>
        {/* Format */}
        <div className={styles.fieldGroup}>
          <span className={styles.fieldLabel}>{t('export.format')}</span>
          <div className={styles.radioGroup}>
            <label className={styles.radioLabel}>
              <input
                type="radio"
                name="format"
                value="png"
                checked={format === 'png'}
                onChange={() => setFormat('png')}
              />
              {t('export.png')}
            </label>
            <label className={styles.radioLabel}>
              <input
                type="radio"
                name="format"
                value="pdf"
                checked={format === 'pdf'}
                onChange={() => setFormat('pdf')}
              />
              {t('export.pdf')}
            </label>
            <label className={styles.radioLabel}>
              <input
                type="radio"
                name="format"
                value="json"
                checked={format === 'json'}
                onChange={() => setFormat('json')}
              />
              {t('export.json')}
            </label>
          </div>
        </div>

        {/* Scope (only for PNG) */}
        {format === 'png' && (
          <div className={styles.fieldGroup}>
            <span className={styles.fieldLabel}>{t('export.scope')}</span>
            <div className={styles.radioGroup}>
              <label className={styles.radioLabel}>
                <input
                  type="radio"
                  name="scope"
                  value="current-view"
                  checked={scope === 'current-view'}
                  onChange={() => setScope('current-view')}
                />
                {t('export.currentView')}
              </label>
              <label className={styles.radioLabel}>
                <input
                  type="radio"
                  name="scope"
                  value="room"
                  checked={scope === 'room'}
                  onChange={() => setScope('room')}
                />
                {t('export.allRoomViews')}
              </label>
            </div>
          </div>
        )}

        {/* Options */}
        <div className={styles.fieldGroup}>
          <span className={styles.fieldLabel}>{t('export.options')}</span>
          {!is3DView && (
            <label className={styles.checkboxLabel}>
              <input
                type="checkbox"
                checked={includeGrid}
                onChange={(e) => setIncludeGrid(e.target.checked)}
              />
              {t('export.includeGrid')}
            </label>
          )}
          <label className={styles.checkboxLabel}>
            {t('export.scaleFactor')}
            <input
              type="number"
              className={styles.scaleInput}
              min={1}
              max={4}
              step={1}
              value={pixelRatio}
              onChange={(e) => setPixelRatio(Number(e.target.value))}
            />
            x
          </label>
        </div>

        {error && <div className={styles.errorMessage}>{error}</div>}
        {isExporting && <div className={styles.statusMessage}>{t('export.generating')}</div>}
      </div>
    </Modal>
  );
}
