import type { FastifyRequest, FastifyReply } from 'fastify'
import type { ITokenService } from '../../../domain/ports/token-service'
import type { UserRole } from '../../../domain/entities/user'
import { AppError } from '../../../domain/errors/app-error'

export interface CurrentUser {
  id: string
  role: UserRole
}

// Augmentación del tipo de request para incluir currentUser
declare module 'fastify' {
  interface FastifyRequest {
    currentUser: CurrentUser | undefined
  }
}

type PreHandlerFn = (request: FastifyRequest, reply: FastifyReply) => Promise<void>

export function createAuthGuard(tokenService: ITokenService, allowedRoles: UserRole[]): PreHandlerFn {
  return async function authGuard(request: FastifyRequest, reply: FastifyReply): Promise<void> {
    const authHeader = request.headers['authorization']

    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return reply
        .status(401)
        .send({ error: { code: 'UNAUTHORIZED', message: 'Se requiere autenticación' } })
    }

    const token = authHeader.slice(7)

    let payload: ReturnType<ITokenService['verifyAccessToken']>
    try {
      payload = tokenService.verifyAccessToken(token)
    } catch (err) {
      if (err instanceof AppError) {
        return reply.status(err.httpStatus).send({ error: { code: err.code, message: err.message } })
      }
      return reply.status(401).send({ error: { code: 'UNAUTHORIZED', message: 'Token inválido' } })
    }

    if (!allowedRoles.includes(payload.role)) {
      return reply
        .status(403)
        .send({ error: { code: 'FORBIDDEN', message: 'Sin permisos suficientes para esta operación' } })
    }

    request.currentUser = { id: payload.userId, role: payload.role }
  }
}

export function requireCurrentUser(request: FastifyRequest): CurrentUser {
  if (!request.currentUser) {
    throw new AppError('UNAUTHORIZED', 401, 'Se requiere autenticación')
  }
  return request.currentUser
}
