/**
 * Organization Management Validators
 *
 * Validation logic for organization operations including staff invitations,
 * role updates, and invitation acceptance.
 *
 * @module lib/validators/organization.validator
 */

import validator from 'validator';
import type { OrgRole } from '@/lib/types/organization.types';

// ============================================
// VALIDATION RULES CONFIGURATION
// ============================================

export const ORGANIZATION_VALIDATION_RULES = {
  /** Minimum name length */
  NAME_MIN_LENGTH: 2,

  /** Maximum name length */
  NAME_MAX_LENGTH: 100,

  /** Minimum invitation token length */
  TOKEN_MIN_LENGTH: 32,

  /** Minimum password length */
  PASSWORD_MIN_LENGTH: 12,

  /** Maximum password length */
  PASSWORD_MAX_LENGTH: 128,

  /** Allowed roles for invitation */
  ALLOWED_INVITATION_ROLES: ['ADMIN', 'STAFF'] as const,

  /** All valid organization roles */
  VALID_ORG_ROLES: ['OWNER', 'ADMIN', 'STAFF'] as const,
} as const;

// ============================================
// TYPE DEFINITIONS
// ============================================

export interface ValidationError {
  field: string;
  message: string;
  code: string;
}

export interface InviteStaffRequest {
  email: string;
  name?: string;
  role: 'ADMIN' | 'STAFF';
}

export interface AcceptInvitationRequest {
  token: string;
  password: string;
  name?: string;
}

export interface UpdateMemberRoleRequest {
  memberId: string;
  role: 'ADMIN' | 'STAFF';
}

// ============================================
// STAFF INVITATION VALIDATORS
// ============================================

/**
 * Validate staff invitation request
 *
 * @param data - Invitation data to validate
 * @returns Array of validation errors (empty if valid)
 */
export function validateInviteStaffRequest(
  data: Partial<InviteStaffRequest>
): ValidationError[] {
  const errors: ValidationError[] = [];

  // Validate email
  if (!data.email || data.email.trim().length === 0) {
    errors.push({
      field: 'email',
      message: 'Email is required',
      code: 'EMAIL_REQUIRED',
    });
  } else if (!validator.isEmail(data.email)) {
    errors.push({
      field: 'email',
      message: 'Invalid email address',
      code: 'EMAIL_INVALID',
    });
  }

  // Validate name (optional but check length if provided)
  if (data.name !== undefined && data.name !== null) {
    const trimmedName = data.name.trim();
    if (trimmedName.length > 0) {
      if (trimmedName.length < ORGANIZATION_VALIDATION_RULES.NAME_MIN_LENGTH) {
        errors.push({
          field: 'name',
          message: `Name must be at least ${ORGANIZATION_VALIDATION_RULES.NAME_MIN_LENGTH} characters`,
          code: 'NAME_TOO_SHORT',
        });
      } else if (trimmedName.length > ORGANIZATION_VALIDATION_RULES.NAME_MAX_LENGTH) {
        errors.push({
          field: 'name',
          message: `Name must be less than ${ORGANIZATION_VALIDATION_RULES.NAME_MAX_LENGTH} characters`,
          code: 'NAME_TOO_LONG',
        });
      }
    }
  }

  // Validate role
  if (!data.role) {
    errors.push({
      field: 'role',
      message: 'Role is required',
      code: 'ROLE_REQUIRED',
    });
  } else if (!ORGANIZATION_VALIDATION_RULES.ALLOWED_INVITATION_ROLES.includes(data.role as any)) {
    errors.push({
      field: 'role',
      message: 'Role must be either ADMIN or STAFF',
      code: 'ROLE_INVALID',
    });
  }

  return errors;
}

/**
 * Quick validation check for invite staff request
 */
export function isInviteStaffRequestValid(data: Partial<InviteStaffRequest>): boolean {
  return validateInviteStaffRequest(data).length === 0;
}

// ============================================
// INVITATION ACCEPTANCE VALIDATORS
// ============================================

/**
 * Validate invitation acceptance request
 *
 * @param data - Acceptance data to validate
 * @returns Array of validation errors (empty if valid)
 */
