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

export async function POST(
  req: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session) {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const body = await req.json();
    const { signatureData, signerType } = body;

    if (!signatureData || !signatureData.imageData || !signatureData.name || !signatureData.email) {
      return NextResponse.json({ error: 'Invalid signature data' }, { status: 400 });
    }

    if (!signerType || !['CLIENT', 'COMPANY', 'PARTNER'].includes(signerType)) {
      return NextResponse.json({ error: 'Invalid signer type' }, { status: 400 });
    }

    // Fetch contract
    const contract = await prisma.contract.findUnique({
      where: { id: params.id },
      include: {
        signatures: true,
        user: true,
        quote: true
      }
    });

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

    // Authorization check
    if (signerType === 'CLIENT' && contract.userId !== session.user.id && session.user.role !== 'ADMIN') {
      return NextResponse.json({ error: 'Only the client can sign as client' }, { status: 403 });
    }

    if ((signerType === 'COMPANY' || signerType === 'PARTNER') && session.user.role === 'CUSTOMER') {
      return NextResponse.json({ error: 'Customers cannot sign as company/partner' }, { status: 403 });
    }

    // Check if this signer type has already signed
    const existingSignature = contract.signatures.find((s: any) => s.signerType === signerType);
    if (existingSignature) {
      return NextResponse.json({ 
        error: `${signerType} has already signed this contract` 
      }, { status: 400 });
    }

    // Get current PDF
    if (!contract.pdfStoragePath) {
      return NextResponse.json({ error: 'Contract PDF not found' }, { status: 404 });
    }

    const pdfUrl = await downloadFile(contract.pdfStoragePath);
    const pdfResponse = await fetch(pdfUrl);
    const pdfBuffer = await pdfResponse.arrayBuffer();
    const pdfBytes = new Uint8Array(pdfBuffer);

    // Add signature to PDF
    const timestamp = new Date().toLocaleString('en-ZA');
    const signedPdfBytes = await pdfService.addSignatureToPDF(
      pdfBytes,
      signatureData.imageData,
      signatureData.name,
      signatureData.email,
      signerType,
      timestamp
    );

    // Upload signed PDF
    const signedPdfBuffer = Buffer.from(signedPdfBytes);
    const newPdfPath = await uploadFile(
      signedPdfBuffer, 
      `contract-${contract.contractNumber}-signed-${Date.now()}.pdf`
    );

    // Generate signature hash
    const signatureHash = pdfService.generateSignatureHash({
      ...signatureData,
      timestamp,
      contractId: contract.id,
      signerType
    });

    // Upload signature image to S3
    const signatureImageBuffer = Buffer.from(
      signatureData.imageData.replace(/^data:image\/\w+;base64,/, ''),
      'base64'
    );
    const signatureImagePath = await uploadFile(
      signatureImageBuffer,
      `signature-${contract.contractNumber}-${signerType}-${Date.now()}.png`
    );

    // Get IP address and user agent
    const ipAddress = req.headers.get('x-forwarded-for') || req.headers.get('x-real-ip') || 'unknown';
    const userAgent = req.headers.get('user-agent') || 'unknown';

    // Save signature record
    await prisma.signature.create({
      data: {
        contractId: contract.id,
        signerType: signerType,
        signerName: signatureData.name,
        signerEmail: signatureData.email,
        signatureImage: signatureImagePath,
        signatureHash: signatureHash,
        ipAddress: ipAddress,
        userAgent: userAgent
      }
    });

    // Update contract
    const updateData: any = {
      pdfStoragePath: newPdfPath
    };

    if (signerType === 'CLIENT') {
      updateData.customerSignature = signatureImagePath;
    } else if (signerType === 'COMPANY' || signerType === 'PARTNER') {
      updateData.contractorSignature = signatureImagePath;
    }

    // Check if all required signatures are collected
    const allSignatures = await prisma.signature.findMany({
      where: { contractId: contract.id }
    });

    const hasClientSignature = allSignatures.some((s: any) => s.signerType === 'CLIENT') || signerType === 'CLIENT';
    const hasCompanySignature = allSignatures.some((s: any) => s.signerType === 'COMPANY' || s.signerType === 'PARTNER') || (signerType === 'COMPANY' || signerType === 'PARTNER');

    const isFullySigned = hasClientSignature && hasCompanySignature;

    if (isFullySigned) {
      updateData.status = 'ACTIVE';
      updateData.signedAt = new Date();
    } else {
      updateData.status = 'PENDING_SIGNATURE';
    }

    const updatedContract = await prisma.contract.update({
      where: { id: contract.id },
      data: updateData,
      include: {
        signatures: true
      }
    });

    // Get new PDF URL
    const newPdfUrl = await downloadFile(newPdfPath);

    return NextResponse.json({
      success: true,
      pdfUrl: newPdfUrl,
      isFullySigned,
      contract: updatedContract
    });
  } catch (error) {
    console.error('Error signing contract:', error);
    return NextResponse.json(
      { error: 'Failed to sign contract' },
      { status: 500 }
    );
  }
}
