import type { ExtensionLoader } from "../extensions/loader";
import type { ExtensionAuditLog } from "../extensions/auditLog";
import type { ExtensionManifestStore } from "../extensions/manifestStore";
import type { InMemoryEventBus } from "./eventBus";
import type { OpsMetrics } from "./opsMetrics";
import { createEvent } from "./events";

type ControllerLog = (message: string, fields?: Record<string, unknown>) => void;

function buildManifestPayload(
    loader: ExtensionLoader,
    manifestStore: ExtensionManifestStore
): Record<string, unknown> {
    const snapshot = manifestStore.snapshot();
    const extensionRows = loader
        .listStatuses()
        .filter((status) => status.kind === "external")
        .map((status) => ({
        id: status.id,
        kind: status.kind,
        loaded: status.loaded,
        enabled: manifestStore.isEnabled(status.id, true)
    }));

    return {
        updatedAt: snapshot.updatedAt,
        extensions: extensionRows
    };
}

async function emitManifest(
    eventBus: InMemoryEventBus,
    streamId: string,
    loader: ExtensionLoader,
    manifestStore: ExtensionManifestStore
): Promise<void> {
    await eventBus.emit(
        createEvent("ws_out", {
            streamId,
            target: "admin",
            event: "extensions_manifest",
            data: buildManifestPayload(loader, manifestStore)
        })
    );
}

export function attachExtensionAdminController(
    eventBus: InMemoryEventBus,
    loader: ExtensionLoader,
    manifestStore: ExtensionManifestStore,
    auditLog: ExtensionAuditLog,
    log: ControllerLog,
    opsMetrics?: OpsMetrics
): () => void {
    return eventBus.on(
        "admin_command",
        async (event) => {
            if (event.payload.command !== "ext") {
                return;
            }

            const action = event.payload.args[0]?.toLowerCase() ?? "list";
            const extensionId = event.payload.args[1]?.trim() ?? "";

            if (action === "list") {
                await emitManifest(eventBus, event.payload.streamId, loader, manifestStore);
                return;
            }

            if ((action === "enable" || action === "disable") && extensionId) {
                opsMetrics?.recordModuleToggleAttempt();
                const moduleStatus = loader.listStatuses().find((status) => status.id === extensionId);
                if (!moduleStatus) {
                    opsMetrics?.recordModuleToggleResult("failed");
                    await auditLog.appendToggle({
                        timestamp: new Date().toISOString(),
                        streamId: event.payload.streamId,
                        extensionId,
                        enabled: action === "enable",
                        tokenId: event.payload.tokenId,
                        sessionId: event.payload.sessionId,
                        result: "failed",
                        error: "unknown_extension"
                    });
                    await eventBus.emit(
                        createEvent("ws_out", {
                            streamId: event.payload.streamId,
                            target: "admin",
                            event: "extensions_manifest_error",
                            data: {
                                message: `Unknown extension: ${extensionId}`
                            }
                        })
                    );
                    return;
                }
                if (moduleStatus.kind === "builtin") {
                    opsMetrics?.recordModuleToggleResult("failed");
                    await auditLog.appendToggle({
                        timestamp: new Date().toISOString(),
                        streamId: event.payload.streamId,
                        extensionId,
                        enabled: action === "enable",
                        tokenId: event.payload.tokenId,
                        sessionId: event.payload.sessionId,
                        result: "failed",
                        error: "builtin_not_toggleable"
                    });
                    await eventBus.emit(
                        createEvent("ws_out", {
                            streamId: event.payload.streamId,
                            target: "admin",
                            event: "extensions_manifest_error",
                            data: {
                                message: `Core module cannot be toggled: ${extensionId}`
                            }
                        })
                    );
                    return;
                }

                const shouldEnable = action === "enable";
                try {
                    await manifestStore.setEnabled(extensionId, shouldEnable);
                    if (shouldEnable) {
                        await loader.enable(extensionId);
                    } else {
                        await loader.disable(extensionId);
                    }
                    opsMetrics?.recordModuleToggleResult("success");
                    await auditLog.appendToggle({
                        timestamp: new Date().toISOString(),
                        streamId: event.payload.streamId,
                        extensionId,
                        enabled: shouldEnable,
                        tokenId: event.payload.tokenId,
                        sessionId: event.payload.sessionId,
                        result: "success"
                    });
                } catch (error) {
                    opsMetrics?.recordModuleToggleResult("failed");
                    await auditLog.appendToggle({
                        timestamp: new Date().toISOString(),
                        streamId: event.payload.streamId,
                        extensionId,
                        enabled: shouldEnable,
                        tokenId: event.payload.tokenId,
                        sessionId: event.payload.sessionId,
                        result: "failed",
                        error: error instanceof Error ? error.message : String(error)
                    });
                    await eventBus.emit(
                        createEvent("ws_out", {
                            streamId: event.payload.streamId,
                            target: "admin",
                            event: "extensions_manifest_error",
                            data: {
                                message: `Failed to ${action} ${extensionId}`
                            }
                        })
                    );
                    return;
                }

                log("extension_toggled", {
                    extensionId,
                    enabled: shouldEnable,
                    sessionId: event.payload.sessionId
                });

                await emitManifest(eventBus, event.payload.streamId, loader, manifestStore);
                return;
            }

            await eventBus.emit(
                createEvent("ws_out", {
                    streamId: event.payload.streamId,
                    target: "admin",
                    event: "extensions_manifest_error",
                    data: {
                        message: "Usage: ext list | ext enable <id> | ext disable <id>"
                    }
                })
            );
        },
        {
            componentId: "extension-admin-controller",
            componentKind: "core"
        }
    );
}
