import type { ModuleId } from '../types/moduleIds';

export type AsukaPermissions = {
  /** Per-module open permission override (false denies). */
  moduleOpen?: Partial<Record<ModuleId, boolean>>;

  canOpenModule: boolean;
  /** Allows moving/reordering layout panels and editing layout structure. */
  canMovePanels: boolean;
  /** Allows collapsing/expanding layout zones and collapsible panel blocks. */
  canCollapsePanels: boolean;

  canAddRect: boolean;
  canAddText: boolean;
  canAddImage: boolean;
  canAddShape: boolean;
  canDrawShape: boolean;
  canClearCanvas: boolean;

  canUndo: boolean;
  canRedo: boolean;
  canReset: boolean;

  canDuplicateObject: boolean;
  canDeleteObject: boolean;
  canMoveObject: boolean;
  canResizeObject: boolean;
  canRotateObject: boolean;

  canEditObjectColors: boolean;
  canEditObjectStudio: boolean;
  canEditObjectText: boolean;

  /** Dev tools: export/import state, storage helpers, etc. */
  canUseStateTools: boolean;

  /** Can use the magnifier action module. */
  canUseMagnifier: boolean;
  canUseZoom: boolean;
  canZoomIn: boolean;
  canZoomOut: boolean;
  canFitViewport: boolean;
  canResetViewport: boolean;
  canPanCanvas: boolean;

  canSwitchView: boolean;
  canViewViews: boolean;
  canCreateView: boolean;
  canEditView: boolean;
  canDeleteView: boolean;

  canViewLayers: boolean;
  canReorderLayers: boolean;
  canLockLayers: boolean;
  canHideLayers: boolean;
  canSelectLayers: boolean;

  canViewDesigns: boolean;
  canAddDesigns: boolean;

  canOpenImages: boolean;
  canUploadImage: boolean;
  canUseRemoteImages: boolean;
  canUseExternalImageLibraries: boolean;
  canUseFacebookImages: boolean;
  canUsePixabayImages: boolean;
  canUsePexelsImages: boolean;

  canEditText: boolean;
  canEditFontFamily: boolean;
  canEditTextFormatting: boolean;
  canEditTextCurve: boolean;

  canUseColors: boolean;
  canEditColors: boolean;
  canUseStudio: boolean;
  canApplyStudioEffects: boolean;

  canDownload: boolean;
  canDownloadCurrentView: boolean;
  canDownloadAllViews: boolean;
  canDownloadObjects: boolean;
  canDownloadDrawingZones: boolean;
  canExportJson: boolean;
  canImportJson: boolean;

  canViewDrawingAreas: boolean;
  canCreateDrawingAreas: boolean;
  canEditDrawingAreas: boolean;
  canDeleteDrawingAreas: boolean;

  canViewFixedSlots: boolean;
  canCreateFixedSlots: boolean;
  canEditFixedSlots: boolean;
  canDeleteFixedSlots: boolean;

  // Pricing (fine-grained)
  /** Can see pricing UI (panel + breakdown). */
  canViewPricing: boolean;
  /** Can edit the external/base price field. */
  canEditPricingBasePrice: boolean;
  /** Can edit pricing rules (handler/scope/conditions/targets, enable/disable, reorder). */
  canEditPricingRules: boolean;
  /** Can add/duplicate pricing rules. */
  canAddPricingRule: boolean;
  /** Can delete pricing rules. */
  canRemovePricingRule: boolean;

  // Elements (simple)
  /** Can see Elements UI and apply element variations. */
  canViewElements: boolean;
  /** Can create new element definitions/catalog entries. */
  canAddElements: boolean;
  /** Can edit existing element definitions (structure/base metadata). */
  canEditElements: boolean;
  /** Can edit element variations (assets, tree, prices...). */
  canEditElementVariations: boolean;
  /** Can move placed product elements in 3D scenes. */
  canMoveElements: boolean;
  /** Can delete elements (also removes all canvas instances). */
  canDeleteElements: boolean;

  // Spatial assembly
  /** Can open Assembly to inspect the room, components, validation and BOM. */
  canViewAssembly: boolean;
  /** Can draw surfaces, place/rotate components and edit Assembly rules. */
  canEditAssembly: boolean;
};

