import { globalAK } from "#common/global";

import type { Interface } from "#elements/Interface";

import { multiTabOrchestrateLeave } from "#flow/tabs/orchestrator";

import { ChallengeTypes, IdentificationChallenge } from "@goauthentik/api";

import { ReactiveController, ReactiveControllerHost } from "lit";

type MultitabControllerHost = ReactiveControllerHost &
    Interface & { challenge: ChallengeTypes | null };

const isChallenge = (v: unknown): v is ChallengeTypes =>
    v !== null && typeof v === "object" && "component" in v;

const isIdentificationChallenge = (v: unknown): v is IdentificationChallenge =>
    isChallenge(v) && v.component === "ak-stage-identification";

/**
 * Coordinate with authentication events across multiple tabs
 *
 * @remarks
 *
 * The RedirectStage triggers a change in authentication state. If there is more than one tab open
 * to authentik, this controller receives that event and, after checking with the context to ensure
 * coherency, redirects all tabs to the URL that reflects that state.
 *
 */
export class FlowMultitabController implements ReactiveController {
    #abortController: AbortController | null = null;

    constructor(private host: MultitabControllerHost) {
        /* no op */
    }

    onMultitab = () => {
        const { challenge } = this.host;
        if (!challenge) {
            return;
        }

        if (
            isIdentificationChallenge(challenge) &&
            challenge.applicationPreLaunch &&
            challenge.applicationPreLaunch !== "blank://blank"
        ) {
            multiTabOrchestrateLeave();
            window.location.assign(challenge.applicationPreLaunch);
            return;
        }

        const qs = new URLSearchParams(window.location.search);
        const next = qs.get("next");
        if (next) {
            const url = new URL(next, window.location.origin);
            if (!url.pathname.startsWith(`${globalAK().api.relBase}if/flow`)) {
                multiTabOrchestrateLeave();
            }
            window.location.assign(url);
        }
    };

    hostConnected() {
        this.#abortController?.abort();
        this.#abortController = new AbortController();
        const { signal } = this.#abortController;
        window.addEventListener("ak-multitab-continue", this.onMultitab, { signal });
    }

    hostDisconnected() {
        this.#abortController?.abort();
        this.#abortController = null;
    }
}
