import type { LayoutZoneId } from '../types/layout';

const SIDE_LAYOUT_ZONES = ['right', 'left'] as const satisfies readonly LayoutZoneId[];
const ALL_LAYOUT_ZONES = ['top', 'right', 'bottom', 'left'] as const satisfies readonly LayoutZoneId[];

export type ModuleLayoutPlacementKind = 'embedded' | 'trigger';

export interface ModuleLayoutPlacement {
  moduleId: string;
  kind: ModuleLayoutPlacementKind;
  zone: LayoutZoneId;
  zoneType: 'default' | 'panels' | 'inline';
  blockId: string;
  blockCollapsed: boolean;
  zoneCollapsed: boolean;
  renderMode: 'inline' | 'portal' | null;
}

const normalizeZoneType = (value: unknown): ModuleLayoutPlacement['zoneType'] => {
  const normalized = String(value ?? '').trim().toLowerCase();
  if (normalized === 'panels') return 'panels';
  if (normalized === 'inline') return 'inline';
  return 'default';
};

const isSideZoneRenderedAsTrigger = (state: any, zone: LayoutZoneId): boolean => {
  if (zone !== 'left' && zone !== 'right') return false;
  const breakpoint = String(state?.responsiveBreakpoint ?? '').trim().toLowerCase();
  const responsiveConfig = state?.responsiveConfig && typeof state.responsiveConfig === 'object'
    ? state.responsiveConfig
    : {};

  if (breakpoint === 'tablet') {
    return responsiveConfig?.drawerPanelsOnTablet !== false;
  }

  if (breakpoint !== 'mobile') return false;
  if (responsiveConfig?.moveSideZonesToBottomNav === false) return false;

  const configuredZones = Array.isArray(responsiveConfig?.bottomNavZones) && responsiveConfig.bottomNavZones.length > 0
    ? responsiveConfig.bottomNavZones.map((entry: unknown) => String(entry ?? '').trim())
    : ['left', 'right'];
  return configuredZones.includes(zone);
};

/**
 * Resolves where a module currently lives in the configured layout.
 *
 * Side zones using `inline` or `panels` render the module body directly and are
 * therefore returned as `embedded`. Default zones and top/bottom toolbars only
 * render a trigger, so contextual actions must open the regular module overlay.
 *
 * When the same module appears more than once, a visible embedded renderer wins,
 * followed by a hidden/collapsed embedded renderer, then a normal menu trigger.
 */
export function resolveModuleLayoutPlacement(state: any, moduleIdInput: unknown): ModuleLayoutPlacement | null {
  const moduleId = String(moduleIdInput ?? '').trim();
  if (!moduleId) return null;

  const blocksByZone = state?.blocksByZone && typeof state.blocksByZone === 'object'
    ? state.blocksByZone
    : {};
  const zoneType = state?.zoneType && typeof state.zoneType === 'object'
    ? state.zoneType
    : {};
  const zoneCollapsed = state?.zoneCollapsed && typeof state.zoneCollapsed === 'object'
    ? state.zoneCollapsed
    : {};

  const placements: ModuleLayoutPlacement[] = [];

  for (const zone of ALL_LAYOUT_ZONES) {
    const blocks = Array.isArray(blocksByZone?.[zone]) ? blocksByZone[zone] : [];
    const currentZoneType = normalizeZoneType(zoneType?.[zone]);
    const zoneCanEmbed = SIDE_LAYOUT_ZONES.includes(zone as any)
      && !isSideZoneRenderedAsTrigger(state, zone)
      && (currentZoneType === 'inline' || currentZoneType === 'panels');

    for (const block of blocks) {
      if (String(block?.kind ?? '').trim() !== moduleId) continue;
      const renderMode = block?.renderMode === 'inline' || block?.renderMode === 'portal'
        ? block.renderMode
        : null;
      const isPortal = renderMode === 'portal';
      placements.push({
        moduleId,
        kind: isPortal || zoneCanEmbed ? 'embedded' : 'trigger',
        zone,
        zoneType: currentZoneType,
        blockId: String(block?.id ?? '').trim(),
        blockCollapsed: !isPortal && currentZoneType === 'panels' && renderMode !== 'inline' && Boolean(block?.collapsed),
        zoneCollapsed: isPortal ? false : Boolean(zoneCollapsed?.[zone]),
        renderMode,
      });
    }
  }

  if (!placements.length) return null;

  const score = (placement: ModuleLayoutPlacement): number => {
    if (placement.kind !== 'embedded') return 0;
    if (!placement.zoneCollapsed && !placement.blockCollapsed) return 30;
    return 20;
  };

  return placements
    .map((placement, index) => ({ placement, index, score: score(placement) }))
    .sort((a, b) => b.score - a.score || a.index - b.index)[0]?.placement ?? null;
}

/** Returns true when the module body is mounted directly by a side layout zone. */
export function isModuleEmbeddedInLayout(state: any, moduleIdInput: unknown): boolean {
  return resolveModuleLayoutPlacement(state, moduleIdInput)?.kind === 'embedded';
}
