
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { prisma } from '@/lib/db';
import { uploadFile } from '@/lib/s3';

// POST /api/uploads/milestone-photo - Upload mandatory milestone photo
export async function POST(request: NextRequest) {
  try {
    const session = await getServerSession();
    if (!session?.user) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const formData = await request.formData();
    const file = formData.get('file') as File;
    const milestoneId = formData.get('milestoneId') as string;
    const contractId = formData.get('contractId') as string;
    const latitude = parseFloat(formData.get('latitude') as string);
    const longitude = parseFloat(formData.get('longitude') as string);
    const accuracy = parseFloat(formData.get('accuracy') as string);

    if (!file || !milestoneId || !contractId) {
      return NextResponse.json(
        { error: 'Missing required fields' },
        { status: 400 }
      );
    }

    // Check GPS requirements
    const milestone = await prisma.projectMilestone.findUnique({
      where: { id: milestoneId },
    });

    if (!milestone) {
      return NextResponse.json({ error: 'Milestone not found' }, { status: 404 });
    }

    if (milestone.gpsRequired && (!latitude || !longitude)) {
      return NextResponse.json(
        { error: 'GPS location required for this milestone' },
        { status: 400 }
      );
    }

    // Get expected location from contract
    const contract = await prisma.contract.findUnique({
      where: { id: contractId },
      include: {
        quote: {
          include: {
            lead: true,
          },
        },
      },
    });

    let locationVerified = false;
    let locationDistance = null;

    if (contract?.quote.lead.latitude && contract?.quote.lead.longitude) {
      locationDistance = calculateDistance(
        latitude,
        longitude,
        contract.quote.lead.latitude,
        contract.quote.lead.longitude
      );
      locationVerified = locationDistance < 100; // Within 100 meters
    }

    // Upload file to S3
    const buffer = Buffer.from(await file.arrayBuffer());
    const fileName = `${Date.now()}-${file.name}`;
    const cloudStoragePath = await uploadFile(buffer, `milestones/${contractId}/${fileName}`);

    // Create file upload record
    const upload = await prisma.fileUpload.create({
      data: {
        fileName: file.name,
        fileSize: file.size,
        fileType: file.type,
        cloudStoragePath,
        latitude,
        longitude,
        accuracy,
        gpsTimestamp: new Date(),
        expectedLatitude: contract?.quote.lead.latitude,
        expectedLongitude: contract?.quote.lead.longitude,
        locationVerified,
        locationDistance,
        uploadType: 'CONTRACTOR_PROGRESS',
        userId: session.user.id,
        contractId,
        milestoneId,
        isMandatory: true,
        isApproved: false,
      },
    });

    // Update milestone photo count
    await prisma.projectMilestone.update({
      where: { id: milestoneId },
      data: {
        photosUploaded: {
          increment: 1,
        },
        locationVerified: locationVerified || milestone.locationVerified,
      },
    });

    // Check if milestone photo requirements are met
    const updatedMilestone = await prisma.projectMilestone.findUnique({
      where: { id: milestoneId },
    });

    const requirementsMet =
      updatedMilestone &&
      updatedMilestone.photosUploaded >= updatedMilestone.minPhotos &&
      (!updatedMilestone.gpsRequired || updatedMilestone.locationVerified);

    return NextResponse.json({
      success: true,
      upload,
      locationVerified,
      locationDistance,
      requirementsMet,
    });
  } catch (error) {
    console.error('Error uploading milestone photo:', error);
    return NextResponse.json(
      { error: 'Failed to upload photo' },
      { status: 500 }
    );
  }
}

function calculateDistance(
  lat1: number,
  lon1: number,
  lat2: number,
  lon2: number
): number {
  const R = 6371e3;
  const φ1 = (lat1 * Math.PI) / 180;
  const φ2 = (lat2 * Math.PI) / 180;
  const Δφ = ((lat2 - lat1) * Math.PI) / 180;
  const Δλ = ((lon2 - lon1) * Math.PI) / 180;

  const a =
    Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
    Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return R * c;
}
