import express from 'express';
import { PrismaClient } from '@prisma/client';
import multer from 'multer';
import path from 'path';
import jwt from 'jsonwebtoken';
import { requireAuth, requireSysAdmin, requireOfficerOrAdmin } from '../middleware/auth';

const router = express.Router();
const prisma = new PrismaClient();
const JWT_SECRET = process.env.JWT_SECRET || 'ahri_super_secret_key_change_in_production';

// Multer Setup
const storage = multer.diskStorage({
  destination: 'uploads/',
  filename: (req, file, cb) => {
    cb(null, `${Date.now()}-${file.originalname}`);
  }
});

const upload = multer({ 
  storage,
  limits: { fileSize: 50 * 1024 * 1024 }, // 50MB limit for videos
  fileFilter: (req, file, cb) => {
    const filetypes = /jpeg|jpg|png|webp|mp4|webm|quicktime|mov/;
    const mimetype = filetypes.test(file.mimetype);
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    if (mimetype && extname) return cb(null, true);
    cb(new Error('Only images and videos are allowed'));
  }
});

// Upload endpoint (sys admin only — used when creating/editing rooms)
router.post(
  '/upload',
  requireAuth,
  requireSysAdmin,
  upload.fields([{ name: 'photos', maxCount: 5 }, { name: 'video', maxCount: 1 }]),
  (req, res) => {
    const files = req.files as { [fieldname: string]: Express.Multer.File[] };

    const photoUrls = files['photos']?.map((file) => `/uploads/${file.filename}`) || [];
    const videoUrl = files['video']?.[0] ? `/uploads/${files['video'][0].filename}` : null;

    res.json({ photoUrls, videoUrl });
  }
);

// Get all meeting rooms
router.get('/', async (req, res) => {
  try {
    const { date, startTime, endTime } = req.query;
    let filter: any = {};

    // Check authorization to see if we should include hidden rooms
    let showHidden = false;
    const header = req.headers.authorization;
    if (header?.startsWith('Bearer ')) {
      const token = header.slice(7);
      try {
        const decoded = jwt.verify(token, JWT_SECRET) as any;
        if (decoded && (decoded.role === 'SYS_ADMIN' || decoded.role === 'OFFICER')) {
          showHidden = true;
        }
      } catch (_) {
        // Ignore invalid token and default to public view
      }
    }

    if (!showHidden) {
      filter.isHidden = false;
    }

    if (date && startTime && endTime) {
      const start = new Date(String(startTime));
      const end = new Date(String(endTime));
      const dateObj = new Date(String(date));
      if (isNaN(start.getTime()) || isNaN(end.getTime()) || isNaN(dateObj.getTime())) {
        // Invalid date parameters – ignore the availability filter
        console.warn('Invalid date parameters supplied to /api/rooms');
      } else {
        filter = {
          ...filter,
          bookings: {
            none: {
              date: dateObj,
              status: { in: ['PENDING', 'APPROVED'] },
              OR: [{ startTime: { lt: end }, endTime: { gt: start } }]
            }
          }
        };
      }
    }

    const rooms = await prisma.meetingRoom.findMany({
      where: filter
    });
    res.json(rooms);
  } catch (error) {
    console.error('Fetch rooms error:', error);
    res.status(500).json({ error: 'Failed to fetch rooms' });
  }
});

// Get a single meeting room
router.get('/:id', async (req, res) => {
  try {
    const room = await prisma.meetingRoom.findUnique({ where: { id: req.params.id } });
    if (!room) return res.status(404).json({ error: 'Room not found' });
    res.json(room);
  } catch (error) {
    console.error('Fetch room error:', error);
    res.status(500).json({ error: 'Failed to fetch room' });
  }
});

// Create a room (sys admin only)
router.post('/', requireAuth, requireSysAdmin, async (req, res) => {
  try {
    const data = req.body;
    const room = await prisma.meetingRoom.create({ data });
    res.status(201).json(room);
  } catch (error) {
    console.error('Create room error:', error);
    res.status(500).json({ error: 'Failed to create room' });
  }
});

// Update a room (sys admin only)
router.put('/:id', requireAuth, requireSysAdmin, async (req, res) => {
  try {
    const data = req.body;
    const room = await prisma.meetingRoom.update({
      where: { id: String(req.params.id) },
      data,
    });
    res.json(room);
  } catch (error) {
    console.error('Update room error:', error);
    res.status(500).json({ error: 'Failed to update room' });
  }
});

// Update room status (isFrozen, isHidden, frozenReason) - Officer or Admin
router.patch('/:id/status', requireAuth, requireOfficerOrAdmin, async (req, res) => {
  try {
    const { isFrozen, isHidden, frozenReason } = req.body;
    const updateData: any = {};
    if (isFrozen !== undefined) updateData.isFrozen = isFrozen;
    if (isHidden !== undefined) updateData.isHidden = isHidden;
    if (isFrozen === false) {
      updateData.frozenReason = null;
    } else if (frozenReason !== undefined) {
      updateData.frozenReason = frozenReason;
    }

    const room = await prisma.meetingRoom.update({
      where: { id: String(req.params.id) },
      data: updateData,
    });
    res.json(room);
  } catch (error) {
    console.error('Update room status error:', error);
    res.status(500).json({ error: 'Failed to update room status' });
  }
});

// Delete a room (sys admin only)
router.delete('/:id', requireAuth, requireSysAdmin, async (req, res) => {
  try {
    const roomId = String(req.params.id);

    const room = await prisma.meetingRoom.findUnique({
      where: { id: roomId },
      select: { id: true, name: true },
    });

    if (!room) {
      return res.status(404).json({ error: 'Room not found' });
    }

    const [, deletedRoom] = await prisma.$transaction([
      prisma.booking.deleteMany({ where: { roomId } }),
      prisma.meetingRoom.delete({ where: { id: roomId } }),
    ]);

    res.json({
      message: 'Room and related bookings deleted successfully',
      room: deletedRoom,
    });
  } catch (error: any) {
    console.error('Delete room error:', error);
    res.status(500).json({ error: error?.message || 'Failed to delete room' });
  }
});

export default router;
