import { generatePluginKey } from "@shared/helper/pluginHelper"
import logger from "@racletteCore/lib/logger"
import { validatePluginMetadata } from "../utils/operations"
import type { DiscoveredPlugin, PluginType } from "../types"

/** Keys are known at build time; covers both `…/frontend/` and `…/src/frontend/`. */
const appPluginFrontendIndexKeys = new Set(
  Object.keys(
    import.meta.glob(
      [
        "/src/plugins/**/frontend/index.ts",
        "/src/workbenchPlugins/**/frontend/index.ts",
      ],
      { eager: false },
    ),
  ),
)

function resolveAppPluginFrontendPath(
  pluginPath: string,
  metadata: { frontendDir?: string },
): string {
  const explicit = metadata.frontendDir?.replace(/^\.\//, "")
  if (explicit) {
    return `${pluginPath}/${explicit}`
  }

  const direct = `${pluginPath}/frontend`
  const underSrc = `${pluginPath}/src/frontend`
  const directIndex = `${direct}/index.ts`
  const srcIndex = `${underSrc}/index.ts`

  const hasDirect = appPluginFrontendIndexKeys.has(directIndex)
  const hasUnderSrc = appPluginFrontendIndexKeys.has(srcIndex)

  if (hasDirect && hasUnderSrc) {
    return direct
  }
  if (hasUnderSrc) {
    return underSrc
  }
  return direct
}

/**
 * Discover app/user plugins using static glob pattern with exclusions
 */
export const discoverAppPlugins = async (): Promise<DiscoveredPlugin[]> => {
  const plugins: DiscoveredPlugin[] = []

  try {
    const configModules = import.meta.glob(
      [
        "/src/plugins/**/raclette.plugin.ts",
        "/src/workbenchPlugins/**/raclette.plugin.ts",
      ],
      {
        eager: false,
      },
    )

    for (const configPath of Object.keys(configModules)) {
      try {
        const loadConfig = configModules[configPath]
        if (!loadConfig) continue
        const configModule = await loadConfig()
        const metadata = (configModule as any)?.default || configModule

        if (!validatePluginMetadata(metadata)) {
          logger.pluginRegistrar(`Invalid plugin metadata in ${configPath}`)
          continue
        }

        const pluginPath = configPath.replace(/\/raclette\.plugin\.ts$/, "")
        const frontendPath = resolveAppPluginFrontendPath(pluginPath, metadata)

        const pluginKey = generatePluginKey(metadata.name, metadata.author)

        plugins.push({
          configPath,
          pluginPath,
          frontendPath,
          type: "app" as PluginType,
          metadata,
          pluginKey,
        })

        logger.pluginRegistrar("Discovered app plugin", pluginKey)
      } catch (error) {
        logger.pluginRegistrar(
          `Error processing app plugin ${configPath}:`,
          error,
        )
      }
    }
  } catch (error) {
    logger.pluginRegistrar(`Error discovering app plugins:`, error)
  }

  return plugins
}
