/**
 * SAMMS ENTERPRISE - Action System
 * Centralized action registry for action-based UI
 * Provides contextual actions, keyboard shortcuts, and action handlers
 */

import { useCallback, useState, useEffect, createContext, useContext, ReactNode } from 'react';

// Action Types
export interface Action {
  id: string;
  label: string;
  description?: string;
  icon?: string;
  category: ActionCategory;
  shortcut?: KeyboardShortcut;
  handler: ActionHandler;
  condition?: ActionCondition;
  permissions?: string[];
  confirm?: ConfirmConfig;
  loading?: boolean;
  disabled?: boolean;
  visible?: boolean;
  priority?: number;
  group?: string;
}

export type ActionCategory = 
  | 'navigation'
  | 'create'
  | 'edit'
  | 'delete'
  | 'export'
  | 'import'
  | 'workflow'
  | 'ai'
  | 'system'
  | 'custom';

export interface KeyboardShortcut {
  key: string;
  modifiers?: ('ctrl' | 'alt' | 'shift' | 'meta')[];
  platform?: 'mac' | 'windows' | 'linux';
}

export type ActionHandler = (context?: ActionContext) => Promise<void> | void;

export interface ActionCondition {
  check: (context?: ActionContext) => boolean;
  message?: string;
}

export interface ConfirmConfig {
  title: string;
  message: string;
  confirmText?: string;
  cancelText?: string;
  variant?: 'default' | 'destructive';
}

export interface ActionContext {
  selectedIds?: string[];
  entityId?: string;
  entityType?: string;
  data?: Record<string, unknown>;
  parentAction?: string;
  [key: string]: unknown;
}

// Action Registry
class ActionRegistry {
  private actions: Map<string, Action> = new Map();
  private listeners: Set<() => void> = new Set();
  private shortcuts: Map<string, string> = new Map();

  register(action: Action): void {
    this.actions.set(action.id, action);
    
    if (action.shortcut) {
      const shortcutKey = this.getShortcutKey(action.shortcut);
      this.shortcuts.set(shortcutKey, action.id);
    }
    
    this.notifyListeners();
  }

  unregister(actionId: string): void {
    const action = this.actions.get(actionId);
    if (action?.shortcut) {
      const shortcutKey = this.getShortcutKey(action.shortcut);
      this.shortcuts.delete(shortcutKey);
    }
    this.actions.delete(actionId);
    this.notifyListeners();
  }

  get(actionId: string): Action | undefined {
    return this.actions.get(actionId);
  }

  getAll(): Action[] {
    return Array.from(this.actions.values());
  }

  getByCategory(category: ActionCategory): Action[] {
    return this.getAll().filter(action => action.category === category);
  }

  getAvailable(context?: ActionContext): Action[] {
    return this.getAll().filter(action => {
      if (action.visible === false) return false;
      if (action.disabled) return false;
      if (action.condition && !action.condition.check(context)) return false;
      return true;
    });
  }

  getShortcutAction(shortcut: KeyboardShortcut): Action | undefined {
    const shortcutKey = this.getShortcutKey(shortcut);
    const actionId = this.shortcuts.get(shortcutKey);
    return actionId ? this.actions.get(actionId) : undefined;
  }

  private getShortcutKey(shortcut: KeyboardShortcut): string {
    const modifiers = shortcut.modifiers || [];
    return [...modifiers.sort(), shortcut.key.toLowerCase()].join('+');
  }

  subscribe(listener: () => void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }

  private notifyListeners(): void {
    this.listeners.forEach(listener => listener());
  }
}

// Global Action Registry Instance
export const actionRegistry = new ActionRegistry();

// Action Context Provider
interface ActionContextValue {
  registry: ActionRegistry;
  executeAction: (actionId: string, context?: ActionContext) => Promise<void>;
  getActions: (category?: ActionCategory) => Action[];
  getAvailableActions: (context?: ActionContext) => Action[];
  registerAction: (action: Action) => void;
  unregisterAction: (actionId: string) => void;
}

