/* ── ASPG Generate Weekly Prompts — Admin Script ────────────────────────── */
( function () {
    'use strict';

    const generateBtn = document.getElementById( 'aspg-weekly-generate' );
    const statusEl    = document.getElementById( 'aspg-weekly-status' );
    const resultsEl   = document.getElementById( 'aspg-weekly-results' );
    const tbody       = document.getElementById( 'aspg-weekly-tbody' );
    const exportCsv   = document.getElementById( 'aspg-export-csv' );
    const exportXlsx  = document.getElementById( 'aspg-export-xlsx' );
    const clearBtn    = document.getElementById( 'aspg-weekly-clear' );

    let currentPrompts = [];

    // ── Generate ─────────────────────────────────────────────────────────────

    generateBtn.addEventListener( 'click', function () {
        generateBtn.disabled = true;
        generateBtn.textContent = '⏳ Generating…';
        resultsEl.hidden = true;
        showStatus( 'loading', 'Picking genres and crafting prompts — this may take a few seconds…' );

        const formData = new FormData();
        formData.append( 'action', 'aspg_generate_weekly' );
        formData.append( 'nonce',  ASPG_WEEKLY.nonce );

        fetch( ASPG_WEEKLY.ajax_url, { method: 'POST', body: formData } )
            .then( function ( r ) {
                if ( ! r.ok ) throw new Error( 'Server error: ' + r.status );
                return r.json();
            } )
            .then( function ( data ) {
                if ( data.success ) {
                    currentPrompts = data.data.prompts;
                    renderTable( currentPrompts );
                    hideStatus();
                    resultsEl.hidden = false;
                } else {
                    const msg = ( data.data && data.data.message ) ? data.data.message : 'An unknown error occurred.';
                    showStatus( 'error', msg );
                }
            } )
            .catch( function ( err ) {
                showStatus( 'error', err.message || 'Network error. Please try again.' );
            } )
            .finally( function () {
                generateBtn.disabled    = false;
                generateBtn.innerHTML   = '&#9733; Generate 3 Random Prompts';
            } );
    } );

    // ── Render table rows ─────────────────────────────────────────────────────

    function renderTable( prompts ) {
        tbody.innerHTML = '';
        prompts.forEach( function ( row, i ) {
            const tr = document.createElement( 'tr' );
            tr.className = i % 2 === 0 ? 'aspg-row-even' : 'aspg-row-odd';
            tr.innerHTML =
                '<td class="aspg-col-genre"><span class="aspg-genre-pill">' + escHtml( row.genre ) + '</span></td>' +
                '<td class="aspg-col-prompt">' + escHtml( row.prompt ) + '</td>';
            tbody.appendChild( tr );
        } );
    }

    // ── CSV export ────────────────────────────────────────────────────────────

    exportCsv.addEventListener( 'click', function () {
        if ( ! currentPrompts.length ) return;

        const rows = [ [ 'Genre', 'Prompt' ] ].concat(
            currentPrompts.map( function ( p ) { return [ p.genre, p.prompt ]; } )
        );

        const csvContent = rows.map( function ( r ) {
            return r.map( function ( cell ) {
                // Wrap in quotes, escape inner quotes
                return '"' + String( cell ).replace( /"/g, '""' ) + '"';
            } ).join( ',' );
        } ).join( '\r\n' );

        downloadFile( 'weekly-prompts.csv', 'text/csv;charset=utf-8;', csvContent );
    } );

    // ── XLSX export ───────────────────────────────────────────────────────────

    exportXlsx.addEventListener( 'click', function () {
        if ( ! currentPrompts.length ) return;

        // Build a minimal XLSX using the Office Open XML format
        const rows = [ [ 'Genre', 'Prompt' ] ].concat(
            currentPrompts.map( function ( p ) { return [ p.genre, p.prompt ]; } )
        );

        const xlsxBlob = buildXlsx( rows );
        const url = URL.createObjectURL( xlsxBlob );
        const a   = document.createElement( 'a' );
        a.href     = url;
        a.download = 'weekly-prompts.xlsx';
        document.body.appendChild( a );
        a.click();
        document.body.removeChild( a );
        setTimeout( function () { URL.revokeObjectURL( url ); }, 1000 );
    } );

    // ── Clear ─────────────────────────────────────────────────────────────────

    clearBtn.addEventListener( 'click', function () {
        currentPrompts  = [];
        tbody.innerHTML = '';
        resultsEl.hidden = true;
        hideStatus();
    } );

    // ── Helpers ───────────────────────────────────────────────────────────────

    function showStatus( type, msg ) {
        statusEl.hidden    = false;
        statusEl.className = 'aspg-weekly-status aspg-status-' + type;
        statusEl.innerHTML = type === 'loading'
            ? '<span class="aspg-status-spinner"></span> ' + escHtml( msg )
            : '<strong>' + ( type === 'error' ? '⚠ Error: ' : '✓ ' ) + '</strong>' + escHtml( msg );
    }

    function hideStatus() {
        statusEl.hidden    = true;
        statusEl.className = 'aspg-weekly-status';
        statusEl.innerHTML = '';
    }

    function escHtml( str ) {
        return String( str )
            .replace( /&/g, '&amp;' )
            .replace( /</g, '&lt;' )
            .replace( />/g, '&gt;' )
            .replace( /"/g, '&quot;' );
    }

    function downloadFile( filename, mimeType, content ) {
        const blob = new Blob( [ content ], { type: mimeType } );
        const url  = URL.createObjectURL( blob );
        const a    = document.createElement( 'a' );
        a.href     = url;
        a.download = filename;
        document.body.appendChild( a );
        a.click();
        document.body.removeChild( a );
        setTimeout( function () { URL.revokeObjectURL( url ); }, 1000 );
    }

    // ── Minimal XLSX builder (no dependencies) ────────────────────────────────

    function buildXlsx( rows ) {
        // Escape XML special characters in cell values
        function xmlEsc( s ) {
            return String( s )
                .replace( /&/g, '&amp;' )
                .replace( /</g, '&lt;' )
                .replace( />/g, '&gt;' )
                .replace( /"/g, '&quot;' )
                .replace( /'/g, '&apos;' );
        }

        // Column letter (A, B, C…)
        function colLetter( n ) {
            let s = '';
            while ( n >= 0 ) {
                s = String.fromCharCode( ( n % 26 ) + 65 ) + s;
                n = Math.floor( n / 26 ) - 1;
            }
            return s;
        }

        // Build sheet XML
        let sheetRows = '';
        rows.forEach( function ( row, ri ) {
            let cells = '';
            row.forEach( function ( cell, ci ) {
                const ref = colLetter( ci ) + ( ri + 1 );
                cells += '<c r="' + ref + '" t="inlineStr"><is><t>' + xmlEsc( cell ) + '</t></is></c>';
            } );
            sheetRows += '<row r="' + ( ri + 1 ) + '">' + cells + '</row>';
        } );

        const sheetXml =
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
            '<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">' +
            '<sheetData>' + sheetRows + '</sheetData>' +
            '</worksheet>';

        const workbookXml =
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
            '<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" ' +
            'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">' +
            '<sheets><sheet name="Weekly Prompts" sheetId="1" r:id="rId1"/></sheets>' +
            '</workbook>';

        const workbookRels =
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
            '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
            '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>' +
            '</Relationships>';

        const contentTypes =
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
            '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">' +
            '<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>' +
            '<Default Extension="xml" ContentType="application/xml"/>' +
            '<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>' +
            '<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>' +
            '</Types>';

        const rootRels =
            '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
            '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">' +
            '<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>' +
            '</Relationships>';

        // Pack into a ZIP (XLSX is a ZIP archive)
        return zipFiles( [
            { name: '[Content_Types].xml',          data: contentTypes   },
            { name: '_rels/.rels',                  data: rootRels       },
            { name: 'xl/workbook.xml',              data: workbookXml    },
            { name: 'xl/_rels/workbook.xml.rels',   data: workbookRels   },
            { name: 'xl/worksheets/sheet1.xml',     data: sheetXml       },
        ] );
    }

    // Minimal ZIP builder (no compression — stored)
    function zipFiles( files ) {
        const enc      = new TextEncoder();
        const parts    = [];
        const central  = [];
        let   offset   = 0;

        files.forEach( function ( file ) {
            const nameBytes = enc.encode( file.name );
            const dataBytes = enc.encode( file.data );
            const crc       = crc32( dataBytes );
            const now       = dosDateTime();

            // Local file header
            const local = new Uint8Array( 30 + nameBytes.length );
            const lv    = new DataView( local.buffer );
            lv.setUint32( 0,  0x04034b50, true ); // signature
            lv.setUint16( 4,  20,         true ); // version needed
            lv.setUint16( 6,  0,          true ); // flags
            lv.setUint16( 8,  0,          true ); // compression: stored
            lv.setUint16( 10, now.time,   true );
            lv.setUint16( 12, now.date,   true );
            lv.setUint32( 14, crc,        true );
            lv.setUint32( 18, dataBytes.length, true );
            lv.setUint32( 22, dataBytes.length, true );
            lv.setUint16( 26, nameBytes.length, true );
            lv.setUint16( 28, 0,          true ); // extra length
            local.set( nameBytes, 30 );

            parts.push( local, dataBytes );

            // Central directory entry
            const cent = new Uint8Array( 46 + nameBytes.length );
            const cv   = new DataView( cent.buffer );
            cv.setUint32( 0,  0x02014b50, true );
            cv.setUint16( 4,  20,         true );
            cv.setUint16( 6,  20,         true );
            cv.setUint16( 8,  0,          true );
            cv.setUint16( 10, 0,          true );
            cv.setUint16( 12, now.time,   true );
            cv.setUint16( 14, now.date,   true );
            cv.setUint32( 16, crc,        true );
            cv.setUint32( 20, dataBytes.length, true );
            cv.setUint32( 24, dataBytes.length, true );
            cv.setUint16( 28, nameBytes.length, true );
            cv.setUint16( 30, 0, true ); // extra
            cv.setUint16( 32, 0, true ); // comment
            cv.setUint16( 34, 0, true ); // disk start
            cv.setUint16( 36, 0, true ); // internal attr
            cv.setUint32( 38, 0, true ); // external attr
            cv.setUint32( 42, offset, true );
            cent.set( nameBytes, 46 );
            central.push( cent );

            offset += local.length + dataBytes.length;
        } );

        const centralBytes = concat( central );

        // End of central directory
        const eocd = new Uint8Array( 22 );
        const ev   = new DataView( eocd.buffer );
        ev.setUint32( 0,  0x06054b50,         true );
        ev.setUint16( 4,  0,                  true );
        ev.setUint16( 6,  0,                  true );
        ev.setUint16( 8,  files.length,       true );
        ev.setUint16( 10, files.length,       true );
        ev.setUint32( 12, centralBytes.length, true );
        ev.setUint32( 16, offset,             true );
        ev.setUint16( 20, 0,                  true );

        const all = concat( parts.concat( [ centralBytes, eocd ] ) );
        return new Blob( [ all ], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' } );
    }

    function concat( arrays ) {
        const total  = arrays.reduce( function ( s, a ) { return s + a.length; }, 0 );
        const result = new Uint8Array( total );
        let   pos    = 0;
        arrays.forEach( function ( a ) { result.set( a, pos ); pos += a.length; } );
        return result;
    }

    function dosDateTime() {
        const d    = new Date();
        const date = ( ( d.getFullYear() - 1980 ) << 9 ) | ( ( d.getMonth() + 1 ) << 5 ) | d.getDate();
        const time = ( d.getHours() << 11 ) | ( d.getMinutes() << 5 ) | ( d.getSeconds() >> 1 );
        return { date: date, time: time };
    }

    function crc32( data ) {
        let crc = 0xFFFFFFFF;
        for ( let i = 0; i < data.length; i++ ) {
            crc ^= data[ i ];
            for ( let j = 0; j < 8; j++ ) {
                crc = ( crc & 1 ) ? ( 0xEDB88320 ^ ( crc >>> 1 ) ) : ( crc >>> 1 );
            }
        }
        return ( crc ^ 0xFFFFFFFF ) >>> 0;
    }

} )();
