import { AbilityBuilder, PureAbility, AbilityClass } from '@casl/ability';

/**
 * Define all possible actions in the system
 */
export enum Action {
  Manage = 'manage', // Special: allows everything
  Create = 'create',
  Read = 'read',
  Update = 'update',
  Delete = 'delete',
  Approve = 'approve', // Special: for user approval
  UpdateStatus = 'update-status', // Special: for drivers to update event status
}

/**
 * Define all subjects (resources) in the system
 */
export type Subjects =
  | 'User'
  | 'VIP'
  | 'Driver'
  | 'ScheduleEvent'
  | 'Flight'
  | 'Vehicle'
  | 'Event'
  | 'EventTemplate'
  | 'all';

/**
 * Define the AppAbility type
 */
export type AppAbility = PureAbility<[Action, Subjects]>;

/**
 * User role type (must match backend)
 */
export type UserRole = 'ADMINISTRATOR' | 'COORDINATOR' | 'DRIVER';

/**
 * User interface (simplified from backend)
 */
export interface User {
  id: string;
  role: UserRole;
  isApproved: boolean;
  driver?: {
    id: string;
  } | null;
}

/**
 * Define abilities for a user based on their role
 */
export function defineAbilitiesFor(user: User | null): AppAbility {
  const { can, cannot, build } = new AbilityBuilder<AppAbility>(
    PureAbility as AbilityClass<AppAbility>,
  );

  if (!user) {
    // Not authenticated - no permissions
    return build();
  }

  // Define permissions based on role
  if (user.role === 'ADMINISTRATOR') {
    // Administrators can do everything
    can(Action.Manage, 'all');
  } else if (user.role === 'COORDINATOR') {
    // Coordinators have full access except user management
    can(Action.Read, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle', 'Event', 'EventTemplate']);
    can(Action.Create, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle', 'Event', 'EventTemplate']);
    can(Action.Update, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle', 'Event', 'EventTemplate']);
    can(Action.Delete, ['VIP', 'Driver', 'ScheduleEvent', 'Flight', 'Vehicle', 'Event', 'EventTemplate']);

    // Cannot manage users
    cannot(Action.Create, 'User');
    cannot(Action.Update, 'User');
    cannot(Action.Delete, 'User');
    cannot(Action.Approve, 'User');
  } else if (user.role === 'DRIVER') {
    // Drivers have very limited access - only their own data
    // They can read their own schedule events (filtered by backend)
    can(Action.Read, 'ScheduleEvent');

    // Drivers can update status of their own events
    can(Action.UpdateStatus, 'ScheduleEvent');

    // Drivers can read and update their own driver profile only
    can(Action.Read, 'Driver');
    can(Action.Update, 'Driver'); // For updating their own phone number

    // Cannot access other resources
    cannot(Action.Read, 'VIP'); // VIP info comes embedded in their assignments
    cannot(Action.Read, 'Vehicle'); // Vehicle info comes embedded in their assignments
    cannot(Action.Read, 'Flight');
    cannot(Action.Read, 'User');
  }

  return build();
}
