import { getSubsiteByHost } from '../../utils/subsites.ts';
import {
    checkRateLimit,
    recordRequest as recordRateLimitRequest,
    getCookieId,
    generateNonce,
    createNonceCookie,
    getClientIp,
} from '../../utils/rateLimit.ts';
import { validateCsrfToken, generateCsrfToken } from '../../utils/csrf.ts';
import type { APIContext } from 'astro';

interface SubmitRequestBody {
    csrfToken?: string;
    title?: string;
    year?: string;
    type?: string;
    // requester?: string;
    [key: string]: unknown;
}

interface TMDBResult {
    id: number;
    media_type: string;
    title?: string;
    name?: string;
    overview?: string;
    poster_path?: string;
}

interface TMDBSearchResponse {
    results: TMDBResult[];
}

interface ExtendedRequest extends Request {
    bodyData?: SubmitRequestBody;
}

export async function POST({ request }: APIContext): Promise<Response> {
    const host = request.headers.get('host');
    const subsite = getSubsiteByHost(host ?? undefined);
    if (!subsite || subsite.short !== 'req') {
        return new Response('Not found', { status: 404 });
    }

    let cookieId = getCookieId(request);
    const hadCookie = !!cookieId;
    if (!cookieId) {
        cookieId = generateNonce();
    }

    // Validate CSRF token before rate limiting (to avoid consuming rate limit on invalid requests)
    let csrfToken;
    try {
        const body = await request.json() as SubmitRequestBody;
        csrfToken = body.csrfToken;
        
        if (!validateCsrfToken(csrfToken, cookieId)) {
            const response = new Response(JSON.stringify({ 
                error: 'Invalid or expired security token. Please refresh the page and try again.' 
            }), {
                status: 403,
                headers: { 'Content-Type': 'application/json' },
            });
            if (!hadCookie) {
                response.headers.set('Set-Cookie', createNonceCookie(cookieId));
            }
            console.log(`[submit] CSRF validation failed: cookieId=${cookieId}`);
            return response;
        }
        
        // Store parsed body for later use
        (request as ExtendedRequest).bodyData = body;
    } catch (error) {
        const response = new Response(JSON.stringify({ 
            error: 'Invalid request format' 
        }), {
            status: 400,
            headers: { 'Content-Type': 'application/json' },
        });
        if (!hadCookie) {
            response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        }
        return response;
    }

    // Rate limit check (1 request per 15 seconds, flood protection at 10/30s)
    const rateCheck = checkRateLimit(request, {
        limit: 1,
        windowMs: 15_000,
        burstLimit: 10,
        burstWindowMs: 30_000,
    });

    if (!rateCheck.allowed) {
        const errorMsg = rateCheck.isFlooding
            ? { error: 'Too many requests - please slow down' }
            : { error: 'Rate limit exceeded. Please wait before submitting again.' };
        const response = new Response(JSON.stringify(errorMsg), {
            status: 429,
            headers: {
                'Content-Type': 'application/json',
                'Retry-After': '15',
            },
        });
        if (!hadCookie) {
            response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        }
        console.log(`[submit] rate limited: ip=${rateCheck.ip} flooding=${rateCheck.isFlooding}`);
        return response;
    }

    const DISCORD_WEBHOOK_URL = import.meta.env.BUDO_REQ_DISCORD_WEBHOOK_URL;

    if (!DISCORD_WEBHOOK_URL) {
        console.error('DISCORD_WEBHOOK_URL not set');
        const response = new Response(JSON.stringify({ error: 'Webhook not configured' }), {
            status: 500,
            headers: { 'Content-Type': 'application/json' },
        });
        if (!hadCookie) {
            response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        }
        return response;
    }

    try {
        // Use pre-parsed body data
        const extendedRequest = request as ExtendedRequest;
        const { title, year, type } = extendedRequest.bodyData || {};

        // Input validation
        if (!title || typeof title !== 'string' || !title.trim()) {
            const response = new Response(JSON.stringify({ error: 'Title is required and must be a non-empty string' }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' },
            });
            if (!hadCookie) {
                response.headers.set('Set-Cookie', createNonceCookie(cookieId));
            }
            return response;
        }

        if (title.length > 200) {
            const response = new Response(JSON.stringify({ error: 'Title must be 200 characters or less' }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' },
            });
            if (!hadCookie) {
                response.headers.set('Set-Cookie', createNonceCookie(cookieId));
            }
            return response;
        }

        if (!type || !['movie', 'tv'].includes(type)) {
            const response = new Response(JSON.stringify({ error: 'Type must be either "movie" or "tv"' }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' },
            });
            if (!hadCookie) {
                response.headers.set('Set-Cookie', createNonceCookie(cookieId));
            }
            return response;
        }

        if (year && (typeof year !== 'string' || !/^\d{4}$/.test(year))) {
            const response = new Response(JSON.stringify({ error: 'Year must be a 4-digit number if provided' }), {
                status: 400,
                headers: { 'Content-Type': 'application/json' },
            });
            if (!hadCookie) {
                response.headers.set('Set-Cookie', createNonceCookie(cookieId));
            }
            return response;
        }

        // if (requester && (typeof requester !== 'string' || requester.length > 500)) {
        //     const response = new Response(JSON.stringify({ error: 'Requester name must be 500 characters or less if provided' }), {
        //         status: 400,
        //         headers: { 'Content-Type': 'application/json' },
        //     });
        //     if (!hadCookie) {
        //         response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        //     }
        //     return response;
        // }

        // Fetch synopsis and IMDb ID from TMDB
        let synopsis = '';
        let imdbId = '';
        let matchingItem: TMDBResult | null = null;
        try {
            const searchResponse = await fetch(`https://api.themoviedb.org/3/search/multi?api_key=${import.meta.env.TMDB_API_KEY}&query=${encodeURIComponent(title!)}`);
            if (searchResponse.ok) {
                const searchData = await searchResponse.json() as TMDBSearchResponse;
                matchingItem = searchData.results.find(item => 
                    item.media_type === type && 
                    (item.title || item.name) === title
                ) || null;
                if (matchingItem) {
                    synopsis = matchingItem.overview || '';
                    
                    // Get detailed info for IMDb ID
                    const detailEndpoint = type === 'movie' ? `movie/${matchingItem.id}` : `tv/${matchingItem.id}`;
                    const detailResponse = await fetch(`https://api.themoviedb.org/3/${detailEndpoint}?api_key=${import.meta.env.TMDB_API_KEY}`);
                    if (detailResponse.ok) {
                        const detailData = await detailResponse.json() as { imdb_id?: string };
                        imdbId = detailData.imdb_id || '';
                    }
                }
            }
        } catch (error) {
            console.error('Error fetching synopsis and IMDb:', error);
            // Continue without synopsis
        }

        const fields = [
            {
                name: "Title",
                value: title,
                inline: false
            },
            {
                name: "Type",
                value: type === 'tv' ? 'TV Show' : 'Movie',
                inline: false
            }
        ];

        if (year) {
            fields.push({
                name: "Year",
                value: year,
                inline: false
            });
        }

        if (synopsis) {
            fields.push({
                name: "Synopsis",
                value: synopsis,
                inline: false
            });
        }

        if (imdbId) {
            fields.push({
                name: "IMDb",
                value: `[View on IMDb](https://www.imdb.com/title/${imdbId}/)`,
                inline: false
            });
        } else if (matchingItem) {
            const tmdbUrl = `https://www.themoviedb.org/${type}/${matchingItem.id}`;
            fields.push({
                name: "TMDB",
                value: `[View on TMDB](${tmdbUrl})`,
                inline: false
            });
        }

        // if (requester && requester.trim()) {
        //     fields.push({
        //         name: "Requested by",
        //         value: requester.trim(),
        //         inline: false
        //     });
        // }

        interface DiscordEmbed {
            title: string;
            color: number;
            fields: Array<{ name: string; value: string; inline: boolean }>;
            timestamp: string;
            footer: { text: string };
            image?: { url: string };
        }

        const embed: DiscordEmbed = {
            title: type === 'tv' ? "📺 New TV Show Request" : "🎥 New Movie Request",
            color: type === 'tv' ? 0x4ecdc4 : 0xff6b6b,
            fields: fields,
            timestamp: new Date().toISOString(),
            footer: {
                text: subsite?.host || 'req.boatson.boats'
            }
        };

        if (matchingItem && matchingItem.poster_path) {
            embed.image = { url: `https://image.tmdb.org/t/p/w780${matchingItem.poster_path}` };
        } else {
            // Test image
            embed.image = { url: 'https://image.tmdb.org/t/p/w780/9O7gLzmreU0nGkIB6K3BsJbzvNv.jpg' };
        }

        const apiResponse = await fetch(DISCORD_WEBHOOK_URL, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ embeds: [embed] }),
        });

        if (!apiResponse.ok) {
            throw new Error(`Discord webhook error: ${apiResponse.status}`);
        }

        // Record the request for rate limiting after successful submission
        recordRateLimitRequest(request, 15_000);

        // Generate a new CSRF token for the next submission
        const newCsrfToken = generateCsrfToken(cookieId);

        const response = new Response(JSON.stringify({ success: true, csrfToken: newCsrfToken }), {
            headers: { 'Content-Type': 'application/json' },
        });
        if (!hadCookie) {
            response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        }
        return response;
    } catch (error) {
        console.error('Webhook submission error:', error);
        const response = new Response(JSON.stringify({ error: 'Failed to submit' }), {
            status: 500,
            headers: { 'Content-Type': 'application/json' },
        });
        if (!hadCookie) {
            response.headers.set('Set-Cookie', createNonceCookie(cookieId));
        }
        return response;
    }
}