import { authenticate } from '../../plugins/auth.js'
import { getCcUserById } from '../../services/cc-user.service.js'
import {
  signInCcUser,
  refreshTokens,
  logout,
} from '../../services/auth.service.js'
import { UserType } from '../../constants.js'

const REFRESH_COOKIE_NAME = 'cc_refresh_token'

const extractDeviceInfo = (request) => ({
  user_agent: request.headers['user-agent'] || null,
  ip: request.ip || null,
})

const sendAuthError = (reply, err) => {
  if (!err.statusCode) reply.request.log.error({ err }, 'Unhandled auth error')
  return reply.code(err.statusCode || 500).send({
    success: false,
    error: {
      code: err.code || 'INTERNAL',
      message: err.message,
      ...(err.details && { details: err.details }),
    },
  })
}

const cookieOpts = () => ({
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',
  path: '/',
})

const setRefreshCookie = (reply, refreshToken, expiresAt) => {
  reply.setCookie(REFRESH_COOKIE_NAME, refreshToken, {
    ...cookieOpts(),
    expires: new Date(expiresAt),
  })
}

const clearRefreshCookie = (reply) => {
  reply.clearCookie(REFRESH_COOKIE_NAME, cookieOpts())
}

export const internalAuthRoutes = async (app) => {
  app.post('/login', async (request, reply) => {
    const { email, password } = request.body || {}
    if (!email || !password) {
      return reply.code(422).send({
        success: false,
        error: { code: 'VALIDATION_ERROR', message: 'email and password are required' },
      })
    }
    try {
      const { tokens, profile } = await signInCcUser({
        email,
        password,
        deviceInfo: extractDeviceInfo(request),
      })
      setRefreshCookie(reply, tokens.refresh_token, tokens.refresh_token_expires_at)
      return reply.send({
        success: true,
        data: {
          access_token: tokens.access_token,
          access_token_expires_in: tokens.access_token_expires_in,
          profile,
        },
      })
    } catch (err) {
      return sendAuthError(reply, err)
    }
  })

  app.post('/refresh', async (request, reply) => {
    const refreshToken = request.cookies?.[REFRESH_COOKIE_NAME]
    if (!refreshToken) {
      return reply.code(401).send({
        success: false,
        error: { code: 'REFRESH_MISSING', message: 'Refresh token missing' },
      })
    }
    try {
      const { tokens, profile } = await refreshTokens({
        refreshToken,
        deviceInfo: extractDeviceInfo(request),
      })
      setRefreshCookie(reply, tokens.refresh_token, tokens.refresh_token_expires_at)
      return reply.send({
        success: true,
        data: {
          access_token: tokens.access_token,
          access_token_expires_in: tokens.access_token_expires_in,
          profile,
        },
      })
    } catch (err) {
      clearRefreshCookie(reply)
      return sendAuthError(reply, err)
    }
  })

  app.post('/logout', { preHandler: authenticate }, async (request, reply) => {
    await logout({ sessionId: request.auth.sessionId })
    clearRefreshCookie(reply)
    return reply.send({ success: true })
  })

  app.get('/me', { preHandler: authenticate }, async (request, reply) => {
    if (request.auth.userType !== UserType.CC_USER) {
      return reply.code(403).send({
        success: false,
        error: { code: 'FORBIDDEN', message: 'Control center account required' },
      })
    }
    const user = await getCcUserById(request.auth.userId)
    if (!user) {
      return reply.code(404).send({
        success: false,
        error: { code: 'NOT_FOUND', message: 'Control center account not found' },
      })
    }
    return reply.send({
      success: true,
      data: {
        id: user.id,
        email: user.email,
        display_name: user.display_name,
        role: user.role,
      },
    })
  })
}
