/*
 * Copyright 2017-2025 VMware, Inc. All rights reserved. VMware Confidential
 */

import { Inject, Injectable } from "@angular/core";
import { Route, Router } from "@angular/router";
import { Observable, of, throwError as _throw } from "rxjs";
import { ExtensionContainerGuard } from "../../extension-container/extension-container-guard";
import { ExtensionContainerComponent } from "../../extension-container/extension-container.component";
import { ExternalExtensionLoaderState } from "../extension-loader.model";
import { ExternalExtensionLoaderErrorObservable } from "./external-extension-loader-error";
import { ExtensionPointRoutingHandler } from "../../extension-point-routing.handler";
import { HYPER_PLUGIN_CONFIG, HyperpluginConfig } from "../../../../../lib-interfaces";
import { logger } from "../../../../logging/logger";

@Injectable()
export class RegisterExternalExtensionRoutesStep {
    constructor(
        @Inject(HYPER_PLUGIN_CONFIG) private HYPER_PLUGIN_CONFIG: HyperpluginConfig,
        private extensionPointRoutingHandler: ExtensionPointRoutingHandler,
        private router: Router,
    ) {}

    /**
     * Registeres the extension's routes with the router.
     * State inputs: spec, manifest, route, angularModuleFactory
     * State ouputs: none
     */
    public perform(state: ExternalExtensionLoaderState): Observable<ExternalExtensionLoaderState> {
        try {
            logger.log(`[${state.spec.id} (${state.manifest.name})] Registering route: ${state.routes}`);

            if (state.manifest.module && state.manifest.route) {
                this.registerDynamicRoutesInStaticModule(state);
            }

            logger.log(`[${state.spec.id} (${state.manifest.name})] Registerd route`);
            return of(state);
        } catch (err) {
            console.error(`[${state?.spec?.id} (${state?.manifest?.name})] Could not register routes`, err);
            return new ExternalExtensionLoaderErrorObservable();
        }
    }

    private registerDynamicRoutesInStaticModule(state: ExternalExtensionLoaderState): void {
        const extensibleRoute = this.HYPER_PLUGIN_CONFIG.routes.filter((route) => {
            return route.type === "legacy:navigation:primary";
        })[0];

        if (!extensibleRoute) {
            return;
        }

        const extensibleRouteSegments = extensibleRoute.path.split("/");
        const mainPath = extensibleRouteSegments[0];
        const childSegments = extensibleRouteSegments.slice(1);

        let mainRoute = this.router.config.find((route) => {
            return route.path === mainPath;
        });

        this.extensionPointRoutingHandler.findRouteChain(mainRoute, childSegments).subscribe((pluginsContainerRouter) => {
            if (!pluginsContainerRouter.children) {
                pluginsContainerRouter.children = [];
            }
    
            // const angularFactoryId = Object.keys(state.angularModuleFactories).find((id) => id === state.spec.id);
            // const angularFactory = state.angularModuleFactories[angularFactoryId];
    
            if (!state.routes[state.spec.id]) {
                return;
            }
    
            // Get the hashed vendor and the route created for vCD
            const [hashedVendor, vcdRoute] = state.routes[state.spec.id].split("/");
            const alreadyExistingRouteVendorRoute = pluginsContainerRouter.children.find((route) => {
                return route.path === hashedVendor;
            });
    
            if (!alreadyExistingRouteVendorRoute) {
                const newRoute: Route = {
                    path: hashedVendor,
                    children: [
                        {
                            path: "",
                            pathMatch: "full",
                            redirectTo: vcdRoute,
                        },
                        {
                            path: vcdRoute,
                            component: ExtensionContainerComponent,
                            data: {
                                vcdRoute,
                                fullHeight: extensibleRoute.fullHeight,
                            },
                            canDeactivate: [ExtensionContainerGuard],
                            children: [
                                {
                                    path: "**",
                                    component: ExtensionContainerComponent,
                                    canDeactivate: [ExtensionContainerGuard],
                                },
                            ],
                        },
                    ],
                };
    
                pluginsContainerRouter.children.push(newRoute);
                return;
            }
    
            alreadyExistingRouteVendorRoute.children.push({
                path: vcdRoute,
                component: ExtensionContainerComponent,
                data: {
                    vcdRoute,
                    fullHeight: extensibleRoute.fullHeight,
                },
                canDeactivate: [ExtensionContainerGuard],
                children: [
                    {
                        path: "**",
                        component: ExtensionContainerComponent,
                        canDeactivate: [ExtensionContainerGuard],
                    },
                ],
            });
        });
    }
}
