import fp from 'fastify-plugin'
import { FastifyPluginAsync, FastifyRequest } from 'fastify'

export interface QueryConfigPagination {
    page: number
    limit: number
    offset: number
}

export interface QueryConfigSort {
    field: string
    direction: 'asc' | 'desc'
}

export interface QueryConfig {
    pagination: QueryConfigPagination | null
    sort: QueryConfigSort[]
    filters: Record<string, string>
    paginationDisabled: boolean
}

declare module 'fastify' {
    interface FastifyRequest {
        queryConfig: QueryConfig
    }
}

interface QueryConfigPluginOptions {
    routes?: string[]
}

function matchRoutePattern(currentPath: string, patterns: string[]): boolean {
    return patterns.some(pattern => {
        // Beispiel: /users/:id -> /^\/users\/[^/]+$/
        const regex = new RegExp(
            '^' +
            pattern
                .replace(/\*/g, '.*') // wildcard
                .replace(/:[^/]+/g, '[^/]+') +
            '$'
        )
        return regex.test(currentPath)
    })
}

const queryConfigPlugin: FastifyPluginAsync<QueryConfigPluginOptions> = async (
    fastify,
    opts
) => {
    const routePatterns = opts.routes || []

    fastify.addHook('preHandler', async (req: FastifyRequest, reply) => {
        const path = req.routeOptions.url || req.raw.url || ''

        if (!matchRoutePattern(path, routePatterns)) {
            return
        }

        const query = req.query as Record<string, any>

        // Pagination deaktivieren?
        const disablePagination =
            query.noPagination === 'true' ||
            query.pagination === 'false' ||
            query.limit === '0'

        // Pagination berechnen
        let pagination: QueryConfigPagination | null = null
        if (!disablePagination) {
            const page = Math.max(parseInt(query.page) || 1, 1)
            const limit = Math.max(parseInt(query.limit) || 25, 1)
            const offset = (page - 1) * limit
            pagination = { page, limit, offset }
        }

        // Sortierung
        const sort: QueryConfigSort[] = []
        if (typeof query.sort === 'string') {
            const items = query.sort.split(',')
            for (const item of items) {
                const [field, direction] = item.split(':')
                sort.push({
                    field: field.trim(),
                    direction: (direction || 'asc').toLowerCase() === 'desc' ? 'desc' : 'asc'
                })
            }
        }

        // Filterung
        const filters: Record<string, any> = {}

        for (const [key, value] of Object.entries(query)) {
            const match = key.match(/^filter\[(.+)\]$/)
            if (!match) continue

            const filterKey = match[1]

            if (typeof value === 'string') {
                // Split bei Komma → mehrere Werte
                const parts = value.split(',').map(v => v.trim()).filter(Boolean)

                // Automatische Typkonvertierung je Element
                const parsedValues = parts.map(v => {
                    if (v === 'true') return true
                    if (v === 'false') return false
                    if (v === 'null') return null
                    return v
                })

                filters[filterKey] = parsedValues.length > 1 ? parsedValues : parsedValues[0]
            }
        }

        req.queryConfig = {
            pagination,
            sort,
            filters,
            paginationDisabled: disablePagination
        }
    })
}

export default fp(queryConfigPlugin, { name: 'query-config' })
