import React, { type ReactNode } from 'react';
import {
  SortAscendingSmall,
  SortDescendingSmall,
  ContentFilterSmall,
  HiddenSmall,
  DeleteSmall,
  EditSmall,
  FlagSmall,
  DuplicateSmall,
} from '@wix/wix-ui-icons-common';
import type { HeaderAction } from './headerActionTypes';

export interface FieldActionPermissions {
  schemaEditable?: boolean;
  addDisabled?: boolean;
  editDisabled?: boolean;
  deleteDisabled?: boolean;
}

export interface FieldActionColumn {
  isPrimary?: boolean;
  isSystem?: boolean;
  cellType?: string;
}

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

export type FieldActionDisableReason =
  | 'schemaNotEditable'
  | 'addDisabled'
  | 'editDisabled'
  | 'deleteDisabled'
  | 'alreadyPrimary'
  | 'systemField'
  | 'nonTextField';

interface FieldActionDef {
  label: string;
  icon: ReactNode;
  skin?: 'destructive';
  getDisableReason?: (
    col: FieldActionColumn,
    perms: FieldActionPermissions | undefined,
  ) => FieldActionDisableReason | null;
}

const getReadOnlySchemaReason = (
  perms: FieldActionPermissions | undefined,
): FieldActionDisableReason | null =>
  perms?.schemaEditable === false ? 'schemaNotEditable' : null;

const checkEditPerms = (
  col: FieldActionColumn,
  perms: FieldActionPermissions | undefined,
): FieldActionDisableReason | null => {
  const blocked = getReadOnlySchemaReason(perms);
  if (blocked) {
    return blocked;
  }
  if (perms?.editDisabled) {
    return 'editDisabled';
  }
  if (col.isSystem) {
    return 'systemField';
  }
  return null;
};

const checkAddPerms = (
  col: FieldActionColumn,
  perms: FieldActionPermissions | undefined,
): FieldActionDisableReason | null => {
  const blocked = getReadOnlySchemaReason(perms);
  if (blocked) {
    return blocked;
  }
  if (perms?.addDisabled) {
    return 'addDisabled';
  }
  if (col.isSystem) {
    return 'systemField';
  }
  return null;
};

const checkDeletePerms = (
  col: FieldActionColumn,
  perms: FieldActionPermissions | undefined,
): FieldActionDisableReason | null => {
  const blocked = getReadOnlySchemaReason(perms);
  if (blocked) {
    return blocked;
  }
  if (perms?.deleteDisabled) {
    return 'deleteDisabled';
  }
  if (col.isSystem) {
    return 'systemField';
  }
  if (col.isPrimary) {
    return 'alreadyPrimary';
  }
  return null;
};

export const FIELD_ACTIONS: Record<FieldActionKey, FieldActionDef> = {
  editField: {
    label: 'Edit Field',
    icon: <EditSmall />,
    getDisableReason: checkEditPerms,
  },
  makePrimary: {
    label: 'Use as Primary Field',
    icon: <FlagSmall />,
    getDisableReason: (col, perms) => {
      const blocked = getReadOnlySchemaReason(perms);
      if (blocked) {
        return blocked;
      }
      if (perms?.editDisabled) {
        return 'editDisabled';
      }
      if (col.isPrimary) {
        return 'alreadyPrimary';
      }
      if (col.isSystem) {
        return 'systemField';
      }
      if (col.cellType !== 'text') {
        return 'nonTextField';
      }
      return null;
    },
  },
  hideColumn: {
    label: 'Hide Column',
    icon: <HiddenSmall />,
  },
  duplicateField: {
    label: 'Duplicate Field',
    icon: <DuplicateSmall />,
    getDisableReason: checkAddPerms,
  },
  duplicateFieldWithContent: {
    label: 'Duplicate Field with Content',
    icon: <DuplicateSmall />,
    getDisableReason: checkAddPerms,
  },
  sortAscending: {
    label: 'Sort Ascending',
    icon: <SortAscendingSmall />,
  },
  sortDescending: {
    label: 'Sort Descending',
    icon: <SortDescendingSmall />,
  },
  filter: {
    label: 'Filter',
    icon: <ContentFilterSmall />,
  },
  delete: {
    label: 'Delete',
    icon: <DeleteSmall />,
    skin: 'destructive',
    getDisableReason: checkDeletePerms,
  },
};

export const FIELD_ACTION_DISABLE_REASON_TOOLTIPS: Record<
  FieldActionDisableReason,
  string
> = {
  schemaNotEditable: 'This schema is read-only.',
  addDisabled: 'Adding fields is disabled.',
  editDisabled: 'Editing fields is disabled.',
  deleteDisabled: 'Deleting fields is disabled.',
  alreadyPrimary: 'This is the primary field.',
  systemField: "System fields can't be modified.",
  nonTextField: 'Only text fields can be made primary.',
};

export function getFieldActionDisableReason(
  action: FieldActionKey,
  column: FieldActionColumn,
  permissions: FieldActionPermissions | undefined,
): FieldActionDisableReason | null {
  return FIELD_ACTIONS[action].getDisableReason?.(column, permissions) ?? null;
}

export function getFieldActionDisableState(
  action: FieldActionKey,
  column: FieldActionColumn,
  permissions: FieldActionPermissions | undefined,
): { disabled: boolean; disabledTooltip: string | undefined } {
  const reason = getFieldActionDisableReason(action, column, permissions);
  return {
    disabled: reason !== null,
    disabledTooltip: reason
      ? FIELD_ACTION_DISABLE_REASON_TOOLTIPS[reason]
      : undefined,
  };
}

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

export function buildFieldActionGroups(args: {
  column: FieldActionColumn & { id: string };
  permissions?: FieldActionPermissions;
  handlers: FieldActionHandlers;
  loading?: Partial<Record<FieldActionKey, boolean>>;
  groups: FieldActionKey[][];
}): HeaderAction[][] {
  const { column, permissions, handlers, loading, groups } = args;
  return groups
    .map((group) =>
      group.flatMap((key): HeaderAction[] => {
        const handler = handlers[key];
        if (!handler) {
          return [];
        }
        const def = FIELD_ACTIONS[key];
        const disable = getFieldActionDisableState(key, column, permissions);
        return [
          {
            label: def.label,
            icon: def.icon,
            skin: def.skin,
            onClick: () => handler(column.id),
            loading: loading?.[key],
            ...disable,
          },
        ];
      }),
    )
    .filter((g) => g.length > 0);
}
