import { Router, Response } from 'express'
import { db } from '../config/database'
import { authenticateToken, AuthRequest } from '../middleware/auth'
import { v4 as uuidv4 } from 'uuid'
import { Booking, BookingRequest } from '@skillmate/shared'

const router = Router()

// Get user's bookings
router.get('/my-bookings', authenticateToken, (req: AuthRequest, res: Response) => {
  try {
    const { status, from_date, to_date } = req.query
    let query = `
      SELECT b.*, w.name as workspace_name, w.type as workspace_type, 
             w.floor, w.building, e.first_name, e.last_name, e.photo
      FROM bookings b
      JOIN workspaces w ON b.workspace_id = w.id
      JOIN employees e ON b.employee_id = e.id
      WHERE b.user_id = ?
    `
    const params: any[] = [req.user!.id]

    if (status) {
      query += ' AND b.status = ?'
      params.push(status)
    }

    if (from_date) {
      query += ' AND b.start_time >= ?'
      params.push(from_date)
    }

    if (to_date) {
      query += ' AND b.end_time <= ?'
      params.push(to_date)
    }

    query += ' ORDER BY b.start_time DESC'

    const bookings = db.prepare(query).all(...params)

    res.json(bookings)
  } catch (error) {
    console.error('Error fetching bookings:', error)
    res.status(500).json({ error: 'Failed to fetch bookings' })
  }
})

// Get all bookings (admin/superuser)
router.get('/', authenticateToken, (req: AuthRequest, res: Response) => {
  if (!['admin', 'superuser'].includes(req.user!.role)) {
    return res.status(403).json({ error: 'Insufficient permissions' })
  }

  try {
    const { workspace_id, user_id, status, from_date, to_date } = req.query
    let query = `
      SELECT b.*, w.name as workspace_name, w.type as workspace_type, 
             w.floor, w.building, e.first_name, e.last_name, e.photo,
             u.username
      FROM bookings b
      JOIN workspaces w ON b.workspace_id = w.id
      JOIN employees e ON b.employee_id = e.id
      JOIN users u ON b.user_id = u.id
      WHERE 1=1
    `
    const params: any[] = []

    if (workspace_id) {
      query += ' AND b.workspace_id = ?'
      params.push(workspace_id)
    }

    if (user_id) {
      query += ' AND b.user_id = ?'
      params.push(user_id)
    }

    if (status) {
      query += ' AND b.status = ?'
      params.push(status)
    }

    if (from_date) {
      query += ' AND b.start_time >= ?'
      params.push(from_date)
    }

    if (to_date) {
      query += ' AND b.end_time <= ?'
      params.push(to_date)
    }

    query += ' ORDER BY b.start_time DESC'

    const bookings = db.prepare(query).all(...params)

    res.json(bookings)
  } catch (error) {
    console.error('Error fetching bookings:', error)
    res.status(500).json({ error: 'Failed to fetch bookings' })
  }
})

// Create booking
router.post('/', authenticateToken, (req: AuthRequest, res: Response) => {
  try {
    const bookingRequest: BookingRequest = req.body
    const { workspace_id, start_time, end_time, notes, recurring } = bookingRequest

    if (!workspace_id || !start_time || !end_time) {
      return res.status(400).json({ error: 'Missing required fields' })
    }

    // Check if workspace exists and is active
    const workspace = db.prepare('SELECT * FROM workspaces WHERE id = ? AND is_active = 1').get(workspace_id)
    if (!workspace) {
      return res.status(404).json({ error: 'Workspace not found or inactive' })
    }

    // Check for conflicts
    const conflict = db.prepare(`
      SELECT COUNT(*) as count FROM bookings
      WHERE workspace_id = ? AND status = 'confirmed'
      AND (
        (start_time <= ? AND end_time > ?)
        OR (start_time < ? AND end_time >= ?)
        OR (start_time >= ? AND end_time <= ?)
      )
    `).get(workspace_id, start_time, start_time, end_time, end_time, start_time, end_time)

    if ((conflict as any).count > 0) {
      return res.status(409).json({ error: 'Time slot already booked' })
    }

    // Check booking rules
    const rules = db.prepare('SELECT * FROM booking_rules WHERE workspace_type = ?').get((workspace as any).type)
    if (rules) {
      // Validate against rules
      const startDate = new Date(start_time)
      const endDate = new Date(end_time)
      const now = new Date()
      
      // Check max duration
      if ((rules as any).max_duration_hours) {
        const durationHours = (endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60)
        if (durationHours > (rules as any).max_duration_hours) {
          return res.status(400).json({ 
            error: `Maximum booking duration is ${(rules as any).max_duration_hours} hours` 
          })
        }
      }

      // Check advance booking limits
      if ((rules as any).max_advance_days) {
        const daysInAdvance = (startDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)
        if (daysInAdvance > (rules as any).max_advance_days) {
          return res.status(400).json({ 
            error: `Cannot book more than ${(rules as any).max_advance_days} days in advance` 
          })
        }
      }

      if ((rules as any).min_advance_hours) {
        const hoursInAdvance = (startDate.getTime() - now.getTime()) / (1000 * 60 * 60)
        if (hoursInAdvance < (rules as any).min_advance_hours) {
          return res.status(400).json({ 
            error: `Must book at least ${(rules as any).min_advance_hours} hours in advance` 
          })
        }
      }
    }

    const bookingId = uuidv4()
    const now = new Date().toISOString()

    db.prepare(`
      INSERT INTO bookings (
        id, workspace_id, user_id, employee_id, start_time, end_time,
        status, notes, created_at, updated_at
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `).run(
      bookingId, workspace_id, req.user!.id, req.user!.employeeId,
      start_time, end_time, 'confirmed', notes, now, now
    )

    // Handle recurring bookings
    if (recurring) {
      const recurringId = uuidv4()
      const startDate = new Date(start_time)
      const startTimeOnly = startDate.toTimeString().substring(0, 8)
      const endTimeOnly = new Date(end_time).toTimeString().substring(0, 8)

      db.prepare(`
        INSERT INTO recurring_bookings (
          id, workspace_id, user_id, employee_id, start_date, end_date,
          time_start, time_end, days_of_week, created_at
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `).run(
        recurringId, workspace_id, req.user!.id, req.user!.employeeId,
        start_time, recurring.end_date, startTimeOnly, endTimeOnly,
        JSON.stringify(recurring.days_of_week), now
      )

      // Create individual bookings for the recurring series
      // This is a simplified version - in production you'd want a background job
      createRecurringBookings(recurringId, bookingRequest, req.user)
    }

    const newBooking = db.prepare(`
      SELECT b.*, w.name as workspace_name, w.type as workspace_type
      FROM bookings b
      JOIN workspaces w ON b.workspace_id = w.id
      WHERE b.id = ?
    `).get(bookingId)

    res.status(201).json(newBooking)
  } catch (error) {
    console.error('Error creating booking:', error)
    res.status(500).json({ error: 'Failed to create booking' })
  }
})

