/**
 * Member Tiers Utility Service
 * 
 * Provides centralized tier determination logic for members
 * Replaces hardcoded default 'user' tier assignments with proper data-driven logic
 */

import type { KeycloakUserRepresentation } from '~/utils/types';

export type MemberTier = 'user' | 'board' | 'admin';

interface TierDeterminationResult {
  tier: MemberTier;
  source: 'portal_group' | 'keycloak_groups' | 'keycloak_roles' | 'nocodb' | 'default' | 'override';
  confidence: 'high' | 'medium' | 'low';
  reason: string;
}

/**
 * Determine member tier from NocoDB member data
 * This is the primary source of truth for member tiers
 */
export async function determineMemberTierFromNocoDB(memberId: string): Promise<TierDeterminationResult | null> {
  try {
    const { getMemberById } = await import('~/server/utils/nocodb');
    const member = await getMemberById(memberId);
    
    if (!member) {
      return null;
    }

    // Check portal_group field first (highest priority)
    if (member.portal_group) {
      const tier = mapPortalGroupToTier(member.portal_group);
      if (tier) {
        return {
          tier,
          source: 'portal_group',
          confidence: 'high',
          reason: `Member has portal_group: ${member.portal_group}`
        };
      }
    }

    // Check membership_type as secondary source
    if (member.membership_type) {
      const tier = mapMembershipTypeToTier(member.membership_type);
      if (tier) {
        return {
          tier,
          source: 'nocodb',
          confidence: 'medium',
          reason: `Derived from membership_type: ${member.membership_type}`
        };
      }
    }

    // Check if member has board position
    if (member.board_position || member.board_role) {
      return {
        tier: 'board',
        source: 'nocodb',
        confidence: 'high',
        reason: `Member has board position: ${member.board_position || member.board_role}`
      };
    }

    return null;
  } catch (error) {
    console.error('[member-tiers] Error fetching member from NocoDB:', error);
    return null;
  }
}

/**
 * Determine member tier from Keycloak user data
 * Used as fallback when NocoDB data is not available
 */
export function determineMemberTierFromKeycloak(user: KeycloakUserRepresentation): TierDeterminationResult {
  // Check user groups (primary method)
  if (user.groups && Array.isArray(user.groups)) {
    for (const group of user.groups) {
      const groupName = typeof group === 'string' ? group : group.name;
      if (groupName === 'admin' || groupName === '/admin') {
        return {
          tier: 'admin',
          source: 'keycloak_groups',
          confidence: 'high',
          reason: 'User is in admin group'
        };
      }
      if (groupName === 'board' || groupName === '/board') {
        return {
          tier: 'board',
          source: 'keycloak_groups',
          confidence: 'high',
          reason: 'User is in board group'
        };
      }
      if (groupName === 'user' || groupName === '/user' || groupName === '/users') {
        return {
          tier: 'user',
          source: 'keycloak_groups',
          confidence: 'high',
          reason: 'User is in user group'
        };
      }
    }
  }

  // Check user attributes
  if (user.attributes) {
    if (user.attributes.membershipTier) {
      const tier = Array.isArray(user.attributes.membershipTier) 
        ? user.attributes.membershipTier[0] 
        : user.attributes.membershipTier;
      
      if (isValidTier(tier)) {
        return {
          tier: tier as MemberTier,
          source: 'keycloak_groups',
          confidence: 'medium',
          reason: 'Tier from user attributes'
        };
      }
    }

    if (user.attributes.tier) {
      const tier = Array.isArray(user.attributes.tier) 
        ? user.attributes.tier[0] 
        : user.attributes.tier;
      
      if (isValidTier(tier)) {
        return {
          tier: tier as MemberTier,
          source: 'keycloak_groups',
          confidence: 'medium',
          reason: 'Tier from user attributes'
        };
      }
    }
  }

  // Check realm roles as last resort
  if (user.realmRoles && Array.isArray(user.realmRoles)) {
    if (user.realmRoles.includes('admin')) {
      return {
        tier: 'admin',
        source: 'keycloak_roles',
        confidence: 'medium',
        reason: 'User has admin realm role'
      };
    }
    if (user.realmRoles.includes('board')) {
      return {
        tier: 'board',
        source: 'keycloak_roles',
        confidence: 'medium',
        reason: 'User has board realm role'
      };
    }
  }

  // No tier information found - return null instead of defaulting
  return {
    tier: 'user',
    source: 'default',
    confidence: 'low',
    reason: 'No tier information found, requires manual assignment'
  };
}

/**
 * Determine member tier by email - combines all sources
 */
export async function determineMemberTierByEmail(email: string): Promise<TierDeterminationResult> {
  try {
    // First try to find member in NocoDB by email
    const { getMemberByEmail } = await import('~/server/utils/nocodb');
    const member = await getMemberByEmail(email);
    
    if (member && member.Id) {
      const nocodbResult = await determineMemberTierFromNocoDB(member.Id);
      if (nocodbResult && nocodbResult.confidence !== 'low') {
        return nocodbResult;
      }
    }

    // If not found in NocoDB or low confidence, check Keycloak
    const { createKeycloakAdminClient } = await import('~/server/utils/keycloak-admin');
    const keycloakAdmin = createKeycloakAdminClient();
    const users = await keycloakAdmin.findUserByEmail(email);
    
    if (users && users.length > 0) {
      const keycloakResult = determineMemberTierFromKeycloak(users[0]);
      if (keycloakResult.confidence !== 'low') {
        return keycloakResult;
      }
    }

    // Return default with low confidence if nothing found
    return {
      tier: 'user',
      source: 'default',
      confidence: 'low',
      reason: 'Unable to determine tier from available data sources'
    };
  } catch (error) {
    console.error('[member-tiers] Error determining tier by email:', error);
    return {
      tier: 'user',
      source: 'default',
      confidence: 'low',
      reason: 'Error occurred while determining tier'
    };
  }
}

