local openidc = require("resty.openidc")
local http = require("resty.http")
local cjson = require("cjson")

local client_secret = os.getenv("KEYCLOAK_CLIENT_SECRET")
if not client_secret then
  ngx.log(ngx.ERR, "Missing KEYCLOAK_CLIENT_SECRET env variable")
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

local opts = {
  redirect_uri_path = "/redirect_uri",
  discovery = "https://kc.boomlab.party/realms/rhein-sw/.well-known/openid-configuration",
  client_id = "demo-sso",
  client_secret = client_secret,
  scope = "openid email profile",
  ssl_verify = "no"
}

-- Step 1: login flow
local auth_res, auth_err = openidc.authenticate(opts)
if auth_err then
  ngx.status = 403
  ngx.say("Authentication failed: " .. auth_err)
  ngx.exit(ngx.HTTP_FORBIDDEN)
end

-- Step 2: get token from session or result
local session = require("resty.session").start()
local access_token = session.data.access_token or auth_res.access_token

if not access_token then
  ngx.status = 401
  ngx.say("Access token not available")
  ngx.exit(ngx.HTTP_UNAUTHORIZED)
end

-- Step 3: validate token on each request via introspection
local httpc = http.new()
local res, err = httpc:request_uri("https://kc.boomlab.party/realms/rhein-sw/protocol/openid-connect/token/introspect", {
  method = "POST",
  body = "token=" .. access_token .. "&client_id=" .. opts.client_id .. "&client_secret=" .. opts.client_secret,
  headers = {
    ["Content-Type"] = "application/x-www-form-urlencoded"
  },
  ssl_verify = false,
})

if not res or res.status ~= 200 then
  ngx.status = 500
  ngx.say("Failed to introspect token: " .. (err or (res and res.body or "unknown error")))
  ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

local token_info = cjson.decode(res.body)
if not token_info.active then
  local session = require("resty.session").start()
  session:destroy()
  return openidc.authenticate(opts)
end

-- Step 4: allow proxying the request
ngx.req.set_header("X-User", auth_res.user.preferred_username or "")
ngx.req.set_header("X-Email", auth_res.user.email or "")
-- Don't return anything here — let NGINX continue to proxy the request
