import Fastify from "fastify";
import swaggerPlugin from "./plugins/swagger"
import dayjsPlugin from "./plugins/dayjs";
import healthRoutes from "./routes/health";
import meRoutes from "./routes/auth/me";
import tenantRoutes from "./routes/tenant";
import tenantPlugin from "./plugins/tenant";
import authRoutes from "./routes/auth/auth";
import authRoutesAuthenticated from "./routes/auth/auth-authenticated";
import authPlugin from "./plugins/auth";
import adminRoutes from "./routes/admin";
import corsPlugin from "./plugins/cors";
import queryConfigPlugin from "./plugins/queryconfig";
import dbPlugin from "./plugins/db";
import resourceRoutesSpecial from "./routes/resourcesSpecial";
import fastifyCookie from "@fastify/cookie";
import historyRoutes from "./routes/history";
import fileRoutes from "./routes/files";
import functionRoutes from "./routes/functions";
import bankingRoutes from "./routes/banking";
import exportRoutes from "./routes/exports"
import emailAsUserRoutes from "./routes/emailAsUser";
import authProfilesRoutes from "./routes/profiles";
import helpdeskRoutes from "./routes/helpdesk";
import helpdeskInboundRoutes from "./routes/helpdesk.inbound";
import notificationsRoutes from "./routes/notifications";
import staffTimeRoutes from "./routes/staff/time";
import staffTimeConnectRoutes from "./routes/staff/timeconnects";
import userRoutes from "./routes/auth/user";
import publiclinksAuthenticatedRoutes from "./routes/publiclinks/publiclinks-authenticated";
import wikiRoutes from "./routes/wiki";
import portalContractRoutes from "./routes/portal/contracts";
import mcpRoutes from "./routes/mcp";
import communicationRoutes from "./routes/communication";
import telephonyRoutes from "./routes/telephony";
import instanceAgentRoutes from "./routes/instanceAgents";
import instanceAgentGatewayRoutes from "./routes/instanceAgentGateway";

//Public Links
import publiclinksNonAuthenticatedRoutes from "./routes/publiclinks/publiclinks-non-authenticated";

//Resources
import resourceRoutes from "./routes/resources/main";

//M2M
import authM2m from "./plugins/auth.m2m";
import helpdeskInboundEmailRoutes from "./routes/helpdesk.inbound.email";
import deviceRoutes from "./routes/internal/devices";
import tenantRoutesInternal from "./routes/internal/tenant";
import staffTimeRoutesInternal from "./routes/internal/time";
import authM2mInternalRoutes from "./routes/internal/auth.m2m";

//Devices
import devicesRFIDRoutes from "./routes/devices/rfid";
import devicesManagementRoutes from "./routes/devices/management";


import {sendMail} from "./utils/mailer";
import {loadSecrets, secrets} from "./utils/secrets";
import {initMailer} from "./utils/mailer"
import {initS3} from "./utils/s3";
import { runBootstrap } from "./modules/bootstrap.service";
import { startMatrixPushWorker } from "./modules/matrix-push-worker.service";


//Services
import servicesPlugin from "./plugins/services";

async function main() {
    const app = Fastify({ logger: false });
    await loadSecrets();
    await initMailer();
    await initS3();



    /*app.addHook("onRequest", (req, reply, done) => {
        console.log("Incoming:", req.method, req.url, "Headers:", req.headers)
        done()
    })*/

    // Plugins Global verfügbar
    await app.register(swaggerPlugin);
    await app.register(tenantPlugin);
    await app.register(dayjsPlugin);
    await app.register(dbPlugin);
    await app.register(servicesPlugin);
    await runBootstrap(app);
    startMatrixPushWorker(app);

    app.addHook('preHandler', (req, reply, done) => {
        console.log(req.method)
        console.log('Matched path:', req.routeOptions.url)
        console.log('Exact URL:', req.url)
        done()
    })

    app.get('/health', async (req, res) => {
        return res.send({ status: 'ok' })
    })

    //Plugin nur auf bestimmten Routes
    await app.register(queryConfigPlugin, {
        routes: ['/api/resource/:resource/paginated']
    })

    app.register(fastifyCookie, {
        secret: secrets.COOKIE_SECRET,
    })
    // Öffentliche Routes
    await app.register(authRoutes);
    await app.register(healthRoutes);

    await app.register(helpdeskInboundRoutes);

    await app.register(publiclinksNonAuthenticatedRoutes)


    await app.register(async (m2mApp) => {
        await m2mApp.register(authM2m)
        await m2mApp.register(authM2mInternalRoutes)
        await m2mApp.register(helpdeskInboundEmailRoutes)
        await m2mApp.register(deviceRoutes)
        await m2mApp.register(tenantRoutesInternal)
        await m2mApp.register(staffTimeRoutesInternal)
    },{prefix: "/internal"})

    await app.register(async (devicesApp) => {
        await devicesApp.register(devicesRFIDRoutes)
        await devicesApp.register(devicesManagementRoutes)
    },{prefix: "/devices"})

    await app.register(async (agentApp) => {
        await agentApp.register(instanceAgentGatewayRoutes)
    },{prefix: "/instance-agent"})

    await app.register(corsPlugin);

    //Geschützte Routes

    await app.register(async (subApp) => {
        await subApp.register(authPlugin);
        await subApp.register(authRoutesAuthenticated);
        await subApp.register(meRoutes);
        await subApp.register(tenantRoutes);
        await subApp.register(adminRoutes);
        await subApp.register(resourceRoutesSpecial);
        await subApp.register(historyRoutes);
        await subApp.register(fileRoutes);
        await subApp.register(functionRoutes);
        await subApp.register(bankingRoutes);
        await subApp.register(exportRoutes);
        await subApp.register(emailAsUserRoutes);
        await subApp.register(authProfilesRoutes);
        await subApp.register(helpdeskRoutes);
        await subApp.register(notificationsRoutes);
        await subApp.register(staffTimeRoutes);
        await subApp.register(staffTimeConnectRoutes);
        await subApp.register(userRoutes);
        await subApp.register(publiclinksAuthenticatedRoutes);
        await subApp.register(resourceRoutes);
        await subApp.register(wikiRoutes);
        await subApp.register(portalContractRoutes);
        await subApp.register(mcpRoutes);
        await subApp.register(communicationRoutes);
        await subApp.register(telephonyRoutes);
        await subApp.register(instanceAgentRoutes);

    },{prefix: "/api"})

    app.ready(async () => {
        try {
            console.log("Testing DB Connection:")
            const result = await app.db.execute("SELECT NOW()");
            console.log("✓ DB connection OK: " + JSON.stringify(result.rows[0]));
        } catch (err) {
            console.log("❌ DB connection failed:", err);
        }
    });

    // Start
    try {
        await app.listen({ port: secrets.PORT, host: secrets.HOST });
        console.log(`🚀 Server läuft auf http://${secrets.HOST}:${secrets.PORT}`);
    } catch (err) {
        app.log.error(err);
        process.exit(1);
    }
}

main();