export const PROD_PERMISSIONS: AsukaPermissions = {
  moduleOpen: {
    state: false,
    pricing: false,
    pricingRules: false,
    'pricing-rules': false,
    'element-editor': false,
    elementEditor: false,
    'element-variation-picker': true,
    elementVariationPicker: true,
    variations: true,
  },
  canOpenModule: true,
  canMovePanels: false,
  canCollapsePanels: false,

  canAddRect: true,
  canAddText: true,

  canAddImage: true,
  canAddShape: true,
  canDrawShape: true,

  canDuplicateObject: true,
  canDeleteObject: true,
  canMoveObject: true,
  canResizeObject: true,
  canRotateObject: true,

  canEditObjectColors: true,
  canEditObjectStudio: true,
  canEditObjectText: true,
  canClearCanvas: true,

  canUndo: true,
  canRedo: true,
  canReset: true,

  canSwitchView: true,

  canViewViews: true,
  canCreateView: false,
  canEditView: false,
  canDeleteView: false,

  canViewLayers: true,
  canReorderLayers: true,
  canLockLayers: true,
  canHideLayers: true,
  canSelectLayers: true,

  canViewDesigns: true,
  canAddDesigns: true,

  canOpenImages: true,
  canUploadImage: true,
  canUseRemoteImages: true,
  canUseExternalImageLibraries: true,
  canUseFacebookImages: true,
  canUsePixabayImages: true,
  canUsePexelsImages: true,

  canEditText: true,
  canEditFontFamily: true,
  canEditTextFormatting: true,
  canEditTextCurve: true,

  canUseColors: true,
  canEditColors: true,
  canUseStudio: true,
  canApplyStudioEffects: true,

  canDownload: true,
  canDownloadCurrentView: true,
  canDownloadAllViews: true,
  canDownloadObjects: true,
  canDownloadDrawingZones: true,
  canExportJson: true,
  canImportJson: true,

  canViewDrawingAreas: true,
  canCreateDrawingAreas: false,
  canEditDrawingAreas: false,
  canDeleteDrawingAreas: false,

  canViewFixedSlots: true,
  canCreateFixedSlots: true,
  canEditFixedSlots: true,
  canDeleteFixedSlots: true,

  // Pricing still runs internally, but its configuration UI is not customer-facing.
  canViewPricing: false,
  canEditPricingBasePrice: false,
  canEditPricingRules: false,
  canAddPricingRule: false,
  canRemovePricingRule: false,

  // Elements
  canViewElements: true,
  canAddElements: false,
  canEditElements: false,
  canEditElementVariations: false,
  canMoveElements: false,
  canDeleteElements: false,

  // Assembly stays inspectable on storefronts, but editing is opt-in.
  canViewAssembly: true,
  canEditAssembly: false,

  canUseStateTools: false,

  // Action tools
  canUseMagnifier: true,

  canUseZoom: true,
  canZoomIn: true,
  canZoomOut: true,
  canFitViewport: true,
  canResetViewport: true,
  canPanCanvas: true,
};

