import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@/app/api/auth/[...nextauth]/route';
import { prismaAuth } from '@/lib/db';
import { writeFile, mkdir, access } from 'fs/promises';
import { existsSync } from 'fs';
import { constants } from 'fs';
import path from 'path';

// Maximum file size: 50MB for images, 500MB for videos
const MAX_IMAGE_SIZE = 50 * 1024 * 1024;
const MAX_VIDEO_SIZE = 500 * 1024 * 1024;
// Allowed image types
const ALLOWED_IMAGE_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
// Allowed video types
const ALLOWED_VIDEO_TYPES = ['video/mp4', 'video/mpeg', 'video/quicktime', 'video/x-msvideo', 'video/webm'];
// Combined allowed types
const ALLOWED_TYPES = [...ALLOWED_IMAGE_TYPES, ...ALLOWED_VIDEO_TYPES];

// Get upload directory from environment variable
// REQUIRED: Must be set to a network share path accessible by both this app and the approval system
// Examples:
//   - Linux: /mnt/shared/pending-photos
//   - Windows: \\server\share\pending-photos (mapped to drive or use UNC path)
//   - SMB/CIFS: /mnt/smb/photos/pending
const getUploadDir = (): string => {
  const uploadDir = process.env.UPLOAD_DIR || process.env.PENDING_PHOTOS_DIR;
  
  if (!uploadDir) {
    throw new Error(
      'UPLOAD_DIR or PENDING_PHOTOS_DIR environment variable must be set. ' +
      'This should point to a network share accessible by both the web server and approval system.'
    );
  }
  
  // Use absolute path (network shares should already be absolute)
  return path.resolve(uploadDir);
};

