/**
 * Compatibility Algorithm for Dating Matches
 *
 * Calculates compatibility scores between characters based on:
 * - Shared interests
 * - Age compatibility
 * - Education level
 * - Wealth/prestige
 */

export interface CompatibilityPerson {
  likes?: string[];
  ageYears?: number;
  age_years?: number;
  educationLevel?: number;
  education_level?: number;
  prestige?: number;
}

/**
 * Calculate compatibility score (0-100) between player and potential match
 *
 * Factors:
 * - Shared interests: +5 per match
 * - Age difference: +15 (0-3 years), +5 (4-5 years), -15 (>10 years)
 * - Education level: +10 (same), +5 (±1 level)
 * - Wealth/prestige: +10 (similar), -5 (very different)
 *
 * @param player - Player character data
 * @param match - Potential match character data
 * @returns Compatibility score between 0 and 100
 */
export function calculateCompatibility(
  player: CompatibilityPerson,
  match: CompatibilityPerson
): number {
  let score = 50; // Base compatibility

  // Shared interests
  const playerInterests = new Set(player.likes ?? []);
  const matchInterests = new Set(match.likes ?? []);
  const commonInterests = [...playerInterests].filter(x => matchInterests.has(x));
  score += commonInterests.length * 5;

  // Age compatibility
  const playerAge = player.ageYears ?? player.age_years ?? 18;
  const matchAge = match.ageYears ?? match.age_years ?? 18;
  const ageDiff = Math.abs(playerAge - matchAge);

  if (ageDiff <= 3) {
    score += 15;
  } else if (ageDiff <= 5) {
    score += 5;
  } else if (ageDiff > 10) {
    score -= 15;
  }

  // Education compatibility
  const playerEdu = player.educationLevel ?? player.education_level ?? 0;
  const matchEdu = match.educationLevel ?? match.education_level ?? 0;
  const eduDiff = Math.abs(playerEdu - matchEdu);

  if (eduDiff === 0) {
    score += 10;
  } else if (eduDiff === 1) {
    score += 5;
  }

  // Wealth/prestige compatibility
  const playerPrestige = player.prestige ?? 0;
  const matchPrestige = match.prestige ?? 0;
  const prestigeDiff = Math.abs(playerPrestige - matchPrestige);

  if (prestigeDiff < 20) {
    score += 10;
  } else if (prestigeDiff > 50) {
    score -= 5;
  }

  // Clamp score to 0-100 range
  return Math.max(0, Math.min(100, score));
}

/**
 * Get compatibility level description based on score
 */
export function getCompatibilityLevel(score: number): {
  level: 'excellent' | 'good' | 'moderate' | 'low' | 'poor';
  description: string;
} {
  if (score >= 85) {
    return { level: 'excellent', description: 'Perfect match!' };
  } else if (score >= 70) {
    return { level: 'good', description: 'Great compatibility' };
  } else if (score >= 50) {
    return { level: 'moderate', description: 'Decent compatibility' };
  } else if (score >= 30) {
    return { level: 'low', description: 'Some compatibility' };
  } else {
    return { level: 'poor', description: 'Low compatibility' };
  }
}

/**
 * Get detailed compatibility breakdown
 */
export function getCompatibilityBreakdown(
  player: CompatibilityPerson,
  match: CompatibilityPerson
): {
  total: number;
  breakdown: {
    interests: { score: number; common: string[] };
    age: { score: number; difference: number };
    education: { score: number; difference: number };
    prestige: { score: number; difference: number };
  };
} {
  // Shared interests
  const playerInterests = new Set(player.likes ?? []);
  const matchInterests = new Set(match.likes ?? []);
  const commonInterests = [...playerInterests].filter(x => matchInterests.has(x));
  const interestsScore = commonInterests.length * 5;

  // Age
  const playerAge = player.ageYears ?? player.age_years ?? 18;
  const matchAge = match.ageYears ?? match.age_years ?? 18;
  const ageDiff = Math.abs(playerAge - matchAge);
  let ageScore = 0;
  if (ageDiff <= 3) ageScore = 15;
  else if (ageDiff <= 5) ageScore = 5;
  else if (ageDiff > 10) ageScore = -15;

  // Education
  const playerEdu = player.educationLevel ?? player.education_level ?? 0;
  const matchEdu = match.educationLevel ?? match.education_level ?? 0;
  const eduDiff = Math.abs(playerEdu - matchEdu);
  let eduScore = 0;
  if (eduDiff === 0) eduScore = 10;
  else if (eduDiff === 1) eduScore = 5;

  // Prestige
  const playerPrestige = player.prestige ?? 0;
  const matchPrestige = match.prestige ?? 0;
  const prestigeDiff = Math.abs(playerPrestige - matchPrestige);
  let prestigeScore = 0;
  if (prestigeDiff < 20) prestigeScore = 10;
  else if (prestigeDiff > 50) prestigeScore = -5;

  const total = Math.max(0, Math.min(100, 50 + interestsScore + ageScore + eduScore + prestigeScore));

  return {
    total,
    breakdown: {
      interests: { score: interestsScore, common: commonInterests },
      age: { score: ageScore, difference: ageDiff },
      education: { score: eduScore, difference: eduDiff },
      prestige: { score: prestigeScore, difference: prestigeDiff },
    },
  };
}