/**
 * Map portal_group values to tiers
 */
function mapPortalGroupToTier(portalGroup: string): MemberTier | null {
  const normalized = portalGroup.toLowerCase().trim();
  
  switch (normalized) {
    case 'admin':
    case 'administrator':
      return 'admin';
    case 'board':
    case 'board_member':
    case 'board-member':
      return 'board';
    case 'user':
    case 'member':
    case 'regular':
      return 'user';
    default:
      return null;
  }
}

/**
 * Map membership_type to tier (fallback logic)
 */
function mapMembershipTypeToTier(membershipType: string): MemberTier | null {
  const normalized = membershipType.toLowerCase().trim();
  
  if (normalized.includes('board') || normalized.includes('executive') || normalized.includes('officer')) {
    return 'board';
  }
  
  if (normalized.includes('admin') || normalized.includes('staff')) {
    return 'admin';
  }
  
  if (normalized.includes('member') || normalized.includes('regular') || normalized.includes('standard')) {
    return 'user';
  }
  
  return null;
}

/**
 * Validate if a string is a valid tier
 */
function isValidTier(tier: string): boolean {
  return ['user', 'board', 'admin'].includes(tier);
}

/**
 * Update member tier in both NocoDB and Keycloak
 */
export async function updateMemberTier(
  memberId: string, 
  newTier: MemberTier,
  updateKeycloak: boolean = true
): Promise<{ success: boolean; message: string }> {
  try {
    // Update in NocoDB
    const { updateMember } = await import('~/server/utils/nocodb');
    await updateMember(memberId, {
      portal_group: newTier
    });
    
    if (updateKeycloak) {
      // Get member email from NocoDB
      const { getMemberById } = await import('~/server/utils/nocodb');
      const member = await getMemberById(memberId);
      
      if (member && member.email) {
        // Find user in Keycloak
        const { createKeycloakAdminClient } = await import('~/server/utils/keycloak-admin');
        const keycloakAdmin = createKeycloakAdminClient();
        const users = await keycloakAdmin.findUserByEmail(member.email);
        
        if (users && users.length > 0) {
          const userId = users[0].id;
          // Change user's primary group
          await keycloakAdmin.changeUserPrimaryGroup(userId, newTier);
        }
      }
    }
    
    return {
      success: true,
      message: `Successfully updated member tier to ${newTier}`
    };
  } catch (error: any) {
    console.error('[member-tiers] Error updating member tier:', error);
    return {
      success: false,
      message: error.message || 'Failed to update member tier'
    };
  }
}

/**
 * Audit and fix tier mismatches between NocoDB and Keycloak
 */
export async function auditAndFixTierMismatches(): Promise<{
  checked: number;
  mismatches: number;
  fixed: number;
  errors: string[];
}> {
  const results = {
    checked: 0,
    mismatches: 0,
    fixed: 0,
    errors: [] as string[]
  };

  try {
    const { getMembers } = await import('~/server/utils/nocodb');
    const members = await getMembers();
    
    if (!members?.list) {
      return results;
    }

    for (const member of members.list) {
      results.checked++;
      
      if (!member.email) continue;
      
      try {
        // Get tier from NocoDB
        const nocodbResult = await determineMemberTierFromNocoDB(member.Id);
        if (!nocodbResult) continue;
        
        // Get tier from Keycloak
        const { createKeycloakAdminClient } = await import('~/server/utils/keycloak-admin');
        const keycloakAdmin = createKeycloakAdminClient();
        const users = await keycloakAdmin.findUserByEmail(member.email);
        
        if (users && users.length > 0) {
          const keycloakResult = determineMemberTierFromKeycloak(users[0]);
          
          // Check for mismatch
          if (nocodbResult.tier !== keycloakResult.tier) {
            results.mismatches++;
            console.log(`[member-tiers] Tier mismatch for ${member.email}: NocoDB=${nocodbResult.tier}, Keycloak=${keycloakResult.tier}`);
            
            // Fix by updating Keycloak to match NocoDB (NocoDB is source of truth)
            try {
              await keycloakAdmin.changeUserPrimaryGroup(users[0].id, nocodbResult.tier);
              results.fixed++;
            } catch (fixError: any) {
              results.errors.push(`Failed to fix tier for ${member.email}: ${fixError.message}`);
            }
          }
        }
      } catch (error: any) {
        results.errors.push(`Error checking ${member.email}: ${error.message}`);
      }
    }
    
    return results;
  } catch (error: any) {
    console.error('[member-tiers] Error in audit:', error);
    results.errors.push(`Fatal error: ${error.message}`);
    return results;
  }
}