const ActionContext = createContext<ActionContextValue | null>(null);

export function ActionProvider({ children }: { children: ReactNode }) {
  const [, forceUpdate] = useState({});

  useEffect(() => {
    const unsubscribe = actionRegistry.subscribe(() => forceUpdate({}));
    return unsubscribe;
  }, []);

  const executeAction = useCallback(async (actionId: string, context?: ActionContext) => {
    const action = actionRegistry.get(actionId);
    if (!action) {
      console.error(`Action not found: ${actionId}`);
      return;
    }

    if (action.disabled) {
      console.warn(`Action is disabled: ${actionId}`);
      return;
    }

    if (action.condition && !action.condition.check(context)) {
      console.warn(`Action condition not met: ${actionId}`);
      return;
    }

    try {
      await action.handler(context);
    } catch (error) {
      console.error(`Action execution failed: ${actionId}`, error);
      throw error;
    }
  }, []);

  const value: ActionContextValue = {
    registry: actionRegistry,
    executeAction,
    getActions: (category) => 
      category ? actionRegistry.getByCategory(category) : actionRegistry.getAll(),
    getAvailableActions: (context) => actionRegistry.getAvailable(context),
    registerAction: (action) => actionRegistry.register(action),
    unregisterAction: (actionId) => actionRegistry.unregister(actionId),
  };

  return (
    <ActionContext.Provider value={value}>
      {children}
    </ActionContext.Provider>
  );
}

export function useActions() {
  const context = useContext(ActionContext);
  if (!context) {
    throw new Error('useActions must be used within ActionProvider');
  }
  return context;
}

export function useAction(actionId: string) {
  const { executeAction, registry } = useActions();
  const [loading, setLoading] = useState(false);
  const action = registry.get(actionId);

  const execute = useCallback(async (context?: ActionContext) => {
    if (!action) return;
    setLoading(true);
    try {
      await executeAction(actionId, context);
    } finally {
      setLoading(false);
    }
  }, [action, actionId, executeAction]);

  return { action, execute, loading };
}

// Keyboard Shortcut Hook
export function useKeyboardShortcuts() {
  const { executeAction, registry } = useActions();

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      // Don't trigger shortcuts when typing in inputs
      if (event.target instanceof HTMLInputElement || 
          event.target instanceof HTMLTextAreaElement) {
        return;
      }

      const shortcut: KeyboardShortcut = {
        key: event.key,
        modifiers: [
          event.ctrlKey && 'ctrl',
          event.altKey && 'alt',
          event.shiftKey && 'shift',
          event.metaKey && 'meta',
        ].filter(Boolean) as ('ctrl' | 'alt' | 'shift' | 'meta')[],
      };

      const action = registry.getShortcutAction(shortcut);
      if (action) {
        event.preventDefault();
        executeAction(action.id);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [executeAction, registry]);
}

