/**
 * Dating Match Logic
 *
 * Handles:
 * - Attempting matches between player and NPCs
 * - Recording match attempts
 * - Integrating compatibility algorithm
 * - Supporting serendipity (random matches)
 */

import { calculateCompatibility, CompatibilityPerson } from './compatibility.js';

export interface MatchResult {
  success: boolean;
  compatibility: number;
  reason?: string;
  serendipity?: boolean;
}

export interface MatchAttempt {
  playerId: string;
  targetId: string;
  compatibilityScore: number;
  success: boolean;
  attemptedAt: Date;
  reason?: string;
}

export interface MatchHistory {
  targetId: string;
  targetName: string;
  compatibilityScore: number;
  success: boolean;
  attemptedAt: Date;
}

export interface MatchSuccessRate {
  totalAttempts: number;
  successfulMatches: number;
  successRate: number;
  avgCompatibility: number;
}

// In-memory storage for match attempts (replace with database in production)
const matchAttempts: MatchAttempt[] = [];

/**
 * Attempt to match with target using compatibility algorithm.
 *
 * The match succeeds if:
 * - Compatibility score > 60, OR
 * - Random "serendipity" factor (20% chance)
 *
 * @param player - Player character data
 * @param target - Target character data
 * @param playerId - Player's ID
 * @param targetId - Target's ID
 * @returns Match result with success status and compatibility score
 */
export function attemptMatch(
  player: CompatibilityPerson,
  target: CompatibilityPerson,
  playerId: string,
  targetId: string
): MatchResult {
  // Calculate compatibility
  const compatibility = calculateCompatibility(player, target);

  // Determine if match succeeds
  // Match if score > 60, or allow 20% random matches (serendipity!)
  const serendipity = Math.random() < 0.2;
  const success = compatibility > 60 || serendipity;

  // Record the match attempt
  const attempt: MatchAttempt = {
    playerId,
    targetId,
    compatibilityScore: compatibility,
    success,
    attemptedAt: new Date(),
    reason: success
      ? serendipity && compatibility <= 60 ? 'serendipity' : 'compatibility'
      : 'low_compatibility',
  };

  matchAttempts.push(attempt);

  return {
    success,
    compatibility,
    reason: attempt.reason,
    serendipity: serendipity && compatibility <= 60 && success,
  };
}

/**
 * Check if player has already attempted to match with target
 */
export function hasAttemptedMatch(playerId: string, targetId: string): boolean {
  return matchAttempts.some(
    attempt => attempt.playerId === playerId && attempt.targetId === targetId
  );
}

/**
 * Get player's recent match history
 *
 * @param playerId - Player's ID
 * @param limit - Maximum number of records to return
 * @returns List of match history records
 */
export function getMatchHistory(playerId: string, limit = 10): MatchAttempt[] {
  return matchAttempts
    .filter(attempt => attempt.playerId === playerId)
    .sort((a, b) => b.attemptedAt.getTime() - a.attemptedAt.getTime())
    .slice(0, limit);
}

/**
 * Get player's successful matches only
 */
export function getSuccessfulMatches(playerId: string): MatchAttempt[] {
  return matchAttempts.filter(
    attempt => attempt.playerId === playerId && attempt.success
  );
}

/**
 * Calculate player's match success rate
 *
 * @param playerId - Player's ID
 * @returns Success rate statistics
 */
export function getSuccessRate(playerId: string): MatchSuccessRate {
  const playerAttempts = matchAttempts.filter(
    attempt => attempt.playerId === playerId
  );

  if (playerAttempts.length === 0) {
    return {
      totalAttempts: 0,
      successfulMatches: 0,
      successRate: 0,
      avgCompatibility: 0,
    };
  }

  const successfulMatches = playerAttempts.filter(a => a.success).length;
  const totalCompatibility = playerAttempts.reduce(
    (sum, a) => sum + a.compatibilityScore,
    0
  );

  return {
    totalAttempts: playerAttempts.length,
    successfulMatches,
    successRate: Math.round((successfulMatches / playerAttempts.length) * 100 * 100) / 100,
    avgCompatibility: Math.round((totalCompatibility / playerAttempts.length) * 100) / 100,
  };
}

/**
 * Get match statistics for analytics
 */
export function getMatchStats(): {
  totalMatches: number;
  successfulMatches: number;
  serendipityMatches: number;
  avgCompatibility: number;
} {
  if (matchAttempts.length === 0) {
    return {
      totalMatches: 0,
      successfulMatches: 0,
      serendipityMatches: 0,
      avgCompatibility: 0,
    };
  }

  const successful = matchAttempts.filter(a => a.success);
  const serendipity = matchAttempts.filter(a => a.reason === 'serendipity');
  const totalCompatibility = matchAttempts.reduce(
    (sum, a) => sum + a.compatibilityScore,
    0
  );

  return {
    totalMatches: matchAttempts.length,
    successfulMatches: successful.length,
    serendipityMatches: serendipity.length,
    avgCompatibility: Math.round((totalCompatibility / matchAttempts.length) * 100) / 100,
  };
}

/**
 * Clear match history for a player (e.g., for new game)
 */
export function clearMatchHistory(playerId: string): void {
  const indicesToRemove: number[] = [];
  matchAttempts.forEach((attempt, index) => {
    if (attempt.playerId === playerId) {
      indicesToRemove.push(index);
    }
  });

  // Remove in reverse order to maintain correct indices
  for (let i = indicesToRemove.length - 1; i >= 0; i--) {
    matchAttempts.splice(indicesToRemove[i], 1);
  }
}

/**
 * Clear all match data (for testing)
 */
export function clearAllMatches(): void {
  matchAttempts.length = 0;
}
