import { FastifyInstance } from "fastify"
import fp from "fastify-plugin"
import jwt from "jsonwebtoken"
import { secrets } from "../utils/secrets"

import {
    authUserRoles,
    authRolePermissions,
    authUsers,
} from "../../db/schema"

import { eq, and } from "drizzle-orm"

export default fp(async (server: FastifyInstance) => {
    server.addHook("preHandler", async (req, reply) => {
        // 1️⃣ Token aus Header oder Cookie lesen
        const cookieToken = req.cookies?.token
        const authHeader = req.headers.authorization

        const headerToken =
            authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null

        const token =
            headerToken && headerToken.length > 10
                ? headerToken
                : cookieToken || null

        if (!token) {
            return reply.code(401).send({ error: "Authentication required" })
        }

        try {
            // 2️⃣ JWT verifizieren
            const payload = jwt.verify(token, secrets.JWT_SECRET!) as {
                user_id: string
                email: string
                tenant_id: number | null
            }

            if (!payload?.user_id) {
                return reply.code(401).send({ error: "Invalid token" })
            }

            // Payload an Request hängen
            req.user = payload

            const [currentUser] = await server.db
                .select({
                    is_admin: authUsers.is_admin,
                })
                .from(authUsers)
                .where(eq(authUsers.id, payload.user_id))
                .limit(1)

            req.user.is_admin = Boolean(currentUser?.is_admin)

            // Multi-Tenant Modus ohne ausgewählten Tenant → keine Rollenprüfung
            if (!req.user.tenant_id) {
                return
            }

            const tenantId = req.user.tenant_id
            const userId = req.user.user_id

            // --------------------------------------------------------
            // 3️⃣ Rolle des Nutzers im Tenant holen
            // --------------------------------------------------------
            const roleRows = await server.db
                .select()
                .from(authUserRoles)
                .where(
                    and(
                        eq(authUserRoles.user_id, userId),
                        eq(authUserRoles.tenant_id, tenantId)
                    )
                )
                .limit(1)

            if (roleRows.length === 0) {
                if (req.user.is_admin) {
                    req.role = ""
                    req.permissions = []
                    req.hasPermission = () => false
                    return
                }

                return reply
                    .code(403)
                    .send({ error: "No role assigned for this tenant" })
            }

            const roleId = roleRows[0].role_id

            // --------------------------------------------------------
            // 4️⃣ Berechtigungen der Rolle laden
            // --------------------------------------------------------
            const permissionRows = await server.db
                .select()
                .from(authRolePermissions)
                .where(eq(authRolePermissions.role_id, roleId))

            const permissions = permissionRows.map((p) => p.permission)

            // --------------------------------------------------------
            // 5️⃣ An Request hängen für spätere Nutzung
            // --------------------------------------------------------
            req.role = roleId
            req.permissions = permissions
            req.hasPermission = (perm: string) => permissions.includes(perm)

        } catch (err) {
            console.error("JWT verification error:", err)
            return reply.code(401).send({ error: "Invalid or expired token" })
        }
    })
})

// ---------------------------------------------------------------------------
// Fastify TypeScript Erweiterungen
// ---------------------------------------------------------------------------

declare module "fastify" {
    interface FastifyRequest {
        user: {
            user_id: string
            email: string
            tenant_id: number | null
            is_admin?: boolean
        }
        role: string
        permissions: string[]
        hasPermission: (permission: string) => boolean
    }
}