export const DEFAULT_PERMISSIONS: AsukaPermissions = {
  canOpenModule: true,
  canMovePanels: true,
  canCollapsePanels: true,

  canAddRect: true,
  canAddText: true,

  canAddImage: true,
  canAddShape: true,
  canDrawShape: true,

  canDuplicateObject: true,
  canDeleteObject: true,
  canMoveObject: true,
  canResizeObject: true,
  canRotateObject: true,

  canEditObjectColors: true,
  canEditObjectStudio: true,
  canEditObjectText: true,
  canClearCanvas: true,

  canUndo: true,
  canRedo: true,
  canReset: true,

  canSwitchView: true,

  canViewViews: true,
  canCreateView: true,
  canEditView: true,
  canDeleteView: true,

  canViewLayers: true,
  canReorderLayers: true,
  canLockLayers: true,
  canHideLayers: true,
  canSelectLayers: true,

  canViewDesigns: true,
  canAddDesigns: true,

  canOpenImages: true,
  canUploadImage: true,
  canUseRemoteImages: true,
  canUseExternalImageLibraries: true,
  canUseFacebookImages: true,
  canUsePixabayImages: true,
  canUsePexelsImages: true,

  canEditText: true,
  canEditFontFamily: true,
  canEditTextFormatting: true,
  canEditTextCurve: true,

  canUseColors: true,
  canEditColors: true,
  canUseStudio: true,
  canApplyStudioEffects: true,

  canDownload: true,
  canDownloadCurrentView: true,
  canDownloadAllViews: true,
  canDownloadObjects: true,
  canDownloadDrawingZones: true,
  canExportJson: true,
  canImportJson: true,

  canViewDrawingAreas: true,
  canCreateDrawingAreas: true,
  canEditDrawingAreas: true,
  canDeleteDrawingAreas: true,

  canViewFixedSlots: true,
  canCreateFixedSlots: true,
  canEditFixedSlots: true,
  canDeleteFixedSlots: true,

  canViewPricing: true,
  canEditPricingBasePrice: true,
  canEditPricingRules: true,
  canAddPricingRule: true,
  canRemovePricingRule: true,

  // Elements
  canViewElements: true,
  canAddElements: true,
  canEditElements: true,
  canEditElementVariations: true,
  canMoveElements: true,
  canDeleteElements: true,

  canViewAssembly: true,
  canEditAssembly: true,

  canUseStateTools: true,

  // Action tools
  canUseMagnifier: true,

  canUseZoom: true,
  canZoomIn: true,
  canZoomOut: true,
  canFitViewport: true,
  canResetViewport: true,
  canPanCanvas: true,
};

export type AsukaRole = 'dev' | 'editor' | 'viewer' | (string & {});

export const ROLE_PERMISSIONS: Record<AsukaRole, AsukaPermissions> = {
  dev: DEFAULT_PERMISSIONS,
  editor: {
    ...DEFAULT_PERMISSIONS,
    // Editors can work on the design but don't get dev/state tooling or structural view management by default.
    canUseStateTools: false,
    canCreateView: false,
    canEditView: false,
    canDeleteView: false,
    canMovePanels: true,
    canCollapsePanels: true,
  },
  'layout-editor': {
    ...PROD_PERMISSIONS,
    // Production-like UI, but the integrator can still rearrange modules and collapse zones/panels.
    canMovePanels: true,
    canCollapsePanels: true,
  },
  viewer: {
    ...PROD_PERMISSIONS,
    // Viewers can only browse and preview.
    canMovePanels: false,
    canCollapsePanels: false,
    canAddRect: false,
    canAddText: false,
    canAddImage: false,
    canAddShape: false,
    canDrawShape: false,
    canClearCanvas: false,
    canUndo: false,
    canDuplicateObject: false,
    canDeleteObject: false,
    canMoveObject: false,
    canResizeObject: false,
    canRotateObject: false,
    canEditObjectColors: false,
    canEditObjectStudio: false,
    canEditObjectText: false,
    canRedo: false,
    canReset: false,
    canViewViews: true,
    canCreateView: false,
    canEditView: false,
    canDeleteView: false,
    canViewLayers: true,
    canReorderLayers: false,
    canLockLayers: false,
    canHideLayers: false,
    canSelectLayers: true,
    canViewDesigns: true,
    canAddDesigns: false,
    canOpenImages: true,
    canUploadImage: false,
    canUseRemoteImages: false,
    canUseExternalImageLibraries: false,
    canUseFacebookImages: false,
    canUsePixabayImages: false,
    canUsePexelsImages: false,
    canEditText: false,
    canEditFontFamily: false,
    canEditTextFormatting: false,
    canEditTextCurve: false,
    canUseColors: false,
    canEditColors: false,
    canUseStudio: false,
    canApplyStudioEffects: false,
    canUseZoom: true,
    canZoomIn: true,
    canZoomOut: true,
    canFitViewport: true,
    canResetViewport: true,
    canPanCanvas: true,
    canDownload: false,
    canDownloadCurrentView: false,
    canDownloadAllViews: false,
    canDownloadObjects: false,
    canDownloadDrawingZones: false,
    canExportJson: false,
    canImportJson: false,
    canViewDrawingAreas: false,
    canCreateDrawingAreas: false,
    canEditDrawingAreas: false,
    canDeleteDrawingAreas: false,
    canViewFixedSlots: false,
    canCreateFixedSlots: false,
    canEditFixedSlots: false,
    canDeleteFixedSlots: false,
    canUseStateTools: false,

    // Elements: viewers can browse/apply, but cannot modify catalog.
    canViewElements: true,
    canAddElements: false,
    canEditElements: false,
    canEditElementVariations: false,
    canMoveElements: false,
    canDeleteElements: false,
  },
};

