/**
 * ExportView (View 3) — format selection, validation, and download.
 *
 * Receives canvas state from App.tsx (lifted in T02) and uses the export
 * service (T03) to compose SVG, validate, call the engine API, and trigger
 * downloads.
 */

import { useCallback, useEffect, useMemo, useState } from 'react';
import type { ArtboardConfig, ArtboardUnit, CanvasObject } from '../types/canvas';
import {
  composeCanvasSVG,
  validateForExport,
  triggerDownload,
  type ValidationResult,
} from '../utils/exportService';
import { exportAsDxf } from '../api/engine';
import styles from './ExportView.module.css';

// -- Types --------------------------------------------------------------------

export type ExportFormat = 'dxf' | 'svg' | 'png';

export interface ExportViewProps {
  objects: CanvasObject[];
  artboard: ArtboardConfig | null;
  pngDataUrl: string | null;
  onBack: () => void;
}

interface FormatOption {
  id: ExportFormat;
  name: string;
  description: string;
}

const FORMAT_OPTIONS: FormatOption[] = [
  {
    id: 'dxf',
    name: 'DXF',
    description: 'AutoCAD / LightBurn — vector paths with real-world scale',
  },
  {
    id: 'svg',
    name: 'SVG',
    description: 'Scalable vector — Inkscape, Illustrator, web',
  },
  {
    id: 'png',
    name: 'PNG',
    description: 'Raster image — print preview, sharing',
  },
];

// Scale factors: canvas uses 96 PPI internally
const SCALE_FACTORS: Record<ArtboardUnit, number> = {
  inches: 1 / 96,
  mm: 25.4 / 96,
};

// -- Component ----------------------------------------------------------------

