import React, { type ReactNode } from 'react';
import {
  SortAscendingSmall,
  SortDescendingSmall,
  ContentFilterSmall,
  HiddenSmall,
  DeleteSmall,
  EditSmall,
  FlagSmall,
  DuplicateSmall,
  ArchiveSmall,
} from '@wix/wix-ui-icons-common';
import { withoutDefaults } from '@wix/bex-core';
import { cairoCtaClicked } from '@wix/bex-core/bi';
import type { ReportBI, Translate, TranslationsKeys } from '@wix/bex-core';
import type { HeaderAction, FieldActionsMenuConfig } from './headerActionTypes';

export type FieldActionKey =
  | 'editField'
  | 'makePrimary'
  | 'hideColumn'
  | 'duplicateField'
  | 'duplicateFieldWithContent'
  | 'sortAscending'
  | 'sortDescending'
  | 'filter'
  | 'archive'
  | 'delete';

interface FieldActionDef {
  /** Fallback (English) label, used when no `labelKey` is set or no translate fn is passed. */
  label: string;
  /** Translation key; when set and a translate fn is passed to buildFieldActionGroups, used instead of `label`. */
  labelKey?: TranslationsKeys;
  /** Shared data-hook for the rendered menu item — the same for every source and surface. */
  dataHook: string;
  /** BI name reported via `cairoCtaClicked`; set only on the field-management actions that report. */
  ctaName?: string;
  icon: ReactNode;
  skin?: 'destructive';
}

export const FIELD_ACTIONS: Record<FieldActionKey, FieldActionDef> = {
  editField: {
    label: 'Edit Field',
    labelKey: 'cairo.customFields.edit.CTA',
    dataHook: 'field-action-edit',
    ctaName: 'Edit',
    icon: <EditSmall />,
  },
  makePrimary: {
    label: 'Use as Primary Field',
    dataHook: 'field-action-make-primary',
    ctaName: 'Make Primary',
    icon: <FlagSmall />,
  },
  hideColumn: {
    label: 'Hide Column',
    dataHook: 'field-action-hide',
    icon: <HiddenSmall />,
  },
  duplicateField: {
    label: 'Duplicate Field',
    dataHook: 'field-action-duplicate',
    ctaName: 'Duplicate',
    icon: <DuplicateSmall />,
  },
  duplicateFieldWithContent: {
    label: 'Duplicate Field with Content',
    dataHook: 'field-action-duplicate-with-content',
    ctaName: 'Duplicate with Content',
    icon: <DuplicateSmall />,
  },
  sortAscending: {
    label: 'Sort Ascending',
    dataHook: 'field-action-sort-ascending',
    icon: <SortAscendingSmall />,
  },
  sortDescending: {
    label: 'Sort Descending',
    dataHook: 'field-action-sort-descending',
    icon: <SortDescendingSmall />,
  },
  filter: {
    label: 'Filter',
    dataHook: 'field-action-filter',
    icon: <ContentFilterSmall />,
  },
  archive: {
    label: 'Archive',
    labelKey: 'cairo.customFields.archive.CTA',
    dataHook: 'field-action-archive',
    ctaName: 'Archive',
    icon: <ArchiveSmall />,
  },
  delete: {
    label: 'Delete',
    labelKey: 'cairo.delete.button',
    dataHook: 'field-action-delete',
    ctaName: 'Delete',
    icon: <DeleteSmall />,
    skin: 'destructive',
  },
};

export type FieldActionHandlers = Partial<
  Record<FieldActionKey, (id: string) => void>
>;

export interface FieldActionHandlersConfig {
  handlers: FieldActionHandlers;
  loading?: Partial<Record<FieldActionKey, boolean>>;
  /** Per-action disabled state, owned by the source: a key present here renders
   *  that action disabled with the given tooltip. */
  disabledTooltips?: Partial<Record<FieldActionKey, string>>;
  /** Menu-level disabled reason: when set and there are no actions, the menu
   *  renders a disabled trigger with this tooltip (e.g. a read-only source). */
  disabledTooltip?: string;
}

export interface FieldActionsBIContext {
  reportBi: ReportBI;
  location: string;
  listSize: number;
}

