import type { APIRoute } from 'astro';
import * as turf from '@turf/turf';
import { pool } from '@/lib/db';
import { validateGeoCampaign } from '@/lib/data/dataValidator';
import { queues } from '@/lib/queue/config';

/**
 * Geospatial Job Launcher
 * Draw a boundary → generate thousands of location-based jobs
 */

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 campaign data
        const campaign = validateGeoCampaign(await request.json());

        // Step 2: Calculate density and generate points
        const densityMap = {
            low: 10,
            medium: 50,
            high: 200,
            insane: 1000
        };

        const pointsPerSquareMile = densityMap[campaign.density];

        // Calculate area of boundary
        const polygon = turf.polygon(campaign.boundary.coordinates);
        const area = turf.area(polygon); // in square meters
        const areaMiles = area * 0.000000386102; // convert to square miles

        const targetCount = campaign.target_count || Math.floor(areaMiles * pointsPerSquareMile);

        console.log(`🌍 [Geo] Generating ${targetCount} points for ${areaMiles.toFixed(2)} sq mi at ${campaign.density} density`);

        // Step 3: Generate random points within boundary using Turf.js
        const points = turf.randomPoint(targetCount, { bbox: turf.bbox(polygon) });

        // Filter to only points actually inside the polygon
        const pointsInside = points.features.filter(point => {
            return turf.booleanPointInPolygon(point, polygon);
        });

        console.log(`🌍 [Geo] ${pointsInside.length} points inside boundary`);

        // Step 4: Insert points into geo_locations table
        const client = await pool.connect();
        let insertedCount = 0;

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

            for (const point of pointsInside) {
                const [lng, lat] = point.geometry.coordinates;

                const insertQuery = `
                    INSERT INTO geo_locations (location, created_at)
                    VALUES (ST_SetSRID(ST_MakePoint($1, $2), 4326), NOW())
                    RETURNING id
                `;

                await client.query(insertQuery, [lng, lat]);
                insertedCount++;
            }

            await client.query('COMMIT');
            console.log(`✅ [Geo] Inserted ${insertedCount} locations`);

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

        // Step 5: Create generation jobs and push to BullMQ
        const jobs = pointsInside.map((point, index) => {
            const [lng, lat] = point.geometry.coordinates;

            return {
                name: `geo-campaign-${campaign.site_id}-${index}`,
                data: {
                    job_type: 'geo_campaign',
                    site_id: campaign.site_id,
                    campaign_id: campaign.campaign_type,
                    target_data: {
                        lat,
                        lng,
                        template_id: campaign.template_id
                    }
                }
            };
        });

        // Use addBulk for efficiency
        const addedJobs = await queues.generation.addBulk(jobs);

        console.log(`📋 [Queue] Added ${addedJobs.length} jobs to generation queue`);

        // Step 6: Return success
        return new Response(JSON.stringify({
            success: true,
            campaign: {
                type: campaign.campaign_type,
                density: campaign.density,
                site_id: campaign.site_id
            },
            area_sq_miles: areaMiles,
            points_generated: pointsInside.length,
            locations_inserted: insertedCount,
            jobs_queued: addedJobs.length,
            queue_ids: addedJobs.slice(0, 10).map(j => j.id),
            timestamp: new Date().toISOString(),
            next_steps: {
                monitor_queue: 'GET /api/god/queue/status',
                view_locations: `SELECT * FROM geo_locations ORDER BY created_at DESC LIMIT 100`
            }
        }), {
            status: 200,
            headers: { 'Content-Type': 'application/json' }
        });

    } catch (error: any) {
        console.error('❌ [Geo] Campaign launch failed:', error.message);

        return new Response(JSON.stringify({
            error: 'Campaign launch failed',
            details: error.message
        }), {
            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/geo/launch-campaign',
        description: 'Generate thousands of location-based content jobs from a map boundary',
        features: [
            'Uses @turf/turf for geospatial sampling',
            'Generates points based on density setting',
            'Inserts locations into database',
            'Pushes jobs to BullMQ with addBulk'
        ],
        density_levels: {
            low: '10 points per square mile',
            medium: '50 points per square mile',
            high: '200 points per square mile',
            insane: '1000 points per square mile'
        },
        usage_example: {
            boundary: {
                type: 'Polygon',
                coordinates: [
                    [
                        [-97.74, 30.27],
                        [-97.74, 30.40],
                        [-97.54, 30.40],
                        [-97.54, 30.27],
                        [-97.74, 30.27]
                    ]
                ]
            },
            campaign_type: 'local_article',
            density: 'medium',
            site_id: 'uuid-here',
            template_id: 'optional-uuid'
        }
    }, null, 2), {
        status: 200,
        headers: { 'Content-Type': 'application/json' }
    });
};
