// routes/auth.js
const express = require("express")
const router = express.Router()

const requireAuth = require("../middleware/requireAuth.js")
const { validate } = require("../middleware/validate.middleware")
const authService = require("../services/auth.service")
const { endpoints } = require("@shared/contracts")

const { mapLoginRequestToLoginInput, mapLoginResultToResponse } = require("../adapters/responses/login.adapter")
const { mapRegisterRequestToRegisterInput, mapRegisterResultToResponse } = require("../adapters/responses/register.adapter")
const { mapMeRequestToUserId, mapMeResultToResponse } = require("../adapters/responses/me.adapter")

const { auth } = endpoints

// NOT: app.js’de cookie-parser olmali:
// const cookieParser = require("cookie-parser")
// app.use(cookieParser())

function getCookieOptions() {
  const isProd = process.env.NODE_ENV === "production"
  return {
    httpOnly: true,
    secure: isProd,
    sameSite: "lax",
    path: "/",
  }
}

function parseExpiresInToMs(value) {
  if (!value) return 15 * 60 * 1000
  if (typeof value === "number" && Number.isFinite(value)) return value * 1000
  const str = String(value).trim().toLowerCase()
  const match = str.match(/^(\d+)(ms|s|m|h|d)?$/)
  if (!match) return 15 * 60 * 1000
  const n = Number(match[1])
  const unit = match[2] || "s"
  const mult =
    unit === "ms" ? 1 :
    unit === "s" ? 1000 :
    unit === "m" ? 60 * 1000 :
    unit === "h" ? 60 * 60 * 1000 :
    unit === "d" ? 24 * 60 * 60 * 1000 :
    1000
  return n * mult
}

function setRefreshCookie(res, refreshToken) {
  const opts = getCookieOptions()
  const maxAgeMs = Number(process.env.REFRESH_COOKIE_MAX_AGE_MS || 1000 * 60 * 60 * 24 * 30)
  res.cookie("rt", refreshToken, { ...opts, maxAge: maxAgeMs })
}

function setAccessCookie(res, accessToken) {
  const opts = getCookieOptions()
  const maxAgeMs = parseExpiresInToMs(process.env.ACCESS_TOKEN_EXPIRES_IN || "15m")
  res.cookie("at", accessToken, { ...opts, maxAge: maxAgeMs })
}

function clearRefreshCookie(res) {
  const opts = getCookieOptions()
  res.clearCookie("rt", { ...opts })
}

function clearAccessCookie(res) {
  const opts = getCookieOptions()
  res.clearCookie("at", { ...opts })
}

router.post(
  "/register",
  validate(auth.registerRequestSchema, "body", "validatedRegisterInput"),
  async (req, res) => {
    try {
      const input = mapRegisterRequestToRegisterInput(req.validatedRegisterInput)

      const result = await authService.register({
        ...input,
        meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null },
      })

      // refresh + access cookie set
      if (result.refreshToken) setRefreshCookie(res, result.refreshToken)
      if (result.accessToken) setAccessCookie(res, result.accessToken)

      const response = auth.authResponseSchema.parse(mapRegisterResultToResponse(result))
      res.json(response)
    } catch (err) {
      const status = err.statusCode || 500
      res.status(status).json({ message: err.message || "Kayit islemi basarisiz." })
    }
  }
)

router.post(
  "/login",
  validate(auth.loginRequestSchema, "body", "validatedLoginInput"),
  async (req, res) => {
    try {
      const input = mapLoginRequestToLoginInput(req.validatedLoginInput)

      const result = await authService.login({
        ...input,
        meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null },
      })

      // refresh + access cookie set
      setRefreshCookie(res, result.refreshToken)
      setAccessCookie(res, result.accessToken)

      const response = auth.authResponseSchema.parse(mapLoginResultToResponse(result))
      res.json(response)
    } catch (err) {
      const status = err.statusCode || 500
      res.status(status).json({
        message: err.statusCode ? err.message : "Giris islemi basarisiz.",
      })
    }
  }
)

router.post("/refresh", async (req, res) => {
  try {
    const refreshToken = req.cookies?.rt
    if (!refreshToken) return res.status(401).json({ message: "Refresh token yok" })

    const result = await authService.refresh({
      refreshToken,
      meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null },
    })

    // rotate -> yeni refresh + access cookie
    setRefreshCookie(res, result.refreshToken)
    setAccessCookie(res, result.accessToken)

    const response = auth.authResponseSchema.parse(mapLoginResultToResponse(result))
    res.json(response)
  } catch (err) {
    clearRefreshCookie(res)
    clearAccessCookie(res)
    const status = err.statusCode || 401
    res.status(status).json({ message: err.message || "Refresh basarisiz" })
  }
})

router.post("/logout", async (req, res) => {
  try {
    const refreshToken = req.cookies?.rt

    if (refreshToken) {
      await authService.logout({
        refreshToken,
        meta: { ip: req.ip, userAgent: req.headers["user-agent"] || null },
      })
    }

    clearRefreshCookie(res)
    clearAccessCookie(res)
    res.status(204).send()
  } catch (err) {
    clearRefreshCookie(res)
    clearAccessCookie(res)
    const status = err.statusCode || 500
    res.status(status).json({ message: err.message || "Cikis basarisiz" })
  }
})

router.get("/me", requireAuth, async (req, res) => {
  try {
    const userId = mapMeRequestToUserId(req)
    const user = await authService.getMe(userId)
    const response = auth.meResponseSchema.parse(mapMeResultToResponse(user))
    res.json(response)
  } catch (err) {
    const status = err.statusCode || 500
    res.status(status).json({ message: err.message || "Sunucu hatasi" })
  }
})

module.exports = router

