/*
|--------------------------------------------------------------------------
| Http Exception Handler
|--------------------------------------------------------------------------
|
| AdonisJs will forward all exceptions occurred during an HTTP request to
| the following class. You can learn more about exception handling by
| reading docs.
|
| The exception handler extends a base `HttpExceptionHandler` which is not
| mandatory, however it can do lot of heavy lifting to handle the errors
| properly.
|
*/
import app from '@adonisjs/core/services/app';
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http';
// import logger from '@adonisjs/core/services/logger';
import type { StatusPageRange, StatusPageRenderer } from '@adonisjs/core/types/http';

export default class HttpExceptionHandler extends ExceptionHandler {
    /**
     * In debug mode, the exception handler will display verbose errors
     * with pretty printed stack traces.
     */
    protected debug = !app.inProduction;

    /**
     * Status pages are used to display a custom HTML pages for certain error
     * codes. You might want to enable them in production only, but feel
     * free to enable them in development as well.
     */
    protected renderStatusPages = true; //app.inProduction;

    /**
     * Status pages is a collection of error code range and a callback
     * to return the HTML contents to send as a response.
     */
    // protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
    //     '401..403': (error, { view }) => {
    //         return view.render('./errors/unauthorized', { error });
    //     },
    //     '404': (error, { view }) => {
    //         return view.render('./errors/not-found', { error });
    //     },
    //     '500..599': (error, { view }) => {
    //         return view.render('./errors/server-error', { error });
    //     },
    // };

    protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
        '404': (error, { inertia }) => {
            return inertia.render('Errors/ServerError', {
                error: error.message,
                code: error.status,
            });
        },
        '401..403': async (error, { inertia }) => {
            // session.flash('errors', error.message);
            return inertia.render('Errors/ServerError', {
                error: error.message,
                code: error.status,
            });
        },
        // '500': (error, { inertia }) => {
        //      return inertia.render('Errors/postgres_error', {
        //             status: 'error',
        //             message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
        //             details: {
        //                 code: error.code,
        //                 type: error.status,
        //                 ports: error.errors.map((err: any) => ({
        //                     port: err.port,
        //                     address: err.address,
        //                 })),
        //             },
        //         });
        // },
        '500..599': (error, { inertia }) => {
            if (error.code === 'ECONNREFUSED') {
                const dbErrors = error.errors.some((err: any) => err.code === 'ECONNREFUSED' && err.port === 5432);

                if (dbErrors) {
                    return inertia.render('Errors/postgres_error', {
                        status: 'error',
                        message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
                        details: {
                            code: error.code,
                            type: error.status,
                            ports: error.errors.map((err: any) => ({
                                port: err.port,
                                address: err.address,
                            })),
                        },
                    });
                }
            } else {
                return inertia.render('Errors/ServerError', {
                    error: error.message,
                    code: error.status,
                });
            }
        },
    };

    // constructor() {
    //     super(logger);
    // }

    public async handle(error: any, ctx: HttpContext) {
        const { response, request, session, inertia } = ctx;

        /**
         * Handle failed authentication attempt
         */
        // if (['E_INVALID_AUTH_PASSWORD', 'E_INVALID_AUTH_UID'].includes(error.code)) {
        //   session.flash('errors', { login: error.message });
        //   return response.redirect('/login');
        // }
        // if ([401].includes(error.status)) {
        //   session.flash('errors', { login: error.message });
        //   return response.redirect('/dashboard');
        // }

        // Handle Axios errors
        if (error.code === 'ECONNREFUSED') {
            const dbErrors = error.errors.some((err: any) => err.code === 'ECONNREFUSED' && err.port === 5432);

            if (dbErrors) {
                // return ctx.response.status(503).json({
                //     status: 'error',
                //     message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
                //     details: {
                //         code: error.code,
                //         type: error.status,
                //         ports: error.errors.map((err: any) => ({
                //             port: err.port,
                //             address: err.address,
                //         })),
                //     },
                // });
                // return inertia.render('Errors/postgres_error', {
                //     status: 'error',
                //     message: 'PostgreSQL database connection failed. Please ensure the database service is running.',
                //     details: {
                //         code: error.code,
                //         type: error.status,
                //         ports: error.errors.map((err: any) => ({
                //             port: err.port,
                //             address: err.address,
                //         })),
                //     },
                // });
            }
        }

        // Handle simple ECONNREFUSED errors
        // if (error.code === 'ECONNREFUSED') {
        //     return ctx.response.status(503).json({
        //         status: 'error',
        //         message: 'Database connection failed. Please ensure PostgreSQL is running.',
        //         code: error.code,
        //     });
        // }

        // https://github.com/inertiajs/inertia-laravel/issues/56
        // let test = response.getStatus(); //200
        // let header = request.header('X-Inertia'); // true
        // if (request.header('X-Inertia') && [500, 503, 404, 403, 401, 200].includes(response.getStatus())) {
        if (request.header('X-Inertia') && [422].includes(error.status)) {
            // session.flash('errors', error.messages.errors);
            session.flash('errors', error.messages);
            return response.redirect().back();
            // return inertia.render('errors/server_error', {
            // return inertia.render('errors/server_error', {
            //     // status: response.getStatus(),
            //     error: error,
            // });
            // ->toResponse($request)
            // ->setStatusCode($response->status());
        }

        // Handle simple ECONNREFUSED errors
        //   if (error.code === 'ECONNREFUSED') {
        //     return ctx.response.status(503).json({
        //         status: 'error',
        //         message: 'Database connection failed. Please ensure PostgreSQL is running.',
        //         code: error.code,
        //     });
        // }
        // Dynamically change the error templates based on the absence of X-Inertia header
        // if (!ctx.request.header('X-Inertia')) {
        //     this.statusPages = {
        //         '401..403': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
        //         '404': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
        //         '500..599': (error, { inertia }) => inertia.render('Errors/ServerError', { error: error.message, code: error.status }),
        //     };
        // }

        /**
         * Forward rest of the exceptions to the parent class
         */
        return super.handle(error, ctx);
    }

    /**
     * The method is used to report error to the logging service or
     * the a third party error monitoring service.
     *
     * @note You should not attempt to send a response from this method.
     */
    async report(error: unknown, ctx: HttpContext) {
        return super.report(error, ctx);
    }
}
