import { useEffect, useRef, useState, useCallback } from 'react';
import './ExecutorAssessmentDetail.css';

const IconClose = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden>
    <path d="M5 5l10 10M15 5L5 15" strokeLinecap="round" />
  </svg>
);
const IconPen = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.7" aria-hidden>
    <path d="M13.5 3.5a2.121 2.121 0 0 1 3 3L6 17H3v-3L13.5 3.5Z" strokeLinejoin="round" />
  </svg>
);
const IconEraser = () => (
  <svg viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.7" aria-hidden>
    <path d="M3 12.5l5.2-5.2a2 2 0 0 1 2.8 0l5.2 5.2a2 2 0 0 1 0 2.8l-1.4 1.4H8.2L3 12.5Z" strokeLinejoin="round" />
    <path d="M8.2 16.7h8.8" strokeLinecap="round" />
  </svg>
);

function parseMarksJson(s) {
  if (s == null || s === '') return [];
  try {
    const arr = JSON.parse(s);
    if (!Array.isArray(arr)) return [];
    return arr.filter((st) => st && Array.isArray(st.points) && st.points.length > 0);
  } catch {
    return [];
  }
}

/**
 * Full-screen canvas to draw on a snap image (frame or already-marked JPEG).
 * Used from the assessment video page and from snap detail / risk form page.
 *
 * - `initialMarksJson`: when set, strokes are restored on the overlay so pen/eraser work on real marks
 *   (requires `snapDataUrl` to be the unmarked frame, not the flattened JPEG).
 * - `exportUnmarkedBase`: when true, `onApply` receives the unmarked frame URL as 3rd arg for caching;
 *   set false when the base image is already flattened and marks cannot be erased.
 */
