import { Router, Request, Response } from 'express';
import { prisma } from '../index';
import { asyncHandler } from '../middleware/errorHandler';
import { authenticateToken, AuthenticatedRequest } from '../middleware/auth';
import multer from 'multer';
import { v4 as uuidv4 } from 'uuid';
import path from 'path';
import fs from 'fs';
import Joi from 'joi';

const router = Router();

// Configure multer for file uploads
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = process.env['UPLOAD_DIR'] || './uploads';
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const uuid = uuidv4();
    const extension = path.extname(file.originalname);
    cb(null, `${uuid}${extension}`);
  },
});

const upload = multer({
  storage,
  limits: {
    fileSize: parseInt(process.env['MAX_FILE_SIZE'] || '262144000'), // 250MB default
  },
  fileFilter: (req, file, cb) => {
    // Allow PDF files with multiple possible MIME types
    const allowedMimeTypes = [
      'application/pdf',
      'application/x-pdf',
      'application/acrobat',
      'applications/vnd.pdf',
      'text/pdf',
      'text/x-pdf'
    ];
    
    // Check MIME type or file extension
    const isValidPDF = allowedMimeTypes.includes(file.mimetype) || 
                       file.originalname.toLowerCase().endsWith('.pdf');
    
    // Log for debugging
    console.log('Upload attempt:', {
      mimetype: file.mimetype,
      filename: file.originalname,
      isValid: isValidPDF
    });
    
    if (isValidPDF) {
      cb(null, true);
    } else {
      cb(new Error(`Only PDF files are allowed. Received: ${file.mimetype} for file: ${file.originalname}`));
    }
  },
});

// Validation schemas
const createDocumentSchema = Joi.object({
  docketEntryId: Joi.number().integer().required(),
  title: Joi.string().required().max(500),
  summary: Joi.string().optional().allow(''),
  notes: Joi.string().optional().allow(''),
  displayOrder: Joi.number().integer().min(0).optional(),
});

const updateDocumentSchema = Joi.object({
  title: Joi.string().optional().max(500),
  summary: Joi.string().optional().allow(''),
  notes: Joi.string().optional().allow(''),
  displayOrder: Joi.number().integer().min(0).optional(),
});

// Public endpoint - Download document
router.get('/:id/download', asyncHandler(async (req: Request, res: Response) => {
  const documentId = parseInt(req.params['id'] || '');
  
  if (isNaN(documentId)) {
    return res.status(400).json({
      success: false,
      message: 'Invalid document ID',
    });
  }

  const document = await prisma.document.findUnique({
    where: { id: documentId },
  });

  if (!document) {
    return res.status(404).json({
      success: false,
      message: 'Document not found',
    });
  }

  const filePath = document.filePath;
  
  if (!fs.existsSync(filePath)) {
    return res.status(404).json({
      success: false,
      message: 'File not found on server',
    });
  }

  res.setHeader('Content-Type', document.mimeType);
  res.setHeader('Content-Disposition', `inline; filename="${document.originalFilename}"`);
  
  const fileStream = fs.createReadStream(filePath);
  fileStream.pipe(res);
}));

// Admin endpoint - Upload document
router.post('/upload', authenticateToken, upload.single('file'), asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  if (!req.file) {
    return res.status(400).json({
      success: false,
      message: 'No file uploaded',
    });
  }

  const { error, value } = createDocumentSchema.validate(req.body);
  
  if (error) {
    // Clean up uploaded file if validation fails
    fs.unlinkSync(req.file.path);
    return res.status(400).json({
      success: false,
      message: error.details[0].message,
    });
  }

  const { docketEntryId, title, summary, notes, displayOrder } = value;

  // Verify docket entry exists
  const docketEntry = await prisma.docketEntry.findUnique({
    where: { id: docketEntryId },
  });

  if (!docketEntry) {
    // Clean up uploaded file
    fs.unlinkSync(req.file.path);
    return res.status(404).json({
      success: false,
      message: 'Docket entry not found',
    });
  }

  // Get next display order if not provided
  let finalDisplayOrder = displayOrder;
  if (finalDisplayOrder === undefined) {
    const lastDocument = await prisma.document.findFirst({
      where: { docketEntryId },
      orderBy: { displayOrder: 'desc' },
    });
    finalDisplayOrder = lastDocument ? lastDocument.displayOrder + 1 : 0;
  }

  const document = await prisma.document.create({
    data: {
      docketEntryId,
      title,
      originalFilename: req.file.originalname,
      storedFilename: req.file.filename,
      filePath: req.file.path,
      fileSize: req.file.size,
      mimeType: req.file.mimetype,
      summary: summary || '',
      notes: notes || '',
      displayOrder: finalDisplayOrder,
    },
  });

  res.status(201).json({
    success: true,
    message: 'Document uploaded successfully',
    document,
  });
}));

// Admin endpoint - Update document metadata
router.put('/:id', authenticateToken, asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const documentId = parseInt(req.params['id'] || '');
  
  if (isNaN(documentId)) {
    return res.status(400).json({
      success: false,
      message: 'Invalid document ID',
    });
  }

  const { error, value } = updateDocumentSchema.validate(req.body);
  
  if (error) {
    return res.status(400).json({
      success: false,
      message: error.details[0].message,
    });
  }

  try {
    const document = await prisma.document.update({
      where: { id: documentId },
      data: value,
    });

    res.json({
      success: true,
      message: 'Document updated successfully',
      document,
    });
  } catch (error: any) {
    if (error.code === 'P2025') {
      return res.status(404).json({
        success: false,
        message: 'Document not found',
      });
    }
    throw error;
  }
}));

// Admin endpoint - Delete document
router.delete('/:id', authenticateToken, asyncHandler(async (req: AuthenticatedRequest, res: Response) => {
  const documentId = parseInt(req.params['id'] || '');
  
  if (isNaN(documentId)) {
    return res.status(400).json({
      success: false,
      message: 'Invalid document ID',
    });
  }

  try {
    const document = await prisma.document.findUnique({
      where: { id: documentId },
    });

    if (!document) {
      return res.status(404).json({
        success: false,
        message: 'Document not found',
      });
    }

    // Delete the file from filesystem
    if (fs.existsSync(document.filePath)) {
      fs.unlinkSync(document.filePath);
    }

    // Delete from database
    await prisma.document.delete({
      where: { id: documentId },
    });

    res.json({
      success: true,
      message: 'Document deleted successfully',
    });
  } catch (error: any) {
    if (error.code === 'P2025') {
      return res.status(404).json({
        success: false,
        message: 'Document not found',
      });
    }
    throw error;
  }
}));

export default router;