// Check in to booking
router.post('/:id/check-in', authenticateToken, (req: AuthRequest, res: Response) => {
  try {
    const booking = db.prepare('SELECT * FROM bookings WHERE id = ? AND user_id = ?')
      .get(req.params.id, req.user!.id)

    if (!booking) {
      return res.status(404).json({ error: 'Booking not found' })
    }

    if ((booking as any).status !== 'confirmed') {
      return res.status(400).json({ error: 'Booking is not confirmed' })
    }

    const now = new Date()
    const startTime = new Date((booking as any).start_time)
    
    // Allow check-in 15 minutes before start time
    const earliestCheckIn = new Date(startTime.getTime() - 15 * 60 * 1000)
    
    if (now < earliestCheckIn) {
      return res.status(400).json({ error: 'Too early to check in' })
    }

    db.prepare(`
      UPDATE bookings 
      SET check_in_time = ?, updated_at = ?
      WHERE id = ?
    `).run(now.toISOString(), now.toISOString(), req.params.id)

    res.json({ message: 'Checked in successfully' })
  } catch (error) {
    console.error('Error checking in:', error)
    res.status(500).json({ error: 'Failed to check in' })
  }
})

// Check out from booking
router.post('/:id/check-out', authenticateToken, (req: AuthRequest, res: Response) => {
  try {
    const booking = db.prepare('SELECT * FROM bookings WHERE id = ? AND user_id = ?')
      .get(req.params.id, req.user!.id)

    if (!booking) {
      return res.status(404).json({ error: 'Booking not found' })
    }

    if (!(booking as any).check_in_time) {
      return res.status(400).json({ error: 'Not checked in' })
    }

    const now = new Date().toISOString()

    db.prepare(`
      UPDATE bookings 
      SET check_out_time = ?, status = 'completed', updated_at = ?
      WHERE id = ?
    `).run(now, now, req.params.id)

    res.json({ message: 'Checked out successfully' })
  } catch (error) {
    console.error('Error checking out:', error)
    res.status(500).json({ error: 'Failed to check out' })
  }
})

// Cancel booking
router.post('/:id/cancel', authenticateToken, (req: AuthRequest, res: Response) => {
  try {
    const booking = db.prepare('SELECT * FROM bookings WHERE id = ?').get(req.params.id)

    if (!booking) {
      return res.status(404).json({ error: 'Booking not found' })
    }

    // Users can only cancel their own bookings, admins can cancel any
    if ((booking as any).user_id !== req.user!.id && req.user!.role !== 'admin') {
      return res.status(403).json({ error: 'Not authorized to cancel this booking' })
    }

    if ((booking as any).status !== 'confirmed') {
      return res.status(400).json({ error: 'Booking is not confirmed' })
    }

    const now = new Date().toISOString()

    db.prepare(`
      UPDATE bookings 
      SET status = 'cancelled', updated_at = ?
      WHERE id = ?
    `).run(now, req.params.id)

    res.json({ message: 'Booking cancelled successfully' })
  } catch (error) {
    console.error('Error cancelling booking:', error)
    res.status(500).json({ error: 'Failed to cancel booking' })
  }
})

// Helper function to create recurring bookings
function createRecurringBookings(recurringId: string, request: BookingRequest, user: any) {
  // This is a simplified implementation
  // In production, this should be handled by a background job
  // to avoid timeout issues with many bookings
}

export default router