export function validateAcceptInvitationRequest(
  data: Partial<AcceptInvitationRequest>
): ValidationError[] {
  const errors: ValidationError[] = [];

  // Validate token
  if (!data.token || data.token.trim().length === 0) {
    errors.push({
      field: 'token',
      message: 'Invitation token is required',
      code: 'TOKEN_REQUIRED',
    });
  } else if (data.token.trim().length < ORGANIZATION_VALIDATION_RULES.TOKEN_MIN_LENGTH) {
    errors.push({
      field: 'token',
      message: 'Invalid invitation token',
      code: 'TOKEN_INVALID',
    });
  }

  // Validate password
  if (!data.password || data.password.length === 0) {
    errors.push({
      field: 'password',
      message: 'Password is required',
      code: 'PASSWORD_REQUIRED',
    });
  } else {
    // Check minimum length
    if (data.password.length < ORGANIZATION_VALIDATION_RULES.PASSWORD_MIN_LENGTH) {
      errors.push({
        field: 'password',
        message: `Password must be at least ${ORGANIZATION_VALIDATION_RULES.PASSWORD_MIN_LENGTH} characters`,
        code: 'PASSWORD_TOO_SHORT',
      });
    }

    // Check maximum length
    if (data.password.length > ORGANIZATION_VALIDATION_RULES.PASSWORD_MAX_LENGTH) {
      errors.push({
        field: 'password',
        message: `Password must be less than ${ORGANIZATION_VALIDATION_RULES.PASSWORD_MAX_LENGTH} characters`,
        code: 'PASSWORD_TOO_LONG',
      });
    }

    // Check password strength
    const hasUpperCase = /[A-Z]/.test(data.password);
    const hasLowerCase = /[a-z]/.test(data.password);
    const hasNumber = /[0-9]/.test(data.password);
    const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(data.password);

    if (!hasUpperCase || !hasLowerCase || !hasNumber || !hasSpecialChar) {
      errors.push({
        field: 'password',
        message: 'Password must contain uppercase, lowercase, number, and special character',
        code: 'PASSWORD_WEAK',
      });
    }
  }

  // Validate name (optional but check length if provided)
  if (data.name !== undefined && data.name !== null) {
    const trimmedName = data.name.trim();
    if (trimmedName.length > 0) {
      if (trimmedName.length < ORGANIZATION_VALIDATION_RULES.NAME_MIN_LENGTH) {
        errors.push({
          field: 'name',
          message: `Name must be at least ${ORGANIZATION_VALIDATION_RULES.NAME_MIN_LENGTH} characters`,
          code: 'NAME_TOO_SHORT',
        });
      } else if (trimmedName.length > ORGANIZATION_VALIDATION_RULES.NAME_MAX_LENGTH) {
        errors.push({
          field: 'name',
          message: `Name must be less than ${ORGANIZATION_VALIDATION_RULES.NAME_MAX_LENGTH} characters`,
          code: 'NAME_TOO_LONG',
        });
      }
    }
  }

  return errors;
}

/**
 * Quick validation check for accept invitation request
 */
export function isAcceptInvitationRequestValid(data: Partial<AcceptInvitationRequest>): boolean {
  return validateAcceptInvitationRequest(data).length === 0;
}

// ============================================
// MEMBER ROLE UPDATE VALIDATORS
// ============================================

/**
 * Validate member role update request
 *
 * @param data - Role update data to validate
 * @returns Array of validation errors (empty if valid)
 */
export function validateUpdateMemberRoleRequest(
  data: Partial<UpdateMemberRoleRequest>
): ValidationError[] {
  const errors: ValidationError[] = [];

  // Validate memberId
  if (!data.memberId || data.memberId.trim().length === 0) {
    errors.push({
      field: 'memberId',
      message: 'Member ID is required',
      code: 'MEMBER_ID_REQUIRED',
    });
  }

  // Validate role
  if (!data.role) {
    errors.push({
      field: 'role',
      message: 'Role is required',
      code: 'ROLE_REQUIRED',
    });
  } else if (!ORGANIZATION_VALIDATION_RULES.ALLOWED_INVITATION_ROLES.includes(data.role as any)) {
    errors.push({
      field: 'role',
      message: 'Role must be either ADMIN or STAFF',
      code: 'ROLE_INVALID',
    });
  }

  return errors;
}

/**
 * Quick validation check for update member role request
 */
export function isUpdateMemberRoleRequestValid(data: Partial<UpdateMemberRoleRequest>): boolean {
  return validateUpdateMemberRoleRequest(data).length === 0;
}

// ============================================
// GENERAL VALIDATORS
// ============================================

/**
 * Validate organization role
 */
export function isValidOrgRole(role: string): role is OrgRole {
  return ORGANIZATION_VALIDATION_RULES.VALID_ORG_ROLES.includes(role as any);
}

/**
 * Validate invitation role (cannot be OWNER)
 */
export function isValidInvitationRole(role: string): role is 'ADMIN' | 'STAFF' {
  return ORGANIZATION_VALIDATION_RULES.ALLOWED_INVITATION_ROLES.includes(role as any);
}

/**
 * Sanitize email address
 */
export function sanitizeEmail(email: string): string {
  return email.trim().toLowerCase();
}

/**
 * Sanitize name
 */
export function sanitizeName(name: string): string {
  return name.trim();
}

/**
 * Validate CUID format (for member IDs)
 */
export function isValidCuid(id: string): boolean {
  // CUID format: starts with 'c', 25 characters, alphanumeric
  const cuidRegex = /^c[a-z0-9]{24}$/;
  return cuidRegex.test(id);
}

/**
 * Validate email domain (optional additional check)
 */
export function isBusinessEmail(email: string): boolean {
  const freeEmailDomains = [
    'gmail.com',
    'yahoo.com',
    'hotmail.com',
    'outlook.com',
    'live.com',
    'aol.com',
    'icloud.com',
  ];

  const domain = email.split('@')[1]?.toLowerCase();
  return domain ? !freeEmailDomains.includes(domain) : false;
}

/**
 * Get user-friendly error message
 */
export function getErrorMessage(
  errors: ValidationError[],
  language: 'ar' | 'en' = 'en'
): string {
  if (errors.length === 0) return '';

  const messages = errors.map(e => e.message);

  if (language === 'ar') {
    return `يرجى تصحيح الأخطاء التالية: ${messages.join('، ')}`;
  }

  return `Please correct the following errors: ${messages.join(', ')}`;
}

/**
 * Format validation error for API response
 */
export function formatValidationErrors(errors: ValidationError[]): {
  message: string;
  errors: ValidationError[];
} {
  return {
    message: 'Validation failed',
    errors,
  };
}
