import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { getHolidayHint } from '@/lib/holidays';
import { getRandomLocalQuote } from '@/lib/quotes';

export const dynamic = 'force-dynamic';

export async function GET(req: Request) {
    try {
        const session = await getServerSession(authOptions);
        if (!session?.user?.email) {
            return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
        }

        const { searchParams } = new URL(req.url);
        const weekStartParam = searchParams.get('weekStart');

        if (!weekStartParam) {
            return NextResponse.json({ error: 'weekStart is required' }, { status: 400 });
        }

        const date = new Date(weekStartParam);
        date.setUTCHours(0, 0, 0, 0);

        // Look up by email — session ID can be stale after DB restore
        const user = await prisma.user.findUnique({
            where: { email: session.user.email },
            select: {
                id: true,
                goalFallbackType: true,
                goalDefaultSentence: true,
                language: true,
                quoteLanguages: true,
                quoteSourceUrls: true,
            }
        });

        if (!user) return NextResponse.json({ error: 'User not found' }, { status: 404 });
        const userId = user.id;

        // 1. Check if user has a custom set goal for THIS week specifically
        const goal = await prisma.weeklyGoal.findUnique({
            where: {
                userId_weekStart: {
                    userId: userId,
                    weekStart: date,
                },
            },
        });

        if (goal && goal.text) {
            return NextResponse.json({ goal: goal.text });
        }

        // 2. Handle Fallbacks based on user settings
        const fallbackType = user?.goalFallbackType || 'quote';

        if (fallbackType === 'next_todo') {
            // Fetch first incomplete task for this week
            const weekEnd = new Date(date);
            weekEnd.setDate(weekEnd.getDate() + 7);

            const nextTask = await prisma.task.findFirst({
                where: {
                    userId,
                    completed: false,
                    scheduledDate: {
                        gte: date,
                        lt: weekEnd
                    }
                },
                orderBy: [
                    { scheduledDate: 'asc' },
                    { order: 'asc' }
                ]
            });

            if (nextTask) {
                return NextResponse.json({ goal: `Next: ${nextTask.title}`, isNextTask: true });
            }
            // If no tasks, fall back to quote or default? Let's go to quote.
        }

        if (fallbackType === 'default') {
            return NextResponse.json({ goal: user?.goalDefaultSentence || 'goal of the week', isDefault: true });
        }

        // 3. Fallback to holiday/celebration hints (High priority for "quote" type)
        const holidayHint = getHolidayHint(date);
        if (holidayHint) {
            return NextResponse.json({ goal: holidayHint, isHoliday: true });
        }

        // 4. Try user-configured quote source URLs, then ZenQuotes
        const quoteLangs: string[] = (user as any)?.quoteLanguages?.length > 0
            ? (user as any).quoteLanguages
            : [user?.language || 'en'];

        // Universal JSON quote parser — handles the most common free API response shapes
        const parseQuoteResponse = (data: any): string | null => {
            try {
                // Array responses: pick a random element
                if (Array.isArray(data)) {
                    if (data.length === 0) return null;
                    data = data[Math.floor(Math.random() * data.length)];
                }
                // ZenQuotes: [{q, a}]
                if (data.q && data.a) return `${data.q} — ${data.a}`;
                // Quotable: {content, author}
                if (data.content && data.author) return `${data.content} — ${data.author}`;
                // Forismatic: {quoteText, quoteAuthor}
                if (data.quoteText) return data.quoteAuthor?.trim() ? `${data.quoteText.trim()} — ${data.quoteAuthor.trim()}` : data.quoteText.trim();
                // zitat-service.de: {quote, authorName}
                if (data.quote && data.authorName) return `${data.quote} — ${data.authorName}`;
                // Common: {text, author} or {quote, author} or {body, ...}
                const text = data.text || data.quote || data.body || data.sentence;
                const author = data.author || data.authorName || data.by || data.from || data.speaker;
                if (text) return author ? `${text} — ${author}` : text;
                // Nested: {data: {...}}
                if (data.data) return parseQuoteResponse(data.data);
                // Advice Slip: {slip: {advice}}
                if (data.slip?.advice) return data.slip.advice;
            } catch { /* ignore */ }
            return null;
        };

        // Try each user-configured URL first
        const PRIVATE_IP = /^(localhost|127\.|0\.0\.0\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|169\.254\.|::1$|fc00:|fe80:)/i;
        function isSafeQuoteUrl(raw: string): boolean {
            try {
                const u = new URL(raw);
                if (!['http:', 'https:'].includes(u.protocol)) return false;
                if (PRIVATE_IP.test(u.hostname)) return false;
                return true;
            } catch { return false; }
        }
        const userUrls: string[] = ((user as any)?.quoteSourceUrls?.filter(Boolean) || []).filter(isSafeQuoteUrl);
        for (const url of userUrls) {
            try {
                const res = await fetch(url, { signal: AbortSignal.timeout(4000) });
                if (res.ok) {
                    const data = await res.json();
                    const parsed = parseQuoteResponse(data);
                    if (parsed) return NextResponse.json({ goal: parsed, isQuote: true });
                }
            } catch (e) {
                console.error(`Failed to fetch from ${url}:`, e);
            }
        }

        // Built-in multilingual fallbacks via zitat-service.de (de, en, es) + ZenQuotes (en)
        const zitatLangMap: Record<string, string> = { de: 'de', en: 'en', es: 'es' };
        const zitatLang = quoteLangs.find(l => zitatLangMap[l]);
        if (zitatLang) {
            try {
                const res = await fetch(`https://api.zitat-service.de/v1/quote?language=${zitatLangMap[zitatLang]}`, { signal: AbortSignal.timeout(4000) });
                if (res.ok) {
                    const data = await res.json();
                    const parsed = parseQuoteResponse(data);
                    if (parsed) return NextResponse.json({ goal: parsed, isQuote: true });
                }
            } catch (e) {
                console.error('Failed to fetch from zitat-service.de:', e);
            }
        }

        // ZenQuotes as English fallback
        if (quoteLangs.includes('en')) {
            try {
                const res = await fetch('https://zenquotes.io/api/random', { signal: AbortSignal.timeout(3000) });
                if (res.ok) {
                    const data = await res.json();
                    if (data && data[0] && data[0].q) {
                        return NextResponse.json({ goal: `${data[0].q} — ${data[0].a}`, isQuote: true });
                    }
                }
            } catch (e) {
                console.error('Failed to fetch from ZenQuotes:', e);
            }
        }

        // 5. Fallback to local curated quotes (pick random from selected languages)
        const randomLang = quoteLangs[Math.floor(Math.random() * quoteLangs.length)];
        const localQuote = getRandomLocalQuote(randomLang);
        if (localQuote) {
            return NextResponse.json({ goal: `${localQuote.text} — ${localQuote.author}`, isQuote: true });
        }

        // Final default fallback
        return NextResponse.json({ goal: user?.goalDefaultSentence || 'goal of the week', isDefault: true });
    } catch (error) {
        console.error('API Error:', error);
        return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
    }
}

// POST delegates to PUT for client compatibility
export async function POST(req: Request) {
    return PUT(req);
}

export async function PUT(req: Request) {
    try {
        const session = await getServerSession(authOptions);
        if (!session?.user?.email) {
            return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
        }

        const dbUser = await prisma.user.findUnique({ where: { email: session.user.email }, select: { id: true } });
        if (!dbUser) return NextResponse.json({ error: 'User not found' }, { status: 404 });
        const userId = dbUser.id;

        const { weekStart, text } = await req.json();

        if (!weekStart) {
            return NextResponse.json({ error: 'weekStart is required' }, { status: 400 });
        }

        const date = new Date(weekStart);
        date.setUTCHours(0, 0, 0, 0);

        const goal = await prisma.weeklyGoal.upsert({
            where: {
                userId_weekStart: {
                    userId: userId,
                    weekStart: date,
                },
            },
            update: { text },
            create: {
                userId: userId,
                weekStart: date,
                text,
            },
        });

        return NextResponse.json({ goal: goal.text });
    } catch (error) {
        console.error('API Error:', error);
        return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
    }
}
