import { Controller } from '@hotwired/stimulus';

/*
 * Pad de signature manuscrite (canvas). Dessin à la souris ou au doigt (pointer events),
 * bouton « Recommencer » pour effacer. Le fond est blanc et l'export se fait en JPEG :
 * c'est léger et s'affiche correctement dans les PDF (jsPDF / Dompdf), contrairement à un
 * PNG transparent qui peut ressortir sur fond noir selon le moteur de rendu.
 *
 * API publique (lue par scan_controller) :
 *   - isEmpty()   : true tant qu'aucun trait n'a été tracé
 *   - dataUrl()   : data-URI JPEG de la signature (ou null si vide)
 */
export default class extends Controller {
    static targets = ['canvas', 'placeholder', 'clear'];

    connect() {
        this.drawing = false;
        this.dirty = false;
        this.ctx = null;
        // Le canvas peut être dimensionné par CSS (largeur fluide) : on cale sa
        // résolution interne sur la taille affichée pour un trait net, puis on redessine
        // un fond blanc. Différé d'une frame pour que la mise en page CSS soit appliquée.
        requestAnimationFrame(() => this.setup());
        this._onResize = () => this.handleResize();
        window.addEventListener('resize', this._onResize);
    }

    disconnect() {
        window.removeEventListener('resize', this._onResize);
    }

    setup() {
        const canvas = this.canvasTarget;
        const ratio = window.devicePixelRatio || 1;
        const rect = canvas.getBoundingClientRect();
        const w = Math.max(1, Math.round(rect.width));
        const h = Math.max(1, Math.round(rect.height || 180));
        canvas.width = w * ratio;
        canvas.height = h * ratio;
        const ctx = canvas.getContext('2d');
        ctx.scale(ratio, ratio);
        ctx.lineWidth = 2.2;
        ctx.lineJoin = 'round';
        ctx.lineCap = 'round';
        ctx.strokeStyle = '#111827';
        this.ctx = ctx;
        this._cssW = w;
        this._cssH = h;
        this.paintBackground();
    }

    paintBackground() {
        if (!this.ctx) return;
        this.ctx.save();
        this.ctx.fillStyle = '#ffffff';
        this.ctx.fillRect(0, 0, this._cssW, this._cssH);
        this.ctx.restore();
    }

    // Un redimensionnement réinitialise le canvas (le contenu bitmap ne se met pas à
    // l'échelle). On efface : à ce stade l'utilisateur n'a en principe pas encore signé.
    handleResize() {
        if (this.drawing) return;
        this.setup();
        this.dirty = false;
        this.togglePlaceholder(true);
    }

    pos(event) {
        const rect = this.canvasTarget.getBoundingClientRect();
        return { x: event.clientX - rect.left, y: event.clientY - rect.top };
    }

    start(event) {
        event.preventDefault();
        if (!this.ctx) this.setup();
        this.drawing = true;
        const { x, y } = this.pos(event);
        this.ctx.beginPath();
        this.ctx.moveTo(x, y);
        // Un simple clic (point) doit laisser une marque.
        this.ctx.lineTo(x + 0.1, y + 0.1);
        this.ctx.stroke();
        if (!this.dirty) {
            this.dirty = true;
            this.togglePlaceholder(false);
        }
        if (this.canvasTarget.setPointerCapture && event.pointerId !== undefined) {
            try { this.canvasTarget.setPointerCapture(event.pointerId); } catch { /* ignore */ }
        }
    }

    move(event) {
        if (!this.drawing || !this.ctx) return;
        event.preventDefault();
        const { x, y } = this.pos(event);
        this.ctx.lineTo(x, y);
        this.ctx.stroke();
    }

    end(event) {
        if (!this.drawing) return;
        event.preventDefault();
        this.drawing = false;
        this.ctx.closePath();
    }

    clear() {
        if (!this.ctx) this.setup();
        else this.paintBackground();
        this.dirty = false;
        this.togglePlaceholder(true);
    }

    togglePlaceholder(show) {
        if (this.hasPlaceholderTarget) this.placeholderTarget.classList.toggle('hidden', !show);
    }

    isEmpty() {
        return !this.dirty;
    }

    dataUrl() {
        if (this.isEmpty() || !this.canvasTarget) return null;
        try {
            return this.canvasTarget.toDataURL('image/jpeg', 0.85);
        } catch {
            return null;
        }
    }
}