const MENU_OPEN_CTA_NAME = 'More Actions Menu';

const MENU_DATA_HOOKS = {
  menuDataHook: 'field-actions-menu',
  buttonDataHook: 'field-actions-menu-button',
};

const reportFieldActionCta = (
  bi: FieldActionsBIContext,
  cta: {
    ctaName: string;
    ctaIndex: number;
    moreActionsIndex?: number;
    numCtas: number;
  },
) =>
  bi.reportBi(
    withoutDefaults(cairoCtaClicked)({
      ctaIndex: cta.ctaIndex,
      ctaName: cta.ctaName,
      filteredListSize: bi.listSize,
      isSelectAll: false,
      location: bi.location,
      moreActionsIndex: cta.moreActionsIndex,
      numCtas: cta.numCtas,
      numItems: 1,
      url: typeof window !== 'undefined' ? window.location.href : '',
    }),
  );

export function buildFieldActionGroups(args: {
  columnId: string;
  handlers: FieldActionHandlers;
  loading?: Partial<Record<FieldActionKey, boolean>>;
  /** Per-action disabled tooltips owned by the source (key present ⇒ disabled). */
  disabledTooltips?: Partial<Record<FieldActionKey, string>>;
  groups: FieldActionKey[][];
  /** When provided, labels use the registry's `labelKey` (falling back to `label`). */
  translate?: Translate;
  /** When provided, actions with a registry `ctaName` report `cairoCtaClicked` on click. */
  bi?: FieldActionsBIContext;
}): HeaderAction[][] {
  const {
    columnId,
    handlers,
    loading,
    disabledTooltips,
    groups,
    translate,
    bi,
  } = args;

  // BI-eligible actions (have a handler + a ctaName), in menu order — gives a
  // stable ctaIndex / numCtas no matter which source built the menu.
  const biKeys = groups
    .flat()
    .filter((key) => handlers[key] && FIELD_ACTIONS[key].ctaName);

  return groups
    .map((group) =>
      group.flatMap((key): HeaderAction[] => {
        const handler = handlers[key];
        if (!handler) {
          return [];
        }
        const def = FIELD_ACTIONS[key];
        const disabledTooltip = disabledTooltips?.[key];
        const ctaIndex =
          bi && def.ctaName ? biKeys.indexOf(key) + 1 : undefined;
        return [
          {
            label:
              translate && def.labelKey ? translate(def.labelKey) : def.label,
            dataHook: def.dataHook,
            icon: def.icon,
            skin: def.skin,
            onClick: () => {
              if (bi && def.ctaName && ctaIndex) {
                reportFieldActionCta(bi, {
                  ctaName: def.ctaName,
                  ctaIndex,
                  moreActionsIndex: ctaIndex,
                  numCtas: biKeys.length,
                });
              }
              handler(columnId);
            },
            loading: loading?.[key],
            disabled: disabledTooltip !== undefined,
            disabledTooltip,
          },
        ];
      }),
    )
    .filter((g) => g.length > 0);
}

export function buildFieldActionsMenu(args: {
  fieldId: string;
  config: FieldActionHandlersConfig | null;
  groups: FieldActionKey[][];
  translate: Translate;
  tooltipContent?: string;
  bi?: FieldActionsBIContext;
}): FieldActionsMenuConfig | null {
  const { fieldId, config, groups, translate, tooltipContent, bi } = args;

  const actions = config
    ? buildFieldActionGroups({
        columnId: fieldId,
        handlers: config.handlers,
        loading: config.loading,
        disabledTooltips: config.disabledTooltips,
        groups,
        translate,
        bi,
      })
    : [];

  if (actions.length === 0) {
    return config?.disabledTooltip
      ? {
          actions: [],
          disabledTooltip: config.disabledTooltip,
          tooltipContent,
          ...MENU_DATA_HOOKS,
        }
      : null;
  }

  const numCtas = actions.flat().length;
  return {
    actions,
    tooltipContent,
    ...MENU_DATA_HOOKS,
    onShow: bi
      ? () =>
          reportFieldActionCta(bi, {
            ctaName: MENU_OPEN_CTA_NAME,
            ctaIndex: 0,
            numCtas,
          })
      : undefined,
  };
}