// Predefined Actions
export const defaultActions: Action[] = [
  // Navigation Actions
  {
    id: 'navigate.dashboard',
    label: 'Go to Dashboard',
    category: 'navigation',
    shortcut: { key: 'd', modifiers: ['ctrl'] },
    handler: () => { window.location.href = '/dashboard'; },
  },
  {
    id: 'navigate.search',
    label: 'Global Search',
    category: 'navigation',
    shortcut: { key: 'k', modifiers: ['ctrl'] },
    handler: () => { /* Opens command palette */ },
  },
  {
    id: 'navigate.settings',
    label: 'Open Settings',
    category: 'navigation',
    shortcut: { key: ',', modifiers: ['ctrl'] },
    handler: () => { window.location.href = '/settings'; },
  },
  
  // Create Actions
  {
    id: 'create.invoice',
    label: 'New Invoice',
    description: 'Create a new invoice',
    category: 'create',
    shortcut: { key: 'i', modifiers: ['ctrl', 'shift'] },
    handler: () => { window.location.href = '/invoices/new'; },
  },
  {
    id: 'create.journal-entry',
    label: 'New Journal Entry',
    description: 'Create a new journal entry',
    category: 'create',
    shortcut: { key: 'j', modifiers: ['ctrl', 'shift'] },
    handler: () => { window.location.href = '/accounting/journal-entries/new'; },
  },
  {
    id: 'create.employee',
    label: 'Add Employee',
    description: 'Add a new employee',
    category: 'create',
    shortcut: { key: 'e', modifiers: ['ctrl', 'shift'] },
    handler: () => { window.location.href = '/hr/employees/new'; },
  },
  {
    id: 'create.account',
    label: 'New Account',
    description: 'Create a new GL account',
    category: 'create',
    handler: () => { window.location.href = '/accounting/accounts/new'; },
  },
  
  // Export Actions
  {
    id: 'export.csv',
    label: 'Export to CSV',
    description: 'Export current view to CSV',
    category: 'export',
    shortcut: { key: 'e', modifiers: ['ctrl'] },
    handler: async (context) => {
      console.log('Exporting to CSV...', context);
      // Implementation would trigger CSV export
    },
  },
  {
    id: 'export.pdf',
    label: 'Export to PDF',
    description: 'Export current view to PDF',
    category: 'export',
    handler: async (context) => {
      console.log('Exporting to PDF...', context);
      // Implementation would trigger PDF export
    },
  },
  
  // AI Actions
  {
    id: 'ai.analyze',
    label: 'AI Analyze',
    description: 'Run AI analysis on selected data',
    category: 'ai',
    shortcut: { key: 'a', modifiers: ['ctrl', 'shift'] },
    handler: async (context) => {
      console.log('Running AI analysis...', context);
      // Implementation would trigger AI analysis
    },
  },
  {
    id: 'ai.suggest',
    label: 'AI Suggestions',
    description: 'Get AI-powered suggestions',
    category: 'ai',
    handler: async (context) => {
      console.log('Getting AI suggestions...', context);
    },
  },
  
  // System Actions
  {
    id: 'system.refresh',
    label: 'Refresh Data',
    category: 'system',
    shortcut: { key: 'r', modifiers: ['ctrl'] },
    handler: () => { window.location.reload(); },
  },
  {
    id: 'system.help',
    label: 'Help & Documentation',
    category: 'system',
    shortcut: { key: 'F1' },
    handler: () => { window.open('/help', '_blank'); },
  },
];

// Register default actions
defaultActions.forEach(action => actionRegistry.register(action));

// Utility functions for creating actions
export function createAction(
  id: string,
  config: Omit<Action, 'id'>
): Action {
  return { id, ...config };
}

export function createCrudActions(entityName: string, basePath: string): Action[] {
  return [
    {
      id: `${entityName}.create`,
      label: `New ${entityName}`,
      category: 'create',
      handler: () => { window.location.href = `${basePath}/new`; },
    },
    {
      id: `${entityName}.edit`,
      label: `Edit ${entityName}`,
      category: 'edit',
      condition: {
        check: (ctx) => !!ctx?.entityId,
        message: 'Select an item to edit',
      },
      handler: (ctx) => { window.location.href = `${basePath}/${ctx?.entityId}/edit`; },
    },
    {
      id: `${entityName}.delete`,
      label: `Delete ${entityName}`,
      category: 'delete',
      confirm: {
        title: `Delete ${entityName}`,
        message: `Are you sure you want to delete this ${entityName}? This action cannot be undone.`,
        variant: 'destructive',
      },
      condition: {
        check: (ctx) => !!ctx?.entityId,
        message: 'Select an item to delete',
      },
      handler: async (ctx) => {
        console.log(`Deleting ${entityName}:`, ctx?.entityId);
        // Implementation would call API
      },
    },
    {
      id: `${entityName}.export`,
      label: `Export ${entityName}s`,
      category: 'export',
      handler: async () => {
        console.log(`Exporting ${entityName}s...`);
      },
    },
  ];
}

export default actionRegistry;