import { Router, type Request, type Response } from 'express'
import { z } from 'zod'
import { prisma } from '../../infra/database/prisma'

export function buildSectorRoutes(): Router {
  const router = Router()

  // GET /api/sectors
  router.get('/', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const sectors = await prisma.sector.findMany({
      where: { tenantId },
      orderBy: { name: 'asc' },
      include: { _count: { select: { teams: true, protocols: true } } },
    })
    res.json(sectors)
  })

  // POST /api/sectors
  router.post('/', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const schema = z.object({ name: z.string().min(1).max(100) })

    let body: z.infer<typeof schema>
    try { body = schema.parse(req.body) }
    catch (err: any) { res.status(400).json({ error: err.errors ?? err.message }); return }

    try {
      const sector = await prisma.sector.create({ data: { tenantId, name: body.name } })
      res.status(201).json(sector)
    } catch {
      res.status(409).json({ error: 'Setor com este nome já existe.' })
    }
  })

  // PATCH /api/sectors/:id
  router.patch('/:id', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const id = req.params['id'] as string
    const schema = z.object({
      name:     z.string().min(1).max(100).optional(),
      isActive: z.boolean().optional(),
    })

    let body: z.infer<typeof schema>
    try { body = schema.parse(req.body) }
    catch (err: any) { res.status(400).json({ error: err.errors ?? err.message }); return }

    const existing = await prisma.sector.findFirst({ where: { id, tenantId } })
    if (!existing) { res.status(404).json({ error: 'Setor não encontrado' }); return }

    const updated = await prisma.sector.update({ where: { id }, data: body })
    res.json(updated)
  })

  // DELETE /api/sectors/:id
  router.delete('/:id', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const id = req.params['id'] as string

    const existing = await prisma.sector.findFirst({ where: { id, tenantId } })
    if (!existing) { res.status(404).json({ error: 'Setor não encontrado' }); return }

    await prisma.team.deleteMany({ where: { sectorId: id } })
    await prisma.sector.delete({ where: { id } })
    res.status(204).send()
  })

  // GET /api/sectors/:id/teams
  router.get('/:id/teams', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const sectorId = req.params['id'] as string

    const teams = await prisma.team.findMany({
      where: { sectorId, tenantId },
      orderBy: { name: 'asc' },
      include: { _count: { select: { protocols: true } } },
    })
    res.json(teams)
  })

  // POST /api/sectors/:id/teams
  router.post('/:id/teams', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const sectorId = req.params['id'] as string
    const schema = z.object({ name: z.string().min(1).max(100) })

    let body: z.infer<typeof schema>
    try { body = schema.parse(req.body) }
    catch (err: any) { res.status(400).json({ error: err.errors ?? err.message }); return }

    const sector = await prisma.sector.findFirst({ where: { id: sectorId, tenantId } })
    if (!sector) { res.status(404).json({ error: 'Setor não encontrado' }); return }

    try {
      const team = await prisma.team.create({ data: { tenantId, sectorId, name: body.name } })
      res.status(201).json(team)
    } catch {
      res.status(409).json({ error: 'Equipe com este nome já existe neste setor.' })
    }
  })

  // PATCH /api/sectors/:sectorId/teams/:teamId
  router.patch('/:sectorId/teams/:teamId', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const teamId   = req.params['teamId'] as string
    const schema = z.object({
      name:     z.string().min(1).max(100).optional(),
      isActive: z.boolean().optional(),
    })

    let body: z.infer<typeof schema>
    try { body = schema.parse(req.body) }
    catch (err: any) { res.status(400).json({ error: err.errors ?? err.message }); return }

    const existing = await prisma.team.findFirst({ where: { id: teamId, tenantId } })
    if (!existing) { res.status(404).json({ error: 'Equipe não encontrada' }); return }

    const updated = await prisma.team.update({ where: { id: teamId }, data: body })
    res.json(updated)
  })

  // DELETE /api/sectors/:sectorId/teams/:teamId
  router.delete('/:sectorId/teams/:teamId', async (req: Request, res: Response) => {
    const tenantId = req.tenantId!
    const teamId   = req.params['teamId'] as string

    const existing = await prisma.team.findFirst({ where: { id: teamId, tenantId } })
    if (!existing) { res.status(404).json({ error: 'Equipe não encontrada' }); return }

    await prisma.team.delete({ where: { id: teamId } })
    res.status(204).send()
  })

  return router
}