export default function ExportView({
  objects,
  artboard,
  pngDataUrl,
  onBack,
}: ExportViewProps) {
  const [selectedFormat, setSelectedFormat] = useState<ExportFormat>('dxf');
  const [selectedUnit, setSelectedUnit] = useState<ArtboardUnit>(
    artboard?.unit ?? 'inches',
  );
  const [exporting, setExporting] = useState(false);
  const [exportError, setExportError] = useState<string | null>(null);

  // Run validation on mount and when objects/artboard change
  const validation: ValidationResult = useMemo(
    () => validateForExport(objects, artboard),
    [objects, artboard],
  );

  const hasBlockingErrors = validation.issues.some(
    (i) => i.severity === 'error',
  );

  // Reset unit when artboard changes
  useEffect(() => {
    if (artboard) {
      setSelectedUnit(artboard.unit);
    }
  }, [artboard]);

  // Whether unit selector is relevant for the selected format
  const showUnitSelector = selectedFormat === 'dxf' || selectedFormat === 'svg';

  // -- Export handlers --------------------------------------------------------

  const handleExport = useCallback(async () => {
    if (!artboard && selectedFormat !== 'png') return;
    setExporting(true);
    setExportError(null);

    try {
      switch (selectedFormat) {
        case 'dxf': {
          const svgString = composeCanvasSVG(objects, artboard!);
          const scaleFactor = SCALE_FACTORS[selectedUnit];
          const dxfBlob = await exportAsDxf(
            svgString,
            selectedUnit,
            scaleFactor,
          );
          triggerDownload(dxfBlob, 'export.dxf');
          break;
        }

        case 'svg': {
          const svgString = composeCanvasSVG(objects, artboard!);
          const svgBlob = new Blob([svgString], { type: 'image/svg+xml' });
          triggerDownload(svgBlob, 'export.svg');
          break;
        }

        case 'png': {
          if (!pngDataUrl) {
            setExportError('No PNG preview available. Go back and try again.');
            break;
          }
          // Convert data URL to Blob
          const response = await fetch(pngDataUrl);
          const pngBlob = await response.blob();
          triggerDownload(pngBlob, 'export.png');
          break;
        }
      }
    } catch (err) {
      const message =
        err instanceof Error ? err.message : 'Export failed unexpectedly.';
      setExportError(message);
      console.error('[ExportView] export error:', err);
    } finally {
      setExporting(false);
    }
  }, [selectedFormat, selectedUnit, objects, artboard, pngDataUrl]);

  // Disable download when there are blocking errors (except PNG which
  // doesn't need artboard/vector validation)
  const downloadDisabled =
    exporting ||
    (selectedFormat !== 'png' && hasBlockingErrors) ||
    (selectedFormat === 'png' && !pngDataUrl);

  // -- Render -----------------------------------------------------------------

  return (
    <div className={styles.container} data-testid="export-view">
      {/* Header */}
      <header className={styles.header}>
        <h1 className={styles.headerTitle}>Export</h1>
        <button
          type="button"
          className={styles.backBtn}
          onClick={onBack}
          data-testid="export-back-btn"
        >
          ← Back to Design
        </button>
      </header>

      <div className={styles.body}>
        {/* Main panel — preview */}
        <div className={styles.mainPanel}>
          <div className={styles.previewSection}>
            <span className={styles.previewLabel}>Preview</span>
            {pngDataUrl ? (
              <img
                className={styles.previewImage}
                src={pngDataUrl}
                alt="Design preview"
                data-testid="export-preview"
              />
            ) : (
              <div className={styles.previewPlaceholder}>
                No preview available
              </div>
            )}
          </div>
        </div>

        {/* Side panel — format, units, validation, download */}
        <aside className={styles.sidePanel}>
          {/* Format selector */}
          <div>
            <p className={styles.sectionLabel}>Format</p>
            <div className={styles.formatGrid} data-testid="format-selector">
              {FORMAT_OPTIONS.map((fmt) => (
                <button
                  key={fmt.id}
                  type="button"
                  className={`${styles.formatCard}${
                    selectedFormat === fmt.id
                      ? ` ${styles.formatCardSelected}`
                      : ''
                  }`}
                  onClick={() => {
                    setSelectedFormat(fmt.id);
                    setExportError(null);
                  }}
                  data-testid={`format-${fmt.id}`}
                >
                  <span className={styles.formatName}>{fmt.name}</span>
                  <span className={styles.formatDesc}>{fmt.description}</span>
                </button>
              ))}
            </div>
          </div>

          {/* Unit selector (DXF/SVG only) */}
          {showUnitSelector && (
            <div>
              <p className={styles.sectionLabel}>Units</p>
              <div
                className={styles.unitSelector}
                data-testid="unit-selector"
              >
                <label className={styles.unitLabel}>
                  <input
                    type="radio"
                    name="export-unit"
                    value="inches"
                    checked={selectedUnit === 'inches'}
                    onChange={() => setSelectedUnit('inches')}
                  />
                  Inches
                </label>
                <label className={styles.unitLabel}>
                  <input
                    type="radio"
                    name="export-unit"
                    value="mm"
                    checked={selectedUnit === 'mm'}
                    onChange={() => setSelectedUnit('mm')}
                  />
                  Millimeters
                </label>
              </div>
            </div>
          )}

          {/* Validation panel */}
          <div>
            <p className={styles.sectionLabel}>Validation</p>
            <div
              className={styles.validationPanel}
              data-testid="validation-panel"
            >
              {validation.issues.length === 0 ? (
                <p className={styles.validationOk}>✓ Ready to export</p>
              ) : (
                validation.issues.map((issue, i) => (
                  <div
                    key={`${issue.objectId ?? 'global'}-${i}`}
                    className={`${styles.validationItem} ${
                      issue.severity === 'error'
                        ? styles.validationError
                        : styles.validationWarning
                    }`}
                    data-testid={`validation-${issue.severity}`}
                  >
                    <span className={styles.validationIcon}>
                      {issue.severity === 'error' ? '✕' : '⚠'}
                    </span>
                    <span>{issue.message}</span>
                  </div>
                ))
              )}
            </div>
          </div>

          {/* Export error */}
          {exportError && (
            <div className={styles.exportError} data-testid="export-error">
              {exportError}
            </div>
          )}

          {/* Download button */}
          <button
            type="button"
            className={`${styles.downloadBtn}${
              exporting ? ` ${styles.downloadBtnExporting}` : ''
            }`}
            disabled={downloadDisabled}
            onClick={handleExport}
            data-testid="download-btn"
          >
            {exporting
              ? 'Exporting…'
              : `Download ${selectedFormat.toUpperCase()}`}
          </button>
        </aside>
      </div>
    </div>
  );
}
