import type { APIRoute } from 'astro';
import Papa from 'papaparse';
import { pool } from '@/lib/db';
import { validateIngestionPayload, GenericTargetSchema } from '@/lib/data/dataValidator';

/**
 * Data Ingestion Endpoint
 * Load 10k+ targets from CSV/JSON in seconds
 */

function validateGodToken(request: Request): boolean {
    const token = request.headers.get('X-God-Token') ||
        request.headers.get('Authorization')?.replace('Bearer ', '') ||
        new URL(request.url).searchParams.get('token');

    const godToken = process.env.GOD_MODE_TOKEN || import.meta.env.GOD_MODE_TOKEN;
    if (!godToken) return true;
    return token === godToken;
}

export const POST: APIRoute = async ({ request }) => {
    if (!validateGodToken(request)) {
        return new Response(JSON.stringify({ error: 'Unauthorized' }), {
            status: 401,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    try {
        // Step 1: Validate payload
        const payload = validateIngestionPayload(await request.json());
        let records: Record<string, any>[] = [];

        // Step 2: Parse data (CSV or JSON)
        if (payload.format === 'csv') {
            const parseResult = Papa.parse(payload.data, {
                header: true,
                skipEmptyLines: true,
                dynamicTyping: true,
                transformHeader: (header) => header.trim().toLowerCase().replace(/\s+/g, '_')
            });

            if (parseResult.errors.length > 0) {
                return new Response(JSON.stringify({
                    error: 'CSV parsing failed',
                    details: parseResult.errors.slice(0, 10)
                }), {
                    status: 400,
                    headers: { 'Content-Type': 'application/json' }
                });
            }

            records = parseResult.data as Record<string, any>[];

        } else if (payload.format === 'json') {
            records = JSON.parse(payload.data);
            if (!Array.isArray(records)) {
                records = [records];
            }
        }

        if (records.length === 0) {
            return new Response(JSON.stringify({
                error: 'No records found after parsing'
            }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' }
            });
        }

        // Step 3: Validate each record with Zod
        const validatedRecords = records.map((record, index) => {
            try {
                return GenericTargetSchema.parse(record);
            } catch (error: any) {
                throw new Error(`Record ${index + 1} validation failed: ${error.message}`);
            }
        });

        console.log(`📋 [Ingestion] Parsed ${validatedRecords.length} records for table: ${payload.tableName}`);

        // Step 4: Validate-only mode (dry run)
        if (payload.validateOnly) {
            return new Response(JSON.stringify({
                valid: true,
                recordCount: validatedRecords.length,
                columns: Object.keys(validatedRecords[0]),
                sample: validatedRecords.slice(0, 3),
                message: 'Validation successful - no data inserted (validateOnly=true)'
            }), {
                status: 200,
                headers: { 'Content-Type': 'application/json' }
            });
        }

        // Step 5: Apply column mapping if provided
        const mappedRecords = validatedRecords.map(record => {
            if (!payload.columnMapping) return record;

            const mapped: Record<string, any> = {};
            for (const [sourceCol, targetCol] of Object.entries(payload.columnMapping)) {
                if (record[sourceCol] !== undefined) {
                    mapped[targetCol] = record[sourceCol];
                }
            }
            return Object.keys(mapped).length > 0 ? mapped : record;
        });

        // Step 6: Bulk INSERT in transaction
        const client = await pool.connect();
        let insertedCount = 0;

        try {
            await client.query('BEGIN');

            const columns = Object.keys(mappedRecords[0]);

            // Batch inserts (1000 at a time for performance)
            const batchSize = 1000;
            for (let i = 0; i < mappedRecords.length; i += batchSize) {
                const batch = mappedRecords.slice(i, i + batchSize);

                for (const record of batch) {
                    const values = columns.map(col => record[col]);
                    const placeholders = values.map((_, idx) => `$${idx + 1}`).join(', ');

                    const insertQuery = `
                        INSERT INTO "${payload.tableName}" (${columns.join(', ')}) 
                        VALUES (${placeholders})
                        ON CONFLICT DO NOTHING
                    `;

                    const result = await client.query(insertQuery, values);
                    insertedCount += result.rowCount || 0;
                }
            }

            await client.query('COMMIT');
            console.log(`✅ [Ingestion] Inserted ${insertedCount} records into ${payload.tableName}`);

        } catch (error: any) {
            await client.query('ROLLBACK');
            throw new Error(`Database insertion failed: ${error.message}`);

        } finally {
            client.release();
        }

        // Step 7: Success response
        return new Response(JSON.stringify({
            success: true,
            tableName: payload.tableName,
            recordsProcessed: validatedRecords.length,
            recordsInserted: insertedCount,
            recordsSkipped: validatedRecords.length - insertedCount,
            columns: Object.keys(mappedRecords[0]),
            timestamp: new Date().toISOString(),
            next_steps: {
                query_data: `SELECT * FROM ${payload.tableName} LIMIT 10`,
                push_to_queue: `Use POST /api/god/sql with push_to_queue flag`
            }
        }), {
            status: 200,
            headers: { 'Content-Type': 'application/json' }
        });

    } catch (error: any) {
        console.error('❌ [Ingestion] Error:', error.message);

        return new Response(JSON.stringify({
            error: 'Ingestion failed',
            details: error.message,
            hint: 'Check that table exists and columns match your data'
        }), {
            status: 500,
            headers: { 'Content-Type': 'application/json' }
        });
    }
};

// GET for documentation
export const GET: APIRoute = async ({ request }) => {
    if (!validateGodToken(request)) {
        return new Response(JSON.stringify({ error: 'Unauthorized' }), {
            status: 401,
            headers: { 'Content-Type': 'application/json' }
        });
    }

    return new Response(JSON.stringify({
        endpoint: 'POST /api/god/data/ingest',
        description: 'Bulk load targets from CSV or JSON',
        features: [
            'Parse CSV with papaparse',
            'Validate with Zod schemas',
            'Bulk INSERT in transaction',
            'Column mapping support',
            'Dry-run mode (validateOnly)'
        ],
        usage: {
            csv_example: {
                format: 'csv',
                tableName: 'geo_locations',
                data: 'city_name,state,lat,lng\nAustin,TX,30.2672,-97.7431\nDallas,TX,32.7767,-96.7970',
                validateOnly: false
            },
            json_example: {
                format: 'json',
                tableName: 'sites',
                data: JSON.stringify([
                    { domain: 'example.com', name: 'Example Site' },
                    { domain: 'test.com', name: 'Test Site' }
                ])
            },
            with_mapping: {
                format: 'csv',
                tableName: 'posts',
                data: 'Title,URL,Status\nTest Post,/test,draft',
                columnMapping: {
                    'Title': 'title',
                    'URL': 'slug',
                    'Status': 'status'
                }
            }
        },
        limits: {
            max_records: 100000,
            batch_size: 1000,
            transaction_timeout: '30 seconds'
        }
    }, null, 2), {
        status: 200,
        headers: { 'Content-Type': 'application/json' }
    });
};
