import { Controller, Delete, Get, Middleware, Post, Put } from '@overnightjs/core';
import { Request, Response } from 'express';
import { auth, AuthRequest } from '../middleware/auth';
import PatientService from '../services/PatientService';

@Controller('api/patients')
export class PatientController {
  @Get()
  @Middleware(auth)
  async getAllPatients(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as AuthRequest).user.userId;
      const page = parseInt(req.query.page as string) || 1;
      const limit = parseInt(req.query.limit as string) || 20;
      const search = req.query.search as string || '';

      const { data, total } = await PatientService.getAllPatients(page, limit, search, userId);

      res.json({
        success: true,
        data,
        meta: {
          total,
          page,
          limit,
          totalPages: Math.ceil(total / limit)
        }
      });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Get(':id')
  @Middleware(auth)
  async getPatientById(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const patient = await PatientService.getPatientById(id, userId);
      if (!patient) {
        res.status(404).json({ success: false, error: 'Patient not found' });
        return;
      }
      res.json({ success: true, data: patient });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Post()
  @Middleware(auth)
  async createPatient(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as AuthRequest).user.userId;
      let { doctorId } = req.body;

      // If doctorId not provided, get the doctor ID associated with the current user
      if (!doctorId) {
        doctorId = await PatientService.getDoctorIdFromUserId(userId);
      }

      const result = await PatientService.createPatientWithUser({
        ...req.body,
        doctorId
      });

      res.status(201).json({
        success: true,
        data: result.patient,
        message: result.message
      });
    } catch (error: any) {
      console.error('Create patient error:', error);
      const statusCode = error.message.includes('already exists') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Put(':id')
  @Middleware(auth)
  async updatePatient(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const updatedPatient = await PatientService.updatePatientAndUser(id, req.body, userId);
      if (!updatedPatient) {
        res.status(404).json({ success: false, error: 'Patient not found' });
        return;
      }
      res.json({ success: true, data: updatedPatient });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 : 400;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Delete(':id')
  @Middleware(auth)
  async deletePatient(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const patient = await PatientService.deletePatient(id, userId);
      if (!patient) {
        res.status(404).json({ success: false, error: 'Patient not found' });
        return;
      }
      res.json({ success: true, message: 'Patient deleted successfully' });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Post(':id/clinical-records')
  @Middleware(auth)
  async addClinicalRecord(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const clinicalRecord = await PatientService.addClinicalRecord({
        patientId: id,
        ...req.body
      }, userId);
      res.status(201).json({ success: true, data: clinicalRecord });
    } catch (error: any) {
      console.error('Add clinical record error:', error);
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Put(':id/clinical-records/:recordId')
  @Middleware(auth)
  async updateClinicalRecord(req: Request, res: Response): Promise<void> {
    try {
      const { id, recordId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const clinicalRecord = await PatientService.updateClinicalRecord(
        id,
        recordId,
        req.body,
        userId
      );
      res.json({ success: true, data: clinicalRecord });
    } catch (error: any) {
      console.error('Update clinical record error:', error);
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('Blob') ? 400 :
            error.message.includes('not supported') ? 400 :
          error.message.includes('not found') ? 404 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Put(':id/dental-records/:recordId')
  @Middleware(auth)
  async updateDentalRecord(req: Request, res: Response): Promise<void> {
    try {
      const { id, recordId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const dentalRecord = await PatientService.updateDentalRecord(
        id,
        recordId,
        req.body,
        userId
      );
      res.json({ success: true, data: dentalRecord });
    } catch (error: any) {
      console.error('Update dental record error:', error);
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('not found') ? 404 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Post(':id/dental-records')
  @Middleware(auth)
  async addDentalRecord(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const dentalRecord = await PatientService.addDentalRecord({
        patientId: id,
        ...req.body
      }, userId);
      res.status(201).json({ success: true, data: dentalRecord });
    } catch (error: any) {
      console.error('Add dental record error:', error);
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Post(':id/test-results')
  @Middleware(auth)
  async addTestResult(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const testResult = await PatientService.addTestResult({
        patientId: id,
        ...req.body
      }, userId);

      res.status(201).json({ success: true, data: testResult });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('Blob') ? 400 :
            error.message.includes('not supported') ? 400 :
          error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Put(':id/test-results/:resultId')
  @Middleware(auth)
  async updateTestResult(req: Request, res: Response): Promise<void> {
    try {
      const { id, resultId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const testResult = await PatientService.updateTestResult(id, resultId, req.body, userId);
      res.json({ success: true, data: testResult });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('Blob') ? 400 :
            error.message.includes('not supported') ? 400 :
              error.message.includes('not found') ? 404 :
                error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Delete(':id/test-results/:resultId')
  @Middleware(auth)
  async deleteTestResult(req: Request, res: Response): Promise<void> {
    try {
      const { id, resultId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      await PatientService.deleteTestResult(id, resultId, userId);
      res.json({ success: true });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('not found') ? 404 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Post(':id/documents')
  @Middleware(auth)
  async addDocument(req: Request, res: Response): Promise<void> {
    try {
      const { id } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const document = await PatientService.addDocument({
        patientId: id,
        ...req.body
      }, userId);

      res.status(201).json({ success: true, data: document });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('Blob') ? 400 :
            error.message.includes('not supported') ? 400 :
          error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Put(':id/documents/:documentId')
  @Middleware(auth)
  async updateDocument(req: Request, res: Response): Promise<void> {
    try {
      const { id, documentId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      const document = await PatientService.updateDocument(id, documentId, req.body, userId);
      res.json({ success: true, data: document });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('Blob') ? 400 :
            error.message.includes('not supported') ? 400 :
              error.message.includes('not found') ? 404 :
                error.message.includes('required') ? 400 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }

  @Delete(':id/documents/:documentId')
  @Middleware(auth)
  async deleteDocument(req: Request, res: Response): Promise<void> {
    try {
      const { id, documentId } = req.params;
      const userId = (req as AuthRequest).user.userId;

      await PatientService.deleteDocument(id, documentId, userId);
      res.json({ success: true });
    } catch (error: any) {
      const statusCode = error.message.includes('must be a doctor') ? 403 :
        error.message.includes('not your patient') ? 403 :
          error.message.includes('not found') ? 404 : 500;
      res.status(statusCode).json({ success: false, error: error.message });
    }
  }
}

export default new PatientController();