// Runtime role registry (allows custom roles at boot or at runtime).
const ROLE_REGISTRY: Record<string, AsukaPermissions> = { ...ROLE_PERMISSIONS };

/** Define or override a role at runtime. */
export function defineRole(
  role: string,
  patch: Partial<AsukaPermissions> | AsukaPermissions,
): AsukaPermissions {
  const next = mergePermissions(DEFAULT_PERMISSIONS, patch as any);
  ROLE_REGISTRY[role] = next;
  return next;
}

/** List available roles (built-in + custom). */
export function listRoles(): string[] {
  return Object.keys(ROLE_REGISTRY);
}

/** Get the permission preset for a role (falls back to DEFAULT_PERMISSIONS). */
export function getRolePreset(role: string): AsukaPermissions {
  return ROLE_REGISTRY[role] ?? DEFAULT_PERMISSIONS;
}

export function permissionsForRole(role: AsukaRole): AsukaPermissions {
  return getRolePreset(role as any);
}

export function mergeModuleOpen(
  base?: AsukaPermissions['moduleOpen'],
  patch?: AsukaPermissions['moduleOpen'],
): AsukaPermissions['moduleOpen'] | undefined {
  if (!base && !patch) return undefined;
  return { ...(base ?? {}), ...(patch ?? {}) };
}

/** Compute effective permissions for a given context (e.g. active view). */
export function getEffectivePermissions(
  base: AsukaPermissions,
  patch?: Partial<AsukaPermissions> | null,
): AsukaPermissions {
  const merged = mergePermissions(base, patch);
  return {
    ...merged,
    moduleOpen: mergeModuleOpen(base.moduleOpen, (patch as any)?.moduleOpen),
  };
}

export function mergePermissions(
  base: AsukaPermissions,
  patch?: Partial<AsukaPermissions> | null,
): AsukaPermissions {
  return { ...base, ...(patch ?? {}) };
}

