import JsBarcode from 'jsbarcode';
import { QRCodeSVG } from 'qrcode.react';
import { useEffect, useRef } from 'react';

export const BARCODE_TYPES = [
    { value: 'CODE128', label: 'CODE 128 (default)' },
    { value: 'EAN13', label: 'EAN-13 (13 digits)' },
    { value: 'EAN8', label: 'EAN-8 (8 digits)' },
    { value: 'UPCA', label: 'UPC-A (12 digits)' },
    { value: 'CODE39', label: 'CODE 39' },
    { value: 'QR', label: 'QR Code' },
] as const;

export type BarcodeType = (typeof BARCODE_TYPES)[number]['value'];

/** Generate a random barcode value matching the selected type's format. */
export function generateBarcodeValue(type: BarcodeType): string {
    const rand = (n: number) => Math.floor(Math.random() * n);

    switch (type) {
        case 'EAN13': {
            const digits = Array.from({ length: 12 }, () => rand(10)).join('');
            return digits + calcEanCheckDigit(digits);
        }
        case 'EAN8': {
            const digits = Array.from({ length: 7 }, () => rand(10)).join('');
            return digits + calcEanCheckDigit(digits);
        }
        case 'UPCA': {
            const digits = Array.from({ length: 11 }, () => rand(10)).join('');
            return digits + calcUpcCheckDigit(digits);
        }
        case 'CODE39':
            return 'PROD' + String(Date.now()).slice(-6);
        case 'QR':
            return 'PRD-' + Math.random().toString(36).slice(2, 10).toUpperCase();
        case 'CODE128':
        default:
            return 'PRD' + String(Date.now()).slice(-9);
    }
}

function calcEanCheckDigit(digits: string): string {
    let sum = 0;
    for (let i = 0; i < digits.length; i++) {
        sum += parseInt(digits[i]) * (i % 2 === 0 ? 1 : 3);
    }
    return String((10 - (sum % 10)) % 10);
}

function calcUpcCheckDigit(digits: string): string {
    let sum = 0;
    for (let i = 0; i < digits.length; i++) {
        sum += parseInt(digits[i]) * (i % 2 === 0 ? 3 : 1);
    }
    return String((10 - (sum % 10)) % 10);
}

interface BarcodeRendererProps {
    value: string;
    type: BarcodeType;
    height?: number;
    width?: number;
    showText?: boolean;
}

export function BarcodeRenderer({ value, type, height = 60, width = 2, showText = true }: BarcodeRendererProps) {
    const svgRef = useRef<SVGSVGElement>(null);

    useEffect(() => {
        if (!value || type === 'QR') return;
        if (!svgRef.current) return;
        try {
            JsBarcode(svgRef.current, value, {
                format: type,
                height,
                width,
                displayValue: showText,
                fontSize: 11,
                margin: 4,
            });
        } catch {
            // invalid value for the selected format — leave blank
        }
    }, [value, type, height, width, showText]);

    if (!value) return <div className="text-xs italic text-gray-400">Enter a barcode value</div>;

    if (type === 'QR') {
        return <QRCodeSVG value={value} size={Math.min(height * 2, 120)} level="M" marginSize={2} />;
    }

    return <svg ref={svgRef} />;
}

/** Opens a browser print dialog with just the barcode for the given product. */
export function printBarcode(productName: string, value: string, type: BarcodeType) {
    if (!value) return;

    const win = window.open('', '_blank', 'width=420,height=320');
    if (!win) return;

    const style = `<style>
        body{margin:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
             min-height:100vh;font-family:sans-serif;background:#fff}
        svg{max-width:320px}
        p{margin:6px 0 0;font-size:12px;text-align:center;color:#333}
        small{font-size:10px;color:#777}
    </style>`;

    if (type === 'QR') {
        // Build a QR SVG inline via qrcode.react's canvas approach
        const canvas = document.createElement('canvas');
        canvas.width = 200;
        canvas.height = 200;
        const ctx = canvas.getContext('2d');
        if (!ctx) { win.close(); return; }

        // Use the existing DOM QRCodeSVG — grab the first one on the page that matches
        const existingSvg = document.querySelector<SVGSVGElement>('svg[data-qr-value]');
        if (existingSvg && existingSvg.getAttribute('data-qr-value') === value) {
            const svgHtml = new XMLSerializer().serializeToString(existingSvg);
            win.document.write(`<!DOCTYPE html><html><head><title>QR – ${productName}</title>${style}</head><body>
                ${svgHtml}
                <p>${productName}</p><small>${value}</small>
                <script>window.onload=()=>{window.print();window.close();}<\/script>
            </body></html>`);
            win.document.close();
            return;
        }

        // Fallback: embed a data-URI QR via an offscreen SVG serialised to img
        win.document.write(`<!DOCTYPE html><html><head><title>QR – ${productName}</title>${style}</head><body>
            <img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(value)}" width="200" height="200" />
            <p>${productName}</p><small>${value}</small>
            <script>window.onload=()=>{window.print();window.close();}<\/script>
        </body></html>`);
        win.document.close();
        return;
    }

    // Linear barcodes — render via JsBarcode into a detached SVG
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    try {
        JsBarcode(svg, value, {
            format: type,
            height: 80,
            width: 2,
            displayValue: true,
            fontSize: 12,
            margin: 8,
        });
    } catch {
        win.close();
        return;
    }

    const svgHtml = new XMLSerializer().serializeToString(svg);
    win.document.write(`<!DOCTYPE html><html><head><title>Barcode – ${productName}</title>${style}</head><body>
        ${svgHtml}
        <p>${productName}</p>
        <script>window.onload=()=>{window.print();window.close();}<\/script>
    </body></html>`);
    win.document.close();
}
