import { canUseFeature } from '../core/license/feature-gates';
import type { AsukaLicenseEntitlements } from '../core/license/license.types';
import { registerPremiumImageProviders } from '../registerPremiumImageProviders';

export const PREMIUM_ADDON_IDS = [
  'studio',
  'pricing',
  'pricing-rules',
  'marker',
  'drawing-areas',
  'model-optimizer',
  'assembly',
  'product-parameters',
] as const;

export type PremiumAddonId = (typeof PREMIUM_ADDON_IDS)[number];
export type PremiumAddonLoadStatus = 'idle' | 'loading' | 'loaded' | 'missing';
export type PremiumAddonLoader = () => Promise<unknown>;
export type PremiumAddonLoaders = Record<PremiumAddonId, PremiumAddonLoader>;

export interface PremiumAddonLoadResult {
  id: PremiumAddonId;
  loaded: boolean;
}

const ADDON_FEATURES: Readonly<Record<PremiumAddonId, readonly string[]>> = {
  studio: ['studioBasic'],
  pricing: ['pricing'],
  'pricing-rules': ['pricingRules'],
  marker: ['fixedSlots'],
  'drawing-areas': ['drawingAreas'],
  'model-optimizer': ['modelOptimization'],
  assembly: ['assembly'],
  'product-parameters': ['productParameters'],
};

const DEFAULT_ADDON_LOADERS: PremiumAddonLoaders = {
  studio: () => import('./addons/studio-addon'),
  pricing: () => import('./addons/pricing-addon'),
  'pricing-rules': () => import('./addons/pricing-rules-addon'),
  marker: () => import('./addons/marker-addon'),
  'drawing-areas': () => import('./addons/drawing-areas-addon'),
  'model-optimizer': () => import('./addons/model-optimizer-addon'),
  assembly: () => import('./addons/assembly-addon'),
  'product-parameters': () => import('./addons/product-parameters-addon'),
};

const loadedAddons = new Set<PremiumAddonId>();
const pendingAddons = new Map<PremiumAddonId, Promise<boolean>>();
const addonStatuses = new Map<PremiumAddonId, PremiumAddonLoadStatus>();

export function resolveLicensedPremiumAddonIds(
  license: AsukaLicenseEntitlements | null | undefined,
): PremiumAddonId[] {
  return PREMIUM_ADDON_IDS.filter((id) => ADDON_FEATURES[id].some((feature) => canUseFeature(license, feature)));
}

async function attemptAddonLoad(loader: PremiumAddonLoader): Promise<boolean> {
  try {
    await loader();
    return true;
  } catch {
    return false;
  }
}

async function loadDefaultAddon(id: PremiumAddonId): Promise<boolean> {
  if (loadedAddons.has(id)) return true;
  const pending = pendingAddons.get(id);
  if (pending) return pending;

  addonStatuses.set(id, 'loading');
  const task = attemptAddonLoad(DEFAULT_ADDON_LOADERS[id])
    .then((loaded) => {
      addonStatuses.set(id, loaded ? 'loaded' : 'missing');
      if (loaded) loadedAddons.add(id);
      return loaded;
    })
    .finally(() => {
      pendingAddons.delete(id);
    });
  pendingAddons.set(id, task);
  return task;
}

export async function loadLicensedPremiumAddons(
  license: AsukaLicenseEntitlements | null | undefined,
  loaders: PremiumAddonLoaders = DEFAULT_ADDON_LOADERS,
): Promise<PremiumAddonLoadResult[]> {
  const addonIds = resolveLicensedPremiumAddonIds(license);
  return Promise.all(addonIds.map(async (id) => ({
    id,
    loaded: loaders === DEFAULT_ADDON_LOADERS
      ? await loadDefaultAddon(id)
      : await attemptAddonLoad(loaders[id]),
  })));
}

export function getPremiumAddonLoadStatuses(): Readonly<Record<PremiumAddonId, PremiumAddonLoadStatus>> {
  return Object.fromEntries(PREMIUM_ADDON_IDS.map((id) => [id, addonStatuses.get(id) ?? 'idle'])) as Record<PremiumAddonId, PremiumAddonLoadStatus>;
}

export async function registerPremiumRuntime(
  license: AsukaLicenseEntitlements | null | undefined,
): Promise<PremiumAddonLoadResult[]> {
  registerPremiumImageProviders();
  return loadLicensedPremiumAddons(license);
}
