import { FastifyInstance } from "fastify"
import { and, eq, isNull, asc, inArray } from "drizzle-orm"
// WICHTIG: Hier müssen die Schemas der Entitäten importiert werden!
import {
    wikiPages,
    authUsers,
    // Bereits vorhanden
    customers,
    projects,
    plants,
    products,
    inventoryitems,
    customerinventoryitems,
    customerspaces,
    // NEU HINZUGEFÜGT (Basierend auf deinem DataStore)
    tasks,
    contacts,
    contracts,
    vehicles,
    vendors,
    spaces,
    inventoryitemgroups,
    services,
    hourrates,
    events,
    productcategories,
    servicecategories,
    ownaccounts
} from "../../db/schema/"

// Konfiguration: Welche Entitäten sollen im Wiki auftauchen?
const ENTITY_CONFIG: Record<string, { table: any, labelField: any, rootLabel: string, idField: 'id' | 'uuid' }> = {
    // --- BEREITS VORHANDEN ---
    'customers': { table: customers, labelField: customers.name, rootLabel: 'Kunden', idField: 'id' },
    'projects': { table: projects, labelField: projects.name, rootLabel: 'Projekte', idField: 'id' },
    'plants': { table: plants, labelField: plants.name, rootLabel: 'Objekte', idField: 'id' },
    'products': { table: products, labelField: products.name, rootLabel: 'Artikel', idField: 'id' },
    'inventoryitems': { table: inventoryitems, labelField: inventoryitems.name, rootLabel: 'Inventarartikel', idField: 'id' },
    'customerinventoryitems': { table: customerinventoryitems, labelField: customerinventoryitems.name, rootLabel: 'Kundeninventar', idField: 'id' },
    'customerspaces': { table: customerspaces, labelField: customerspaces.name, rootLabel: 'Kundenlagerplätze', idField: 'id' },

    // --- NEU BASIEREND AUF DATASTORE ---
    'tasks': { table: tasks, labelField: tasks.name, rootLabel: 'Aufgaben', idField: 'id' },
    'contacts': { table: contacts, labelField: contacts.fullName, rootLabel: 'Kontakte', idField: 'id' },
    'contracts': { table: contracts, labelField: contracts.name, rootLabel: 'Verträge', idField: 'id' },
    'vehicles': { table: vehicles, labelField: vehicles.license_plate, rootLabel: 'Fahrzeuge', idField: 'id' },
    'vendors': { table: vendors, labelField: vendors.name, rootLabel: 'Lieferanten', idField: 'id' },
    'spaces': { table: spaces, labelField: spaces.name, rootLabel: 'Lagerplätze', idField: 'id' },
    'inventoryitemgroups': { table: inventoryitemgroups, labelField: inventoryitemgroups.name, rootLabel: 'Inventarartikelgruppen', idField: 'id' },
    'services': { table: services, labelField: services.name, rootLabel: 'Leistungen', idField: 'id' },
    'hourrates': { table: hourrates, labelField: hourrates.name, rootLabel: 'Stundensätze', idField: 'id' },
    'events': { table: events, labelField: events.name, rootLabel: 'Termine', idField: 'id' },
    'productcategories': { table: productcategories, labelField: productcategories.name, rootLabel: 'Artikelkategorien', idField: 'id' },
    'servicecategories': { table: servicecategories, labelField: servicecategories.name, rootLabel: 'Leistungskategorien', idField: 'id' },
    'ownaccounts': { table: ownaccounts, labelField: ownaccounts.name, rootLabel: 'Zusätzliche Buchungskonten', idField: 'id' },
}

// Types
interface WikiTreeQuery {
    entityType?: string
    entityId?: number
    entityUuid?: string
}

interface WikiCreateBody {
    title: string
    parentId?: string
    isFolder?: boolean
    entityType?: string
    entityId?: number
    entityUuid?: string
}

interface WikiUpdateBody {
    title?: string
    content?: any
    parentId?: string | null
    sortOrder?: number
    isFolder?: boolean
}