export async function POST(request: NextRequest) {
  try {
    // Check authentication
    const session = await auth();
    if (!session?.user?.id) {
      return NextResponse.json(
        { error: 'Authentication required. Please sign in to upload files.' },
        { status: 401 }
      );
    }

    const formData = await request.formData();
    const photos = formData.getAll('photos') as File[];

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

    // Validate files
    const errors: string[] = [];
    const validPhotos: Array<{ file: File; name: string; size: number; type: string }> = [];

    for (const photo of photos) {
      // Check file type
      if (!ALLOWED_TYPES.includes(photo.type)) {
        errors.push(`${photo.name}: Invalid file type. Only images (JPEG, PNG, GIF, WebP) and videos (MP4, MOV, AVI, WebM) are allowed.`);
        continue;
      }

      // Check file size based on type
      const isVideo = ALLOWED_VIDEO_TYPES.includes(photo.type);
      const maxSize = isVideo ? MAX_VIDEO_SIZE : MAX_IMAGE_SIZE;
      const maxSizeMB = isVideo ? 500 : 50;
      
      if (photo.size > maxSize) {
        errors.push(`${photo.name}: File size exceeds ${maxSizeMB}MB limit.`);
        continue;
      }

      if (photo.size === 0) {
        errors.push(`${photo.name}: File is empty.`);
        continue;
      }

      validPhotos.push({
        file: photo,
        name: photo.name,
        size: photo.size,
        type: photo.type,
      });
    }

    if (validPhotos.length === 0) {
      return NextResponse.json(
        { 
          error: 'No valid files to upload',
          details: errors.length > 0 ? errors : ['No files provided']
        },
        { status: 400 }
      );
    }

    const userId = parseInt(session.user.id, 10);
    if (isNaN(userId)) {
      return NextResponse.json(
        { error: 'Invalid user ID' },
        { status: 400 }
      );
    }

    // Get upload directory and ensure it exists
    let uploadBaseDir: string;
    try {
      uploadBaseDir = getUploadDir();
    } catch (error: any) {
      console.error('[PHOTO UPLOAD] Configuration error:', error.message);
      return NextResponse.json(
        { 
          error: 'Upload directory not configured',
          details: error.message + '. Please set UPLOAD_DIR or PENDING_PHOTOS_DIR environment variable to a network share path.'
        },
        { status: 500 }
      );
    }

    const userUploadDir = path.join(uploadBaseDir, userId.toString());
    
    // Check if parent directory (mount point) exists and is accessible
    const parentDir = path.dirname(uploadBaseDir);
    if (!existsSync(parentDir)) {
      console.error(`[PHOTO UPLOAD] Parent directory (mount point) does not exist: ${parentDir}`);
      return NextResponse.json(
        { 
          error: 'Upload directory mount point not found',
          details: `The mount point ${parentDir} does not exist. Please ensure the network share is mounted. See docs/NETWORK_SHARE_SETUP.md for setup instructions.`
        },
        { status: 500 }
      );
    }

    // Check if parent directory is accessible (not just exists)
    try {
      await access(parentDir, constants.R_OK | constants.W_OK);
    } catch (accessError: any) {
      console.error(`[PHOTO UPLOAD] Cannot access parent directory: ${parentDir}`, accessError);
      return NextResponse.json(
        { 
          error: 'Upload directory not accessible',
          details: `Cannot access mount point ${parentDir}. Please check permissions and ensure the network share is properly mounted. Error: ${accessError.message}`
        },
        { status: 500 }
      );
    }
    
    // Create directories if they don't exist
    // Note: Network shares should already exist, but we create user subdirectories
    try {
      if (!existsSync(uploadBaseDir)) {
        console.warn(`[PHOTO UPLOAD] Upload directory does not exist, attempting to create: ${uploadBaseDir}`);
        await mkdir(uploadBaseDir, { recursive: true });
      }
      if (!existsSync(userUploadDir)) {
        await mkdir(userUploadDir, { recursive: true });
      }
    } catch (error: any) {
      // Check if error is permission-related
      if (error.code === 'EACCES' || error.errno === -13) {
        console.error(`[PHOTO UPLOAD] Permission denied creating directory: ${uploadBaseDir}`, error);
        return NextResponse.json(
          { 
            error: 'Permission denied',
            details: `Permission denied when creating ${uploadBaseDir}. The mount point ${parentDir} exists but the application does not have write permissions. Please check:\n1. The network share is mounted with correct permissions\n2. The web server user has write access to the mount point\n3. See docs/NETWORK_SHARE_SETUP.md for troubleshooting`
          },
          { status: 500 }
        );
      }
      console.error(`[PHOTO UPLOAD] Failed to access/create upload directory: ${uploadBaseDir}`, error);
      return NextResponse.json(
        { 
          error: 'Failed to access upload directory',
          details: `Cannot access network share at ${uploadBaseDir}. Please verify the path is correct and the server has read/write permissions. Error: ${error.message}`
        },
        { status: 500 }
      );
    }

    // Save files and create database records
    const savedPhotos = [];
    const saveErrors: string[] = [];

    for (const photo of validPhotos) {
      try {
        // Generate unique filename: timestamp-originalname
        const timestamp = Date.now();
        const sanitizedOriginalName = photo.name.replace(/[^a-zA-Z0-9._-]/g, '_');
        const fileExtension = path.extname(photo.name);
        const baseName = path.basename(sanitizedOriginalName, fileExtension);
        const uniqueFilename = `${timestamp}-${baseName}${fileExtension}`;
        const filePath = path.join(userUploadDir, uniqueFilename);

        // Read file buffer
        const arrayBuffer = await photo.file.arrayBuffer();
        const buffer = Buffer.from(arrayBuffer);

        // Write file to disk
        await writeFile(filePath, buffer);

        // Create database record
        const pendingPhoto = await prismaAuth.pendingPhoto.create({
          data: {
            userId,
            filename: uniqueFilename,
            originalFilename: photo.name,
            filePath: filePath,
            fileSize: photo.size,
            mimeType: photo.type,
            status: 'pending',
          },
        });

        savedPhotos.push({
          id: pendingPhoto.id,
          filename: photo.name,
          size: photo.size,
        });
      } catch (error: any) {
        console.error(`Error saving photo ${photo.name}:`, error);
        saveErrors.push(`${photo.name}: ${error.message || 'Failed to save file'}`);
      }
    }

    if (savedPhotos.length === 0) {
      return NextResponse.json(
        { 
          error: 'Failed to save any photos',
          details: saveErrors.length > 0 ? saveErrors : ['Unknown error occurred']
        },
        { status: 500 }
      );
    }

    console.log(`[FILE UPLOAD] User ${userId} (${session.user.email}) submitted ${savedPhotos.length} file(s) for review`);

    return NextResponse.json({
      message: `Successfully submitted ${savedPhotos.length} file(s) for admin review`,
      photos: savedPhotos,
      errors: errors.length > 0 || saveErrors.length > 0 
        ? [...errors, ...saveErrors] 
        : undefined,
    });
  } catch (error: any) {
    console.error('Error uploading photos:', error);
    return NextResponse.json(
      { error: 'Failed to upload files', details: error.message },
      { status: 500 }
    );
  }
}

