import SignaturePad from 'signature_pad';
import { h } from '../core/dom';
import { modal } from '../ui/modal';
import { segmented, checkbox } from '../ui/controls';
import { pickFiles } from '../ui/dropzone';
import { readBytes, bufferOf } from '../core/util';
import { getSignatures, saveSignature, deleteSignature, type SavedSignature } from '../core/signatures';

export interface CapturedSignature {
  dataUrl: string;
  w: number;
  h: number;
}

/** Open the signature modal: reuse a saved signature, or draw/type/upload a new one. */
export function captureSignature(): Promise<CapturedSignature | null> {
  return new Promise((resolve) => {
    const m = modal({ title: 'Add your signature', subtitle: 'Reuse a saved one, or make a new one — it stays on your device.', width: 560 });
    let mode: 'draw' | 'type' | 'upload' = 'draw';
    let color = '#12141b';
    let saved: SavedSignature[] = [];
    let saveForReuse = true;

    // ----- saved signatures section -----
    const savedWrap = h('div.sig-saved-wrap');
    const renderSaved = () => {
      savedWrap.replaceChildren();
      if (!saved.length) return;
      savedWrap.append(
        h('div.sig-saved-title', 'Saved signatures'),
        h('div.sig-saved-grid',
          ...saved.map((s) =>
            h('div.sig-saved-card', { title: 'Use this signature' },
              h('img', { src: s.dataUrl, onclick: () => m.close({ dataUrl: s.dataUrl, w: s.w, h: s.h }) }),
              h('button.sig-saved-del', {
                title: 'Delete', onclick: async (e: Event) => { e.stopPropagation(); await deleteSignature(s.id); saved = saved.filter((x) => x.id !== s.id); renderSaved(); },
              }, '×'),
            ),
          ),
        ),
        h('div.sig-saved-sep', h('span', 'or create a new one')),
      );
    };

    // ----- create section -----
    const stage = h('div.sig-stage');
    const canvas = h('canvas.sig-canvas') as HTMLCanvasElement;
    let pad: SignaturePad | null = null;
    let uploaded: { dataUrl: string; w: number; h: number } | null = null;

    const typeInput = h('input.input sig-type-input', { placeholder: 'Type your name', oninput: () => renderTyped() }) as HTMLInputElement;
    const typedCanvas = h('canvas.sig-canvas') as HTMLCanvasElement;
    const typeFonts = ['"Segoe Script","Brush Script MT",cursive', 'Georgia, "Times New Roman", serif', '"Comic Sans MS", cursive'];
    let typeFont = typeFonts[0];

    function setupDraw() {
      const rect = stage.getBoundingClientRect();
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      canvas.width = Math.max(300, rect.width) * dpr;
      canvas.height = 180 * dpr;
      canvas.style.width = '100%';
      canvas.style.height = '180px';
      const ctx = canvas.getContext('2d')!;
      ctx.scale(dpr, dpr);
      pad = new SignaturePad(canvas, { penColor: color, minWidth: 1.1, maxWidth: 2.8, backgroundColor: 'rgba(0,0,0,0)' });
    }

    function renderTyped() {
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      const w = Math.max(300, stage.getBoundingClientRect().width);
      typedCanvas.width = w * dpr;
      typedCanvas.height = 180 * dpr;
      typedCanvas.style.width = '100%';
      typedCanvas.style.height = '180px';
      const ctx = typedCanvas.getContext('2d')!;
      ctx.scale(dpr, dpr);
      ctx.clearRect(0, 0, w, 180);
      ctx.fillStyle = color;
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.font = `52px ${typeFont}`;
      ctx.fillText(typeInput.value || 'Your name', w / 2, 90);
    }

    function showMode() {
      stage.replaceChildren();
      if (mode === 'draw') {
        stage.appendChild(canvas);
        setupDraw();
      } else if (mode === 'type') {
        stage.append(
          typeInput,
          h('div.sig-fontrow', ...typeFonts.map((f) =>
            h('button.sig-font' + (f === typeFont ? ' on' : ''), { style: { fontFamily: f }, onclick: () => { typeFont = f; showMode(); } }, 'Abc'))),
          typedCanvas,
        );
        renderTyped();
      } else {
        const preview = h('div.sig-upload');
        stage.appendChild(preview);
        if (uploaded) preview.appendChild(h('img', { src: uploaded.dataUrl, style: { maxHeight: '150px', maxWidth: '100%' } }));
        else preview.appendChild(h('button.btn btn-ghost', { onclick: doUpload }, 'Choose an image…'));
      }
    }

    async function doUpload() {
      const files = await pickFiles('image/*', false);
      if (!files.length) return;
      const bytes = await readBytes(files[0]);
      const url = URL.createObjectURL(new Blob([bufferOf(bytes)], { type: files[0].type }));
      const img = new Image();
      img.onload = () => { toDataUrl(img); URL.revokeObjectURL(url); showMode(); };
      img.src = url;
    }
    function toDataUrl(img: HTMLImageElement) {
      const c = document.createElement('canvas');
      c.width = img.naturalWidth; c.height = img.naturalHeight;
      c.getContext('2d')!.drawImage(img, 0, 0);
      uploaded = { dataUrl: c.toDataURL('image/png'), w: img.naturalWidth, h: img.naturalHeight };
    }

    m.body.append(
      savedWrap,
      segmented({
        options: [{ value: 'draw', label: 'Draw' }, { value: 'type', label: 'Type' }, { value: 'upload', label: 'Upload' }],
        value: mode,
        onchange: (v) => { mode = v as any; showMode(); },
      }),
      stage,
      h('div.sig-colors',
        ...['#12141b', '#2f6bff', '#e0483d'].map((c) =>
          h('button.swatch' + (c === color ? ' on' : ''), { style: { background: c }, onclick: () => { color = c; showMode(); } }))),
    );

    m.footer.append(
      checkbox('Save for reuse', saveForReuse, (v) => (saveForReuse = v)),
      h('div', { style: { flex: '1' } }),
      h('button.btn btn-soft', { onclick: () => { if (mode === 'draw') pad?.clear(); else if (mode === 'type') { typeInput.value = ''; renderTyped(); } else { uploaded = null; showMode(); } } }, 'Clear'),
      h('button.btn btn-primary', { onclick: commit }, 'Place signature'),
    );

    async function commit() {
      let result: CapturedSignature | null = null;
      if (mode === 'draw' && pad && !pad.isEmpty()) {
        result = { dataUrl: pad.toDataURL('image/png'), w: canvas.width, h: canvas.height };
      } else if (mode === 'type' && typeInput.value.trim()) {
        result = { dataUrl: typedCanvas.toDataURL('image/png'), w: typedCanvas.width, h: typedCanvas.height };
      } else if (mode === 'upload' && uploaded) {
        result = { dataUrl: uploaded.dataUrl, w: uploaded.w, h: uploaded.h };
      }
      if (result && saveForReuse) { try { await saveSignature(result); } catch { /* ignore */ } }
      m.close(result);
    }

    m.onClose((r) => resolve(r ?? null));

    // load saved signatures, then render
    getSignatures().then((list) => { saved = list; renderSaved(); });
    requestAnimationFrame(showMode);
  });
}