export default async function wikiRoutes(server: FastifyInstance) {

    // ---------------------------------------------------------
    // 1. GET /wiki/tree
    // Lädt Struktur: Entweder gefiltert (Widget) oder Global (mit virtuellen Ordnern)
    // ---------------------------------------------------------
    server.get<{ Querystring: WikiTreeQuery }>("/wiki/tree", async (req, reply) => {
        const user = req.user
        const { entityType, entityId, entityUuid } = req.query

        // FALL A: WIDGET-ANSICHT (Spezifische Entität)
        // Wenn wir spezifisch filtern, wollen wir nur die echten Seiten ohne virtuelle Ordner
        if (entityType && (entityId || entityUuid)) {
            const filters = [
                eq(wikiPages.tenantId, user.tenant_id),
                eq(wikiPages.entityType, entityType)
            ]

            if (entityId) filters.push(eq(wikiPages.entityId, Number(entityId)))
            else if (entityUuid) filters.push(eq(wikiPages.entityUuid, entityUuid))

            return server.db
                .select({
                    id: wikiPages.id,
                    parentId: wikiPages.parentId,
                    title: wikiPages.title,
                    isFolder: wikiPages.isFolder,
                    sortOrder: wikiPages.sortOrder,
                    entityType: wikiPages.entityType,
                    updatedAt: wikiPages.updatedAt,
                })
                .from(wikiPages)
                .where(and(...filters))
                .orderBy(asc(wikiPages.sortOrder), asc(wikiPages.title))
        }

        // FALL B: GLOBALE ANSICHT (Haupt-Wiki)
        // Wir laden ALLES und bauen virtuelle Ordner für die Entitäten

        // 1. Alle Wiki-Seiten des Tenants laden
        const allPages = await server.db
            .select({
                id: wikiPages.id,
                parentId: wikiPages.parentId,
                title: wikiPages.title,
                isFolder: wikiPages.isFolder,
                sortOrder: wikiPages.sortOrder,
                entityType: wikiPages.entityType,
                entityId: wikiPages.entityId,     // Wichtig für Zuordnung
                entityUuid: wikiPages.entityUuid, // Wichtig für Zuordnung
                updatedAt: wikiPages.updatedAt,
            })
            .from(wikiPages)
            .where(eq(wikiPages.tenantId, user.tenant_id))
            .orderBy(asc(wikiPages.sortOrder), asc(wikiPages.title))

        // Trennen in Standard-Seiten und Entity-Seiten
        const standardPages = allPages.filter(p => !p.entityType)
        const entityPages = allPages.filter(p => p.entityType)

        const virtualNodes: any[] = []

        // 2. Virtuelle Ordner generieren
        // Wir iterieren durch unsere Config (Kunden, Projekte...)
        await Promise.all(Object.entries(ENTITY_CONFIG).map(async ([typeKey, config]) => {

            // Haben wir überhaupt Notizen für diesen Typ?
            const pagesForType = entityPages.filter(p => p.entityType === typeKey)
            if (pagesForType.length === 0) return

            // IDs sammeln, um Namen aus der DB zu holen
            // Wir unterscheiden zwischen ID (int) und UUID
            let entities: any[] = []

            if (config.idField === 'id') {
                const ids = [...new Set(pagesForType.map(p => p.entityId).filter((id): id is number => id !== null))]
                if (ids.length > 0) {
                    //@ts-ignore - Drizzle Typisierung bei dynamischen Tables ist tricky
                    entities = await server.db.select({ id: config.table.id, label: config.labelField })
                        .from(config.table)
                        //@ts-ignore
                        .where(inArray(config.table.id, ids))
                }
            } else {
                // Falls UUID genutzt wird (z.B. IoT Devices)
                const uuids = [...new Set(pagesForType.map(p => p.entityUuid).filter((uuid): uuid is string => uuid !== null))]
                if (uuids.length > 0) {
                    //@ts-ignore
                    entities = await server.db.select({ id: config.table.id, label: config.labelField })
                        .from(config.table)
                        //@ts-ignore
                        .where(inArray(config.table.id, uuids))
                }
            }

            if (entities.length === 0) return

            // 3. Virtuellen Root Ordner erstellen (z.B. "Kunden")
            const rootId = `virtual-root-${typeKey}`
            virtualNodes.push({
                id: rootId,
                parentId: null, // Ganz oben im Baum
                title: config.rootLabel,
                isFolder: true,
                isVirtual: true, // Flag fürs Frontend (read-only Folder)
                sortOrder: 1000  // Ganz unten anzeigen
            })

            // 4. Virtuelle Entity Ordner erstellen (z.B. "Müller GmbH")
            entities.forEach(entity => {
                const entityNodeId = `virtual-entity-${typeKey}-${entity.id}`

                virtualNodes.push({
                    id: entityNodeId,
                    parentId: rootId,
                    title: entity.label || 'Unbekannt',
                    isFolder: true,
                    isVirtual: true,
                    sortOrder: 0
                })

                // 5. Die echten Notizen verschieben
                // Wir suchen alle Notizen, die zu dieser Entity gehören
                const myPages = pagesForType.filter(p =>
                    (config.idField === 'id' && p.entityId === entity.id) ||
                    (config.idField === 'uuid' && p.entityUuid === entity.id)
                )

                myPages.forEach(page => {
                    // Nur Root-Notizen der Entity verschieben.
                    // Sub-Pages bleiben wo sie sind (parentId zeigt ja schon auf die richtige Seite)
                    if (!page.parentId) {
                        // Wir modifizieren das Objekt für die Response (nicht in der DB!)
                        // Wir müssen es clonen, sonst ändern wir es für alle Referenzen
                        const pageClone = { ...page }
                        pageClone.parentId = entityNodeId
                        virtualNodes.push(pageClone)
                    } else {
                        // Sub-Pages einfach so hinzufügen
                        virtualNodes.push(page)
                    }
                })
            })
        }))

        // Ergebnis: Normale Seiten + Virtuelle Struktur
        return [...standardPages, ...virtualNodes]
    })

    // ---------------------------------------------------------
    // 2. GET /wiki/:id
    // Lädt EINEN Eintrag komplett MIT Content
    // ---------------------------------------------------------
    server.get<{ Params: { id: string } }>("/wiki/:id", async (req, reply) => {
        const user = req.user
        const { id } = req.params

        const page = await server.db.query.wikiPages.findFirst({
            where: and(
                eq(wikiPages.id, id),
                eq(wikiPages.tenantId, user.tenant_id)
            ),
            with: {
                author: {
                    columns: { id: true } // Name falls vorhanden
                }
            }
        })

        if (!page) return reply.code(404).send({ error: "Page not found" })
        return page
    })

    // ---------------------------------------------------------
    // 3. POST /wiki
    // Erstellt neuen Eintrag
    // ---------------------------------------------------------
    server.post<{ Body: WikiCreateBody }>("/wiki", async (req, reply) => {
        const user = req.user
        const body = req.body

        if (!body.title) return reply.code(400).send({ error: "Title required" })

        const hasEntity = !!body.entityType

        const [newPage] = await server.db
            .insert(wikiPages)
            .values({
                tenantId: user.tenant_id,
                title: body.title,
                parentId: body.parentId || null,
                isFolder: body.isFolder ?? false,
                entityType: hasEntity ? body.entityType : null,
                entityId: hasEntity && body.entityId ? body.entityId : null,
                entityUuid: hasEntity && body.entityUuid ? body.entityUuid : null,
                //@ts-ignore
                createdBy: user.id,
                //@ts-ignore
                updatedBy: user.id
            })
            .returning()

        return newPage
    })

    // ---------------------------------------------------------
    // 4. PATCH /wiki/:id
    // Universal-Update
    // ---------------------------------------------------------
    server.patch<{ Params: { id: string }; Body: WikiUpdateBody }>(
        "/wiki/:id",
        async (req, reply) => {
            const user = req.user
            const { id } = req.params
            const body = req.body

            const existing = await server.db.query.wikiPages.findFirst({
                where: and(eq(wikiPages.id, id), eq(wikiPages.tenantId, user.tenant_id)),
                columns: { id: true }
            })

            if (!existing) return reply.code(404).send({ error: "Not found" })

            const [updatedPage] = await server.db
                .update(wikiPages)
                .set({
                    title: body.title,
                    content: body.content,
                    parentId: body.parentId,
                    sortOrder: body.sortOrder,
                    isFolder: body.isFolder,
                    updatedAt: new Date(),
                    //@ts-ignore
                    updatedBy: user.id
                })
                .where(eq(wikiPages.id, id))
                .returning()

            return updatedPage
        }
    )

    // ---------------------------------------------------------
    // 5. DELETE /wiki/:id
    // Löscht Eintrag
    // ---------------------------------------------------------
    server.delete<{ Params: { id: string } }>("/wiki/:id", async (req, reply) => {
        const user = req.user
        const { id } = req.params

        const result = await server.db
            .delete(wikiPages)
            .where(and(
                eq(wikiPages.id, id),
                eq(wikiPages.tenantId, user.tenant_id)
            ))
            .returning({ id: wikiPages.id })

        if (result.length === 0) return reply.code(404).send({ error: "Not found" })

        return { success: true, deletedId: result[0].id }
    })
}
