import { Router } from "express";
import { Request, Response } from "express";
import { storage } from "../storage";
import multer from "multer";
import { z } from "zod";

const router = Router();

// Configure multer for file uploads
const upload = multer({ 
  storage: multer.memoryStorage(),
  limits: {
    fileSize: 10 * 1024 * 1024, // 10MB limit
  },
  fileFilter: (req, file, cb) => {
    // Accept common document and image formats
    const allowedTypes = [
      'application/pdf',
      'image/jpeg',
      'image/jpg', 
      'image/png',
      'image/gif',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'text/plain',
    ];
    
    if (allowedTypes.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error('Invalid file type. Only PDF, images, and documents are allowed.'));
    }
  }
});

// Validation schemas
const uploadDocumentSchema = z.object({
  patientId: z.string().transform((val) => parseInt(val, 10)),
});

const getDocumentsSchema = z.object({
  patientId: z.string().transform((val) => parseInt(val, 10)),
  limit: z.string().optional().transform((val) => val ? parseInt(val, 10) : undefined),
  offset: z.string().optional().transform((val) => val ? parseInt(val, 10) : undefined),
});

const deleteDocumentSchema = z.object({
  id: z.string().transform((val) => parseInt(val, 10)),
});

// POST /api/patient-documents/upload
// Upload a document for a specific patient
router.post("/upload", upload.single("file"), async (req: Request, res: Response): Promise<any> => {
  try {
    const { patientId } = uploadDocumentSchema.parse(req.body);
    const file = req.file;
    
    if (!file) {
      return res.status(400).json({ error: "No file uploaded" });
    }

    const document = await storage.createPatientDocument(
      patientId,
      file.originalname,
      file.originalname,
      file.mimetype,
      file.size,
      file.buffer
    );

    res.status(201).json({
      success: true,
      document: {
        ...document,
        fileSize: Number(document.fileSize), // Convert BigInt to Number for JSON serialization
      }
    });
  } catch (error) {
    console.error("Error uploading document:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid request data", details: error.errors });
    }
    
    if (error instanceof Error && error.message.includes('Invalid file type')) {
      return res.status(400).json({ error: error.message });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

// GET /api/patient-documents/patient/:patientId
// Get all documents for a specific patient
router.get("/patient/:patientId", async (req: Request, res: Response): Promise<any> => {
  try {
    const { patientId, limit, offset } = getDocumentsSchema.parse({
      patientId: req.params.patientId,
      limit: req.query.limit,
      offset: req.query.offset,
    });

    if (limit !== undefined && offset !== undefined) {
      // Paginated response
      const result = await storage.getDocumentsByPatientIdPaginated(patientId, limit, offset);
      res.json({
        success: true,
        documents: result.documents.map(doc => ({
          ...doc,
          fileSize: Number(doc.fileSize), // Convert BigInt to Number
        })),
        total: result.total,
      });
    } else {
      // Non-paginated response
      const documents = await storage.getDocumentsByPatientId(patientId);
      res.json({
        success: true,
        documents: documents.map(doc => ({
          ...doc,
          fileSize: Number(doc.fileSize), // Convert BigInt to Number
        })),
      });
    }
  } catch (error) {
    console.error("Error fetching documents:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid patient ID", details: error.errors });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

// GET /api/patient-documents/:id/download
// Download a specific document
router.get("/:id/download", async (req: Request, res: Response): Promise<any> => {
  try {
    const { id } = deleteDocumentSchema.parse({ id: req.params.id });
    
    const result = await storage.getDocumentFile(id);
    
    if (!result) {
      return res.status(404).json({ error: "Document not found" });
    }
    
    const { buffer, document } = result;
    
    // Set appropriate headers
    res.setHeader("Content-Type", document.mimeType);
    res.setHeader("Content-Length", document.fileSize.toString());
    res.setHeader(
      "Content-Disposition",
      `attachment; filename="${encodeURIComponent(document.originalName)}"`
    );
    
    res.send(buffer);
  } catch (error) {
    console.error("Error downloading document:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid document ID", details: error.errors });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

// GET /api/patient-documents/:id/view
// View a specific document (inline display)
router.get("/:id/view", async (req: Request, res: Response): Promise<any> => {
  try {
    const { id } = deleteDocumentSchema.parse({ id: req.params.id });
    
    const result = await storage.getDocumentFile(id);
    
    if (!result) {
      return res.status(404).json({ error: "Document not found" });
    }
    
    const { buffer, document } = result;
    
    // Set appropriate headers for inline viewing
    res.setHeader("Content-Type", document.mimeType);
    res.setHeader("Content-Length", document.fileSize.toString());
    res.setHeader(
      "Content-Disposition",
      `inline; filename="${encodeURIComponent(document.originalName)}"`
    );
    
    res.send(buffer);
  } catch (error) {
    console.error("Error viewing document:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid document ID", details: error.errors });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

// DELETE /api/patient-documents/:id
// Delete a specific document
router.delete("/:id", async (req: Request, res: Response): Promise<any> => {
  try {
    const { id } = deleteDocumentSchema.parse({ id: req.params.id });
    
    const success = await storage.deleteDocument(id);
    
    if (!success) {
      return res.status(404).json({ error: "Document not found" });
    }
    
    res.json({ success: true, message: "Document deleted successfully" });
  } catch (error) {
    console.error("Error deleting document:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid document ID", details: error.errors });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

// POST /api/patient-documents/scan
// Simulate document scanning (placeholder for actual scanner integration)
router.post("/scan", async (req: Request, res: Response): Promise<any> => {
  try {
    const { patientId } = uploadDocumentSchema.parse(req.body);
    
    // This is a placeholder for actual scanner integration
    // In a real implementation, you would:
    // 1. Interface with scanner hardware/software
    // 2. Capture the scanned image
    // 3. Process and save the image
    // 4. Return the document info
    
    res.json({
      success: true,
      message: "Scanner interface ready. Please integrate with your scanner hardware/software.",
      patientId,
      note: "This endpoint requires integration with scanner hardware/software SDK."
    });
  } catch (error) {
    console.error("Error scanning document:", error);
    
    if (error instanceof z.ZodError) {
      return res.status(400).json({ error: "Invalid request data", details: error.errors });
    }
    
    res.status(500).json({ error: "Internal server error" });
  }
});

export default router;
