import { join } from 'path';
import { FastifyPluginAsync, FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
import AutoLoad from '@fastify/autoload';
import fastifyCors from '@fastify/cors';
import { MikroORM, RequestContext } from '@mikro-orm/core';
import mikroOrmConfig from '../mikro-orm.config';
import fjwt from '@fastify/jwt';
import fCookie from '@fastify/cookie';
import router from './router';
import fs from 'fs';
import path from 'path';
import fastify from 'fastify';

// Helper function to generate the directory tree in HTML
function generateDirectoryTree(dirPath: string): string {
    const items = fs.readdirSync(dirPath);
    let html = '<ul>';

    items.forEach((item) => {
        const itemPath = path.join(dirPath, item);
        const isDirectory = fs.statSync(itemPath).isDirectory();
        html += `<li>${isDirectory ? `<strong>${item}</strong>` : item}`;

        if (isDirectory) {
            html += generateDirectoryTree(itemPath); // Recursive call for directories
        }

        html += '</li>';
    });

    html += '</ul>';
    return html;
}

// HTML wrapper function
function generateHtmlPage(directoryHtml: string): string {
    return `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Directory Structure</title>
        <style>
            body { font-family: Arial, sans-serif; }
            ul { list-style-type: none; padding-left: 20px; }
            li { margin: 5px 0; cursor: pointer; }
            li strong { color: #007bff; }
        </style>
    </head>
    <body>
        <h1>Directory Structure</h1>
        ${directoryHtml}
        <script>
            document.querySelectorAll('li strong').forEach(folder => {
                folder.addEventListener('click', () => {
                    const subList = folder.nextElementSibling;
                    if (subList) {
                        subList.style.display = subList.style.display === 'none' ? 'block' : 'none';
                    }
                });
            });
        </script>
    </body>
    </html>
    `;
}

// Fastify app setup
const app: FastifyPluginAsync = async (app, opts): Promise<void> => {
    console.log("DB CONFIG: ", {
        dbName: process.env.POSTGRES_NAME,
        host: process.env.POSTGRES_HOSTNAME,
        port: process.env.POSTGRES_PORT,
        user: process.env.POSTGRES_USER,
        password: process.env.POSTGRES_PASSWORD,
    });

    const orm = await MikroORM.init({ ...mikroOrmConfig });

    // Register CORS, JWT, and Cookies
    app.register(fastifyCors, {
        origin: process.env.CORS_ORIGIN
            ? process.env.CORS_ORIGIN.split(',').map(origin => origin.trim())
            : [
                'http://localhost:3000',
                'http://localhost:3001',
                'http://localhost:8080',
                'http://localhost:8081'
            ],
        methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
        allowedHeaders: ['Content-Type', 'Authorization', 'Accept'],
        credentials: true,
        maxAge: 86400
    });

    app.register(fjwt, { secret: process.env.JWT_SECRET || 'your-secret-here' });
    app.register(fCookie);

    // Database and request context
    app.decorate('orm', orm);
    app.decorateRequest('em', null);
    app.addHook('onRequest', (request, reply, done) => {
        request.em = orm.em.fork();
        RequestContext.create(request.em, done);
    });
    app.addHook('onClose', async () => {
        await orm.close();
    });

    // Load plugins
    void app.register(AutoLoad, {
        dir: join(__dirname, 'plugins'),
        options: opts,
    });

    // Directory structure route under `/system/files`
    app.get('/system/files', async (request: FastifyRequest, reply: FastifyReply) => {
        const directoryHtml = generateDirectoryTree(path.join(__dirname, '../')); // Adjust path as needed
        const htmlContent = generateHtmlPage(directoryHtml);

        reply.type('text/html').send(htmlContent);
    });

    // API routes
    void app.register(router, { prefix: '/api/v1' });
};

export async function buildApp(): Promise<FastifyInstance> {
    const server = fastify();
    await server.register(app);

    // Set the port to 14000
    const port = process.env.PORT || 14000;
    await server.listen({ port: Number(port), host: '0.0.0.0' });

    return server;
}

export default app;