export function canOpenModuleId(perms: AsukaPermissions, id: ModuleId): boolean {
  const override = perms.moduleOpen?.[id];
  if (override === false) return false;

  // Fine-grained pricing visibility: if you can't view pricing, you can't open the Pricing module.
  if (id === 'pricing' && (perms as any).canViewPricing === false) return false;
  // If you can't edit pricing rules, hide the dedicated rules editor.
  if (id === 'pricingRules' && (perms as any).canEditPricingRules === false) return false;

  // Dev state tools are guarded by their own permission.
  if (id === 'state' && (perms as any).canUseStateTools === false) return false;

  // Elements modules
  if (id === 'elements' && (perms as any).canViewElements === false) return false;
  if (id === 'element-variation-picker' && (perms as any).canViewElements === false) return false;
  if (
    id === 'element-editor' &&
    (perms as any).canAddElements === false &&
    (perms as any).canEditElements === false &&
    (perms as any).canEditElementVariations === false
  )
    return false;

  // Action tools
  if (id === 'magnifier' && (perms as any).canUseMagnifier === false) return false;
  if (id === 'zoom' && (perms as any).canUseZoom === false) return false;

  // Design/content modules
  if (
    id === 'history' &&
    (perms as any).canUndo === false &&
    (perms as any).canRedo === false &&
    (perms as any).canReset === false
  )
    return false;
  if (id === 'designs' && (perms as any).canViewDesigns === false) return false;
  if (id === 'layers' && (perms as any).canViewLayers === false) return false;
  if (id === 'colors' && (perms as any).canUseColors === false) return false;
  if (id === 'studio' && (perms as any).canUseStudio === false) return false;
  if (id === 'image' && (perms as any).canOpenImages === false) return false;
  if (String(id).startsWith('image-') && (
    (perms as any).canOpenImages === false
    || (perms as any).canAddImage === false
  )) return false;
  if (id === 'image-upload' && (perms as any).canUploadImage === false) return false;
  if (
    id === 'image-facebook'
    && (
      (perms as any).canUseExternalImageLibraries === false
      || (perms as any).canUseFacebookImages === false
    )
  ) return false;
  if (
    id === 'image-pixabay'
    && (
      (perms as any).canUseExternalImageLibraries === false
      || (perms as any).canUsePixabayImages === false
    )
  ) return false;
  if (
    id === 'image-pexels'
    && (
      (perms as any).canUseExternalImageLibraries === false
      || (perms as any).canUsePexelsImages === false
    )
  ) return false;
  if (id === 'text' && (perms as any).canAddText === false && (perms as any).canEditText === false)
    return false;
  if (
    id === 'shapes' &&
    (perms as any).canAddShape === false &&
    (perms as any).canDrawShape === false
  )
    return false;
  if (
    id === 'transform' &&
    (perms as any).canMoveObject === false &&
    (perms as any).canResizeObject === false &&
    (perms as any).canRotateObject === false
  )
    return false;
  if (id === 'font-family' && (perms as any).canEditFontFamily === false) return false;
  if (id === 'text-formatting' && (perms as any).canEditTextFormatting === false) return false;
  if (id === 'text-curve' && (perms as any).canEditTextCurve === false) return false;
  if (id === 'download' && (perms as any).canDownload === false) return false;
  if (id === 'views' && (perms as any).canViewViews === false) return false;
  if (
    (id === 'drawingAreas' || id === 'drawing-areas') &&
    (perms as any).canViewDrawingAreas === false
  )
    return false;
  if (
    (id === 'marker' || id === 'markerEditor' || id === 'fixed-slots') &&
    (perms as any).canViewFixedSlots === false
  )
    return false;
  if (id === 'assembly' && (perms as any).canViewAssembly === false) return false;

  return perms.canOpenModule;
}

/**
 * Contextual object tools are governed by their editing capability, not by the
 * module's presence in the surrounding layout. This prevents an integration
 * from hiding a standalone panel and accidentally removing the same tool from
 * the selection toolbar.
 */
export function canOpenSelectionModuleId(perms: AsukaPermissions, id: ModuleId): boolean {
  if (perms.canOpenModule === false) return false;

  if (id === 'font-family') return perms.canEditFontFamily !== false;
  if (id === 'text-formatting') return perms.canEditTextFormatting !== false;
  if (id === 'text-curve') return perms.canEditTextCurve !== false;
  if (id === 'colors') return perms.canUseColors !== false;
  if (id === 'studio') return perms.canUseStudio !== false;
  if (id === 'transform' || id === 'position') {
    return perms.canMoveObject !== false
      || perms.canResizeObject !== false
      || perms.canRotateObject !== false;
  }

  return canOpenModuleId(perms, id);
}