export default function SnapMarkEditorModal({
  snapDataUrl,
  initialMarksJson,
  exportUnmarkedBase = true,
  violationTime = '00:00',
  onTimeChange,
  onClose,
  onApply,
  primaryButtonLabel = 'Add Observation',
  showViolationTime = true,
  ariaLabel = 'Snap observation',
  headerTitle = 'Snap Observation',
  /** When true, show why older merged JPEGs cannot have prior marks erased (no separate video frame stored). */
  bakedMarksLegacyHint = false
}) {
  const baseCanvasRef = useRef(null);
  const overlayCanvasRef = useRef(null);
  const baseExportUrlRef = useRef(null);
  const [tool, setTool] = useState('pen');
  const [color, setColor] = useState('#dc2626');
  const [size, setSize] = useState(4);
  const [drawing, setDrawing] = useState(false);
  const [marks, setMarks] = useState([]);
  const currentStroke = useRef([]);
  const imgRef = useRef(null);

  useEffect(() => {
    const baseCanvas = baseCanvasRef.current;
    const overlayCanvas = overlayCanvasRef.current;
    if (!baseCanvas || !overlayCanvas || !snapDataUrl) return;
    const baseCtx = baseCanvas.getContext('2d');
    const img = new Image();
    img.onload = () => {
      baseCanvas.width = img.naturalWidth;
      baseCanvas.height = img.naturalHeight;
      overlayCanvas.width = img.naturalWidth;
      overlayCanvas.height = img.naturalHeight;
      baseCtx.clearRect(0, 0, baseCanvas.width, baseCanvas.height);
      baseCtx.drawImage(img, 0, 0);
      imgRef.current = img;
      const overlayCtx = overlayCanvas.getContext('2d');
      overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
      baseExportUrlRef.current = snapDataUrl;
      setMarks(parseMarksJson(initialMarksJson));
    };
    img.src = snapDataUrl;
  }, [snapDataUrl, initialMarksJson]);

  const redraw = useCallback(() => {
    const canvas = overlayCanvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    marks.forEach((stroke) => {
      if (!stroke.points.length) return;
      ctx.save();
      ctx.globalCompositeOperation = stroke.eraser ? 'destination-out' : 'source-over';
      ctx.strokeStyle = stroke.color;
      ctx.lineWidth = stroke.size;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      ctx.beginPath();
      stroke.points.forEach(([x, y], i) => (i === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y)));
      ctx.stroke();
      ctx.restore();
    });
  }, [marks]);

  useEffect(() => {
    redraw();
  }, [redraw]);

  function getPos(e) {
    const canvas = overlayCanvasRef.current;
    const rect = canvas.getBoundingClientRect();
    const scaleX = canvas.width / rect.width;
    const scaleY = canvas.height / rect.height;
    const src = e.touches ? e.touches[0] : e;
    return [(src.clientX - rect.left) * scaleX, (src.clientY - rect.top) * scaleY];
  }

  function onPointerDown(e) {
    e.preventDefault();
    setDrawing(true);
    const pos = getPos(e);
    currentStroke.current = [pos];
    const ctx = overlayCanvasRef.current.getContext('2d');
    ctx.globalCompositeOperation = tool === 'eraser' ? 'destination-out' : 'source-over';
    ctx.strokeStyle = color;
    ctx.lineWidth = tool === 'eraser' ? size * 4 : size;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.beginPath();
    ctx.moveTo(...pos);
  }

  function onPointerMove(e) {
    if (!drawing) return;
    e.preventDefault();
    const pos = getPos(e);
    currentStroke.current.push(pos);
    const ctx = overlayCanvasRef.current.getContext('2d');
    ctx.lineTo(...pos);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(...pos);
  }

  function onPointerUp() {
    if (!drawing) return;
    setDrawing(false);
    const stroke = {
      points: [...currentStroke.current],
      color,
      size: tool === 'eraser' ? size * 4 : size,
      eraser: tool === 'eraser'
    };
    setMarks((prev) => [...prev, stroke]);
    currentStroke.current = [];
  }

  function handleClearMarks() {
    setMarks([]);
  }

  function handleApply() {
    const baseCanvas = baseCanvasRef.current;
    const overlayCanvas = overlayCanvasRef.current;
    if (!baseCanvas || !overlayCanvas) return;
    const out = document.createElement('canvas');
    out.width = baseCanvas.width;
    out.height = baseCanvas.height;
    const outCtx = out.getContext('2d');
    outCtx.drawImage(baseCanvas, 0, 0);
    outCtx.drawImage(overlayCanvas, 0, 0);
    const markedDataUrl = out.toDataURL('image/jpeg', 0.92);
    const baseForPayload = exportUnmarkedBase ? baseExportUrlRef.current : null;
    onApply?.(markedDataUrl, JSON.stringify(marks), baseForPayload);
  }

  return (
    <div className="snap-overlay" role="dialog" aria-modal aria-label={ariaLabel}>
      <div className="snap-modal">
        <div className="snap-modal-header">
          <span className="snap-modal-topic">Topic: {headerTitle}</span>
          <button type="button" className="snap-close-btn" onClick={onClose} aria-label="Close">
            <IconClose />
          </button>
        </div>

        {bakedMarksLegacyHint ? (
          <p className="snap-legacy-baked-hint" role="note">
            This snap was saved as a single JPEG (marks are baked into the pixels). The eraser only removes strokes
            drawn in this session. To remove older marks, go back to the assessment and use <strong>Snap Photo</strong>{' '}
            again so the original video frame is stored.
          </p>
        ) : null}

        <div className="snap-canvas-wrap">
          <div className="snap-canvas-stage">
            <canvas ref={baseCanvasRef} className="snap-canvas snap-canvas--base" />
            <canvas
              ref={overlayCanvasRef}
              className={`snap-canvas snap-canvas--overlay snap-canvas--${tool}`}
              onMouseDown={onPointerDown}
              onMouseMove={onPointerMove}
              onMouseUp={onPointerUp}
              onMouseLeave={onPointerUp}
              onTouchStart={onPointerDown}
              onTouchMove={onPointerMove}
              onTouchEnd={onPointerUp}
            />
          </div>
        </div>

        <div className="snap-tools">
          <div className="snap-tool-group">
            <button
              type="button"
              className={`snap-tool-btn${tool === 'pen' ? ' active' : ''}`}
              onClick={() => setTool('pen')}
              title="Draw"
            >
              <IconPen />
            </button>
            <button
              type="button"
              className={`snap-tool-btn${tool === 'eraser' ? ' active' : ''}`}
              onClick={() => setTool('eraser')}
              title="Eraser"
            >
              <IconEraser />
              <span className="snap-tool-btn-label">Eraser</span>
            </button>
          </div>
          <div className="snap-tool-group">
            <label className="snap-color-wheel" title="Choose custom color">
              <span>Color</span>
              <input
                type="color"
                value={color}
                onChange={(e) => {
                  setTool('pen');
                  setColor(e.target.value);
                }}
                aria-label="Choose custom draw color"
              />
            </label>
          </div>
          <div className="snap-tool-group">
            {['#dc2626', '#737373', '#0a0a0a', '#ffffff'].map((c) => (
              <button
                key={c}
                type="button"
                className={`snap-color-btn${color === c ? ' active' : ''}`}
                style={{ background: c, borderColor: c === color ? '#525252' : 'transparent' }}
                onClick={() => {
                  setTool('pen');
                  setColor(c);
                }}
                title={c}
              />
            ))}
          </div>
          <div className="snap-tool-group">
            <label className="snap-size-label">
              Size
              <input type="range" min="2" max="16" value={size} onChange={(e) => setSize(Number(e.target.value))} />
            </label>
          </div>
          <button type="button" className="snap-tool-btn snap-tool-btn--clear" onClick={handleClearMarks}>
            Clear
          </button>
        </div>

        <div
          className={`snap-modal-footer${showViolationTime && onTimeChange ? '' : ' snap-modal-footer--no-violation-time'}`}
        >
          {showViolationTime && onTimeChange ? (
            <div className="snap-violation-time">
              <label htmlFor="snap-vt-mm">Risk Violation Time</label>
              <div className="snap-time-inputs">
                <input
                  id="snap-vt-mm"
                  type="text"
                  maxLength={2}
                  placeholder="MM"
                  value={violationTime.split(':')[0] || ''}
                  onChange={(e) =>
                    onTimeChange(`${e.target.value.replace(/\D/g, '')}:${violationTime.split(':')[1] || '00'}`)
                  }
                />
                <span>:</span>
                <input
                  type="text"
                  maxLength={2}
                  placeholder="SS"
                  value={violationTime.split(':')[1] || ''}
                  onChange={(e) =>
                    onTimeChange(`${violationTime.split(':')[0] || '00'}:${e.target.value.replace(/\D/g, '')}`)
                  }
                />
              </div>
            </div>
          ) : null}
          <div className="snap-footer-right">
            <button type="button" className="eadp-btn eadp-btn--outline" onClick={onClose}>
              Close
            </button>
            <button type="button" className="eadp-btn eadp-btn--primary" onClick={handleApply}>
              {primaryButtonLabel}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
