import { Router } from 'express'
import { requireCompanyAuth } from '../../middleware/requireCompanyAuth'
import { requireTenant } from '../../middleware/requireTenant'
import { requireSubscription } from '../../middleware/requireSubscription'
import { requireRole } from '../../middleware/requireRole'
import { parseBody, parseQuery, parseParams } from '../../http/validate'
import { ok, created } from '../../http/respond'
import { imageUpload, assertImageFiles } from '../../http/upload'
import * as service from './vehicle.service'
import {
  vehicleSchema, listQuerySchema, availabilityQuerySchema, calendarQuerySchema,
  calendarBlockSchema, maintenanceLogSchema, publishSchema, statusSchema,
  pricingConfigSchema, pricingRuleSchema,
  idParamSchema, photoIdxSchema, blockIdParamSchema, pricingRuleParamSchema,
} from './vehicle.schemas'

const router = Router()

router.use(requireCompanyAuth, requireTenant, requireSubscription)

router.get('/', async (req, res, next) => {
  try {
    const query = parseQuery(listQuerySchema, req)
    const result = await service.listVehicles(req.companyId, query)
    res.json(result)
  } catch (err) { next(err) }
})

router.post('/', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const body = parseBody(vehicleSchema, req)
    const vehicle = await service.createVehicle(body, req.companyId)
    created(res, vehicle)
  } catch (err) { next(err) }
})

router.get('/:id', async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const vehicle = await service.getVehicle(id, req.companyId)
    ok(res, vehicle)
  } catch (err) { next(err) }
})

router.patch('/:id', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const body = parseBody(vehicleSchema.partial(), req)
    const vehicle = await service.updateVehicle(id, req.companyId, body)
    ok(res, vehicle)
  } catch (err) { next(err) }
})

router.delete('/:id', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    await service.deleteVehicle(id, req.companyId)
    ok(res, { success: true })
  } catch (err) { next(err) }
})

router.post('/:id/photos', requireRole('MANAGER'), imageUpload.array('photos', 10), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const files = req.files as Express.Multer.File[]
    assertImageFiles(files)
    const updated = await service.uploadPhotos(id, req.companyId, files)
    ok(res, updated)
  } catch (err) { next(err) }
})

router.delete('/:id/photos/:idx', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id, idx } = parseParams(photoIdxSchema, req)
    const updated = await service.deletePhoto(id, req.companyId, parseInt(idx, 10))
    ok(res, updated)
  } catch (err) { next(err) }
})

router.patch('/:id/status', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const { status } = parseBody(statusSchema, req)
    ok(res, await service.setStatus(id, req.companyId, status))
  } catch (err) { next(err) }
})

router.patch('/:id/publish', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const { isPublished } = parseBody(publishSchema, req)
    await service.setPublished(id, req.companyId, isPublished)
    ok(res, { success: true, isPublished })
  } catch (err) { next(err) }
})

router.get('/:id/availability', async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const { startDate, endDate } = parseQuery(availabilityQuerySchema, req)
    const result = await service.checkAvailability(id, req.companyId, startDate, endDate)
    ok(res, result)
  } catch (err) { next(err) }
})

router.get('/:id/calendar', async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const { year, month } = parseQuery(calendarQuerySchema, req)
    const events = await service.getCalendar(id, req.companyId, year, month)
    ok(res, events)
  } catch (err) { next(err) }
})

router.post('/:id/calendar/blocks', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const body = parseBody(calendarBlockSchema, req)
    const block = await service.createCalendarBlock(id, req.companyId, body)
    created(res, block)
  } catch (err) { next(err) }
})

router.delete('/:id/calendar/blocks/:blockId', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id, blockId } = parseParams(blockIdParamSchema, req)
    await service.deleteCalendarBlock(id, req.companyId, blockId)
    ok(res, { success: true })
  } catch (err) { next(err) }
})

router.get('/:id/maintenance', async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const logs = await service.getMaintenanceLogs(id, req.companyId)
    ok(res, logs)
  } catch (err) { next(err) }
})

router.post('/:id/maintenance', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const body = parseBody(maintenanceLogSchema, req)
    const log = await service.createMaintenanceLog(id, req.companyId, body)
    created(res, log)
  } catch (err) { next(err) }
})

router.get('/:id/pricing', async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    ok(res, await service.getVehiclePricing(id, req.companyId))
  } catch (err) { next(err) }
})

router.put('/:id/pricing', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const body = parseBody(pricingConfigSchema, req)
    ok(res, await service.updateVehiclePricing(id, req.companyId, req.employee.id, body))
  } catch (err) { next(err) }
})

router.post('/:id/pricing/rules', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id } = parseParams(idParamSchema, req)
    const body = parseBody(pricingRuleSchema, req)
    created(res, await service.createVehiclePricingRule(id, req.companyId, req.employee.id, body))
  } catch (err) { next(err) }
})

router.patch('/:id/pricing/rules/:ruleId', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id, ruleId } = parseParams(pricingRuleParamSchema, req)
    const body = parseBody(pricingRuleSchema.partial(), req)
    ok(res, await service.updateVehiclePricingRule(id, req.companyId, ruleId, req.employee.id, body))
  } catch (err) { next(err) }
})

router.delete('/:id/pricing/rules/:ruleId', requireRole('MANAGER'), async (req, res, next) => {
  try {
    const { id, ruleId } = parseParams(pricingRuleParamSchema, req)
    ok(res, await service.deleteVehiclePricingRule(id, req.companyId, ruleId, req.employee.id))
  } catch (err) { next(err) }
})

export default router
