import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { requireAuthenticatedUser, canModifyJourney, unauthorizedResponse } from '@/lib/api-auth';
import { extractExifMetadata } from '@/lib/exif';
import { writeFile, mkdir } from 'fs/promises';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
import sharp from 'sharp';

export async function POST(req: NextRequest, { params }: { params: Promise<{ id: string; stopId: string }> }) {
    try {
        const session = await requireAuthenticatedUser();
        if (!session) return unauthorizedResponse();

        const { id: journeyId, stopId } = await params;

        const journey = await prisma.journey.findUnique({ where: { id: journeyId } });
        if (!journey) {
            return NextResponse.json({ error: 'Journey not found' }, { status: 404 });
        }
        if (!canModifyJourney(session as { user: { id: string; role?: string } }, journey.userId)) {
            return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
        }

        const stop = await prisma.journeyStop.findUnique({ where: { id: stopId } });
        if (!stop || stop.journeyId !== journeyId) {
            return NextResponse.json({ error: 'Stop not found' }, { status: 404 });
        }

        const contentType = req.headers.get('content-type') || '';

        // Mode 1: Archive photo reference (JSON body)
        if (contentType.includes('application/json')) {
            const body = await req.json();
            const { photoId } = body;

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

            const archivePhoto = await prisma.photo.findUnique({ where: { id: photoId } });
            if (!archivePhoto) {
                return NextResponse.json({ error: 'Archive photo not found' }, { status: 404 });
            }

            const maxOrder = await prisma.journeyPhoto.aggregate({
                where: { stopId },
                _max: { order: true },
            });

            const journeyPhoto = await prisma.journeyPhoto.create({
                data: {
                    stopId,
                    photoId: archivePhoto.id,
                    url: archivePhoto.url,
                    filename: archivePhoto.filename,
                    caption: archivePhoto.caption,
                    location: archivePhoto.location,
                    latitude: archivePhoto.latitude,
                    longitude: archivePhoto.longitude,
                    dateTaken: archivePhoto.dateTaken,
                    order: (maxOrder._max.order ?? -1) + 1,
                },
            });

            return NextResponse.json(journeyPhoto, { status: 201 });
        }

        // Mode 2: File upload (multipart)
        const formData = await req.formData();
        const files = formData.getAll('files') as File[];

        if (!files.length) {
            return NextResponse.json({ error: 'No files provided' }, { status: 400 });
        }

        const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'image/tiff', 'image/heic', 'image/heif'];
        const MAX_FILE_SIZE = 50 * 1024 * 1024;

        for (const file of files) {
            if (!ALLOWED_TYPES.includes(file.type)) {
                return NextResponse.json({ error: `Invalid file type: ${file.type}` }, { status: 400 });
            }
            if (file.size > MAX_FILE_SIZE) {
                return NextResponse.json({ error: `File ${file.name} too large (max 50MB)` }, { status: 400 });
            }
        }

        const uploadDir = path.join(process.cwd(), 'public', 'uploads', 'journeys', journeyId, stopId);
        await mkdir(uploadDir, { recursive: true });

        const results = [];

        for (const file of files) {
            const buffer = Buffer.from(await file.arrayBuffer());
            const metadata = await extractExifMetadata(buffer);

            const safeFilename = path.basename(file.name);
            const filename = `${uuidv4()}-${safeFilename}`;
            const filepath = path.join(uploadDir, filename);

            // Process with sharp
            try {
                await sharp(buffer)
                    .rotate()
                    .resize(2500, 2500, { fit: 'inside', withoutEnlargement: true })
                    .jpeg({ quality: 85, mozjpeg: true })
                    .withMetadata()
                    .toFile(filepath);
            } catch {
                await writeFile(filepath, buffer);
            }

            const maxOrder = await prisma.journeyPhoto.aggregate({
                where: { stopId },
                _max: { order: true },
            });

            const journeyPhoto = await prisma.journeyPhoto.create({
                data: {
                    stopId,
                    url: `/uploads/journeys/${journeyId}/${stopId}/${filename}`,
                    filename: safeFilename,
                    caption: metadata.caption,
                    location: metadata.location,
                    latitude: metadata.latitude,
                    longitude: metadata.longitude,
                    dateTaken: metadata.dateTaken,
                    order: (maxOrder._max.order ?? -1) + 1,
                },
            });

            results.push(journeyPhoto);
        }

        return NextResponse.json({ photos: results }, { status: 201 });
    } catch (error) {
        console.error('Journey photo upload error:', error);
        return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
    }
}
