import { getEnv } from './infrastructure/config/env'
import Fastify, { type FastifyInstance } from 'fastify'
import helmet from '@fastify/helmet'
import cors from '@fastify/cors'
import rateLimit from '@fastify/rate-limit'
import cookie from '@fastify/cookie'
import { createContainer } from './infrastructure/container'
import { registerErrorHandler } from './infrastructure/http/plugins/error-handler'
import { authRoutes } from './infrastructure/http/routes/auth'
import { disconnectPrisma } from './infrastructure/db/prisma'

const env = getEnv()

function buildLogger() {
  if (env.NODE_ENV !== 'production') {
    return {
      transport: {
        target: 'pino-pretty',
        options: { colorize: true },
      },
    }
  }
  return true
}

function buildServer(): FastifyInstance {
  return Fastify({ logger: buildLogger() })
}

const server = buildServer()

async function bootstrap(): Promise<void> {
  // Seguridad: cabeceras HTTP
  await server.register(helmet)

  // CORS restringido a los dominios del POS y la tienda
  await server.register(cors, {
    origin: env.CORS_ORIGINS.split(',').filter(Boolean),
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
  })

  // Rate limiting global (100 req/min). Las rutas /auth tienen límites más estrictos.
  await server.register(rateLimit, {
    max: 100,
    timeWindow: '1 minute',
    keyGenerator: (request) => request.ip,
  })

  // Cookie plugin (necesario para el refresh token HttpOnly)
  await server.register(cookie)

  // Error handler centralizado
  registerErrorHandler(server)

  const container = createContainer(env)

  // Rutas
  server.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() }))

  await server.register(authRoutes, { prefix: '/auth', container })

  // Graceful shutdown
  const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM']
  for (const signal of signals) {
    process.once(signal, () => {
      void server.close().then(() => disconnectPrisma()).then(() => process.exit(0))
    })
  }

  await server.listen({ port: env.PORT, host: '127.0.0.1' })
}

bootstrap().catch((err: unknown) => {
  server.log.error(err)
  process.exit(1)
})
