/**
 * Pending Conversation Events System
 *
 * Manages events triggered by AI tool calls that need player interaction.
 * Events are queued during conversations and processed by the game loop.
 *
 * Flow:
 * 1. AI uses tool (e.g., ask_for_date) → PendingConversationEvent created
 * 2. Event added to player.pendingConversationEvents
 * 3. Game loop checks for pending events each tick
 * 4. Event converted to QuestionEvent and sent to client
 * 5. Player response processed, affects game state
 *
 * Extensibility:
 * - Add new event types by creating a create*Event function
 * - Add response processing in processEventResponse
 */

import { v4 as uuidv4 } from 'uuid';
import { Player, Person } from '../../models/index.js';
import type { PendingConversationEvent, PendingEventType } from './tool_processor.js';

// ============================================================
// Types
// ============================================================

/**
 * Answer option for question events
 */
export interface AnswerOption {
  option: string;
  energyCost?: number;
  moneyCost?: number;
  diamondCost?: number;
}

/**
 * Question event sent to client
 */
export interface QuestionEvent {
  id: string;
  type: 'questionEvent';
  message: string;
  title?: string;
  characters: Array<{ id: string; firstname: string; lastname?: string }>;
  answers: AnswerOption[];
  image?: string;
  /** Internal data for processing response */
  _callbackData?: {
    eventType: PendingEventType;
    characterId: string;
    eventId: string;
    [key: string]: unknown;
  };
}

/**
 * Message event sent to client (notification only)
 */
export interface MessageEvent {
  id: string;
  type: 'messageEvent';
  message: string;
  title?: string;
  characters?: Array<{ id: string; firstname: string }>;
  date: string;
  hour: string;
  affinityChange?: number;
}

/**
 * Result of processing an event response
 */
export interface EventResponseResult {
  success: boolean;
  message?: string;
  affinityChange?: number;
  statChanges?: Record<string, number>;
  relationshipChange?: string; // e.g., 'friend' -> 'dating'
  followUpEvent?: QuestionEvent | MessageEvent;
}

// ============================================================
// Event Processing
// ============================================================

/**
 * Check for and process the next pending conversation event
 * Called from the game loop
 */
export function getNextPendingEvent(player: Player): QuestionEvent | MessageEvent | null {
  const pendingEvents = player.pendingConversationEvents;
  if (!pendingEvents || pendingEvents.length === 0) {
    return null;
  }

  // Sort by priority (high first) then by creation time
  const sortedEvents = [...pendingEvents].sort((a, b) => {
    const priorityOrder = { high: 0, medium: 1, low: 2 };
    const priorityDiff = priorityOrder[a.priority] - priorityOrder[b.priority];
    if (priorityDiff !== 0) return priorityDiff;
    return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
  });

  const event = sortedEvents[0];
  const character = player.r?.find(r => r.id === event.characterId);

  if (!character) {
    // Character no longer exists, remove event
    removeEventFromPlayer(player, event.id);
    return null;
  }

  // Check if event expired
  if (event.expiresAt && new Date() > new Date(event.expiresAt)) {
    return handleExpiredEvent(player, event, character);
  }

  // Check if scheduled event hasn't triggered yet
  if (event.triggersAt) {
    const currentGameHour = (player.dayOfYear ?? 1) * 24 + (player.hourOfDay ?? 0);
    if (currentGameHour < event.triggersAt) {
      // Not time yet - skip this event and check for other non-scheduled events
      const nonScheduledEvent = pendingEvents.find(e =>
        !e.triggersAt && e.id !== event.id
      );
      if (nonScheduledEvent) {
        const nonScheduledChar = player.r?.find(r => r.id === nonScheduledEvent.characterId);
        if (nonScheduledChar) {
          // Recursively handle the non-scheduled event
          return getNextPendingEventByType(player, nonScheduledEvent, nonScheduledChar);
        }
      }
      return null; // Wait for scheduled time
    }
  }

  // Convert to game event based on type
  return getNextPendingEventByType(player, event, character);
}

/**
 * Process a pending event by type and return the appropriate game event
 */
function getNextPendingEventByType(
  player: Player,
  event: PendingConversationEvent,
  character: Person
): QuestionEvent | MessageEvent | null {
  switch (event.type) {
    case 'activity_invite':
      return createActivityInviteEvent(event, character, player);
    case 'date_request':
      return createDateRequestEvent(event, character, player);
    case 'emotional_moment':
      return createEmotionalMomentEvent(event, character, player);
    case 'favor_request':
      return createFavorRequestEvent(event, character, player);
    case 'gift_received':
      return createGiftReceivedEvent(event, character, player);
    case 'confession':
      return createConfessionEvent(event, character, player);
    case 'date_accepted':
      return createScheduledDateEvent(event, character, player);
    case 'activity_accepted':
      return createScheduledActivityEvent(event, character, player);
    default:
      console.log(`Unknown pending event type: ${event.type}`);
      removeEventFromPlayer(player, event.id);
      return null;
  }
}

/**
 * Process player's response to a pending event
 */
export function processEventResponse(
  player: Player,
  eventId: string,
  selectedOption: number,
  callbackData: NonNullable<QuestionEvent['_callbackData']>
): EventResponseResult {
  const character = player.r?.find(r => r.id === callbackData.characterId);
  if (!character) {
    return { success: false, message: 'Character not found' };
  }

  // Remove the event from pending
  removeEventFromPlayer(player, callbackData.eventId);

  // Route to appropriate handler
  switch (callbackData.eventType) {
    case 'activity_invite':
      return processActivityResponse(player, character, selectedOption, callbackData);
    case 'date_request':
      return processDateResponse(player, character, selectedOption, callbackData);
    case 'emotional_moment':
      return processEmotionalResponse(player, character, selectedOption, callbackData);
    case 'favor_request':
      return processFavorResponse(player, character, selectedOption, callbackData);
    case 'gift_received':
      return processGiftResponse(player, character, selectedOption, callbackData);
    case 'confession':
      return processConfessionResponse(player, character, selectedOption, callbackData);
    case 'date_accepted':
      return processScheduledDateResponse(player, character, selectedOption, callbackData);
    case 'activity_accepted':
      return processScheduledActivityResponse(player, character, selectedOption, callbackData);
    default:
      return { success: false, message: 'Unknown event type' };
  }
}

// ============================================================
// Event Creators
// ============================================================

function createActivityInviteEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { activityType, urgency, reason, costs } = event.data as {
    activityType: string;
    urgency: string;
    reason?: string;
    costs: { energy: number; money?: number };
  };

  const activityNames: Record<string, string> = {
    coffee: 'grab coffee',
    movie: 'watch a movie',
    walk: 'go for a walk',
    dinner: 'have dinner',
    study: 'study together',
    workout: 'work out',
    shopping: 'go shopping',
    gaming: 'play some games',
    cooking: 'cook together',
    concert: 'go to a concert',
    museum: 'visit a museum',
    picnic: 'have a picnic',
    beach: 'go to the beach',
    hiking: 'go hiking',
    clubbing: 'go clubbing',
  };

  const activityName = activityNames[activityType] ?? activityType;
  const urgencyText = urgency === 'now' ? ' right now' :
                      urgency === 'soon' ? ' soon' : ' sometime';

  let message = `${event.characterName} wants to ${activityName} with you${urgencyText}!`;
  if (reason) {
    message += ` "${reason}"`;
  }

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message,
    title: 'Activity Invitation',
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      {
        option: "Yes, let's do it!",
        energyCost: costs.energy,
        moneyCost: costs.money,
      },
      {
        option: "Maybe another time",
      },
      {
        option: "I can't right now, sorry",
      },
    ],
    _callbackData: {
      eventType: 'activity_invite',
      characterId: character.id,
      eventId: event.id,
      activityType,
      costs,
    },
  };
}

function createDateRequestEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { dateType, venue, costs } = event.data as {
    dateType: string;
    venue?: string;
    costs: { energy: number; money: number };
  };

  const dateDescriptions: Record<string, string> = {
    casual: 'a casual hangout',
    romantic: 'a romantic evening',
    adventurous: 'an exciting adventure',
    cozy: 'a cozy night together',
    fancy: 'a fancy night out',
  };

  const desc = dateDescriptions[dateType] ?? 'a date';
  const venueText = venue ? ` at ${venue}` : '';

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: `${event.characterName} is asking you out for ${desc}${venueText}!`,
    title: 'Date Request',
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      {
        option: "I'd love to!",
        energyCost: costs.energy,
        moneyCost: costs.money,
      },
      {
        option: "Can we reschedule?",
      },
      {
        option: "I don't think so...",
      },
    ],
    _callbackData: {
      eventType: 'date_request',
      characterId: character.id,
      eventId: event.id,
      dateType,
      costs,
    },
  };
}

function createEmotionalMomentEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { feelingType, intensity, aboutPlayer, bonusOptions } = event.data as {
    feelingType: string;
    intensity: string;
    aboutPlayer: boolean;
    bonusOptions: boolean;
  };

  const feelingContexts: Record<string, string> = {
    love: `${event.characterName} just expressed deep feelings for you.`,
    gratitude: `${event.characterName} is expressing heartfelt gratitude.`,
    concern: `${event.characterName} is worried and wants to talk about it.`,
    hurt: `${event.characterName} seems hurt and is opening up to you.`,
    excitement: `${event.characterName} is bursting with excitement!`,
    fear: `${event.characterName} is sharing their fears with you.`,
    jealousy: `${event.characterName} seems jealous about something.`,
    longing: `${event.characterName} has been missing you deeply.`,
    pride: `${event.characterName} is sharing a proud moment.`,
    disappointment: `${event.characterName} is feeling let down.`,
  };

  const answers: AnswerOption[] = [
    { option: "I appreciate you sharing this with me" },
    { option: "Tell me more about how you feel" },
  ];

  // High social stat unlocks better response
  if (bonusOptions) {
    if (feelingType === 'love' || feelingType === 'longing') {
      answers.unshift({ option: "I feel the same way" });
    } else if (feelingType === 'hurt' || feelingType === 'fear') {
      answers.unshift({ option: "I'm here for you, always" });
    } else {
      answers.unshift({ option: "That means so much to me" });
    }
  }

  answers.push({ option: "I'm not sure what to say..." });

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: feelingContexts[feelingType] ?? `${event.characterName} wants to have an emotional conversation.`,
    title: 'Emotional Moment',
    characters: [{ id: character.id, firstname: character.firstname }],
    answers,
    _callbackData: {
      eventType: 'emotional_moment',
      characterId: character.id,
      eventId: event.id,
      feelingType,
      intensity,
      aboutPlayer,
      bonusOptions,
    },
  };
}

function createFavorRequestEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { favorType, importance, costs, affinityReward } = event.data as {
    favorType: string;
    importance: string;
    costs: { energy?: number; money?: number };
    affinityReward: number;
  };

  const favorDescriptions: Record<string, string> = {
    advice: 'asking for your advice',
    help_with_task: 'asking for help with something',
    emotional_support: 'needing emotional support',
    money: 'asking to borrow some money',
    introduction: 'asking you to introduce them to someone',
    time: 'asking for some of your time',
  };

  const desc = favorDescriptions[favorType] ?? 'asking for a favor';
  const importanceText = importance === 'big' ? " It seems really important to them." :
                         importance === 'small' ? "" : " It would mean a lot to them.";

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: `${event.characterName} is ${desc}.${importanceText}`,
    title: 'Favor Request',
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      {
        option: "Of course, happy to help!",
        energyCost: costs.energy,
        moneyCost: costs.money,
      },
      {
        option: "I wish I could, but...",
      },
      {
        option: "Sorry, I can't right now",
      },
    ],
    _callbackData: {
      eventType: 'favor_request',
      characterId: character.id,
      eventId: event.id,
      favorType,
      importance,
      affinityReward,
    },
  };
}

function createGiftReceivedEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): MessageEvent {
  const { giftType, occasion, description, happinessBoost } = event.data as {
    giftType: string;
    occasion?: string;
    description: string;
    happinessBoost: number;
  };

  // Remove the event immediately (gifts don't need response)
  removeEventFromPlayer(player, event.id);

  // Apply happiness boost
  player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + happinessBoost);

  const occasionText = occasion ? ` for ${occasion}` : '';

  return {
    id: uuidv4(),
    type: 'messageEvent',
    message: `${event.characterName} gave you ${description}${occasionText}!`,
    title: 'Gift Received!',
    characters: [{ id: character.id, firstname: character.firstname }],
    date: player.date,
    hour: player.hourOfDay.toString(),
    affinityChange: 12,
  };
}

function createConfessionEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { confessionStyle, hasBeenBuilding, canStartDating } = event.data as {
    confessionStyle: string;
    hasBeenBuilding: boolean;
    canStartDating: boolean;
  };

  const styleDescriptions: Record<string, string> = {
    shy: `${event.characterName} nervously admits they have feelings for you...`,
    confident: `${event.characterName} confidently tells you they're interested in you.`,
    nervous: `${event.characterName} is stumbling over their words, trying to express how they feel...`,
    romantic: `${event.characterName} takes your hand and confesses their feelings in the most romantic way.`,
    casual: `${event.characterName} casually mentions they've been thinking about you a lot lately...`,
  };

  const buildingText = hasBeenBuilding ? " They say these feelings have been building for a while." : "";

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: `${styleDescriptions[confessionStyle] ?? `${event.characterName} confesses their feelings for you.`}${buildingText}`,
    title: 'Confession',
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      { option: "I feel the same way!" },
      { option: "I need some time to think..." },
      { option: "I only see you as a friend" },
    ],
    _callbackData: {
      eventType: 'confession',
      characterId: character.id,
      eventId: event.id,
      confessionStyle,
      canStartDating,
    },
  };
}

/**
 * Create a scheduled date event (when the date time arrives)
 */
function createScheduledDateEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { dateType, costs, suggestedTime } = event.data as {
    dateType: string;
    suggestedTime: string;
    costs: { energy: number; money: number };
  };

  const dateDescriptions: Record<string, string> = {
    casual: 'a casual hangout',
    romantic: 'a romantic evening',
    adventurous: 'an exciting adventure',
    cozy: 'a cozy time together',
    fancy: 'a fancy night out',
  };

  const dateDesc = dateDescriptions[dateType] ?? 'a date';

  console.log(`Scheduled date triggered: ${character.firstname} - ${dateType}`);

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: `It's time for your date with ${event.characterName}! They're ready for ${dateDesc}. Are you ready?`,
    title: `Date with ${event.characterName}`,
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      {
        option: "Let's go!",
        energyCost: costs.energy,
        moneyCost: costs.money,
      },
      {
        option: "I need to reschedule",
      },
      {
        option: "I have to cancel",
      },
    ],
    _callbackData: {
      eventType: 'date_accepted',
      characterId: character.id,
      eventId: event.id,
      dateType,
      costs,
    },
  };
}

/**
 * Create a scheduled activity event (when the activity time arrives)
 */
function createScheduledActivityEvent(
  event: PendingConversationEvent,
  character: Person,
  player: Player
): QuestionEvent {
  const { activityType, costs, enthusiasm } = event.data as {
    activityType: string;
    enthusiasm: string;
    costs: { energy: number; money?: number };
  };

  const activityNames: Record<string, string> = {
    coffee: 'grab coffee',
    movie: 'watch a movie',
    walk: 'go for a walk',
    dinner: 'have dinner',
    study: 'study together',
    workout: 'work out',
    shopping: 'go shopping',
    gaming: 'play some games',
    cooking: 'cook together',
  };

  const activityName = activityNames[activityType] ?? activityType;

  console.log(`Scheduled activity triggered: ${character.firstname} - ${activityType}`);

  return {
    id: uuidv4(),
    type: 'questionEvent',
    message: `${event.characterName} is ready to ${activityName} with you! Let's go?`,
    title: `Activity with ${event.characterName}`,
    characters: [{ id: character.id, firstname: character.firstname }],
    answers: [
      {
        option: "Yes, let's do it!",
        energyCost: costs.energy,
        moneyCost: costs.money,
      },
      {
        option: "Can we do this later?",
      },
      {
        option: "I have to cancel",
      },
    ],
    _callbackData: {
      eventType: 'activity_accepted',
      characterId: character.id,
      eventId: event.id,
      activityType,
      costs,
    },
  };
}

// ============================================================
// Response Processors
// ============================================================

function processActivityResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { activityType, costs } = callbackData as {
    activityType: string;
    costs: { energy: number; money?: number };
  };

  if (selectedOption === 0) {
    // Validate player can afford the activity
    const currentEnergy = player.c.energy ?? 100;
    const currentMoney = player.c.money ?? 0;

    if (currentEnergy < costs.energy) {
      return {
        success: false,
        message: `You're too tired to go. You need ${costs.energy} energy but only have ${currentEnergy}.`,
      };
    }

    if (costs.money && currentMoney < costs.money) {
      return {
        success: false,
        message: `You can't afford this activity. You need $${costs.money} but only have $${currentMoney}.`,
      };
    }

    // Accepted - apply costs and boost relationship
    player.c.energy = Math.max(0, currentEnergy - costs.energy);
    if (costs.money) {
      player.c.money = Math.max(0, currentMoney - costs.money);
    }

    character.affinity = Math.min(100, (character.affinity ?? 50) + 12);
    character.familiarity = (character.familiarity ?? 0) + 5;

    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 10);
    player.c.social = Math.min(100, (player.c.social ?? 50) + 5);

    return {
      success: true,
      message: `You had a great time with ${character.firstname}!`,
      affinityChange: 12,
      statChanges: { happiness: 10, social: 5 },
    };
  } else if (selectedOption === 1) {
    // Raincheck - small disappointment
    character.affinity = Math.max(0, (character.affinity ?? 50) - 2);

    return {
      success: true,
      message: `${character.firstname} understands but seems a little disappointed.`,
      affinityChange: -2,
    };
  } else {
    // Declined - moderate disappointment
    character.affinity = Math.max(0, (character.affinity ?? 50) - 5);

    return {
      success: true,
      message: `${character.firstname} accepts your answer but seems disappointed.`,
      affinityChange: -5,
    };
  }
}

function processDateResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { dateType, costs } = callbackData as {
    dateType: string;
    costs: { energy: number; money: number };
  };

  if (selectedOption === 0) {
    // Accepted date
    player.c.energy = Math.max(0, (player.c.energy ?? 100) - costs.energy);
    player.c.money = Math.max(0, (player.c.money ?? 0) - costs.money);

    // Big relationship boost for dates
    character.affinity = Math.min(100, (character.affinity ?? 50) + 18);
    character.familiarity = (character.familiarity ?? 0) + 8;

    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 15);

    // Romantic dates are extra special
    const bonusAffinity = dateType === 'romantic' ? 5 : dateType === 'fancy' ? 7 : 0;
    character.affinity = Math.min(100, character.affinity + bonusAffinity);

    return {
      success: true,
      message: `You had an amazing ${dateType} date with ${character.firstname}!`,
      affinityChange: 18 + bonusAffinity,
      statChanges: { happiness: 15 },
    };
  } else if (selectedOption === 1) {
    // Reschedule
    character.affinity = Math.max(0, (character.affinity ?? 50) - 3);

    return {
      success: true,
      message: `${character.firstname} agrees to reschedule but seems a bit let down.`,
      affinityChange: -3,
    };
  } else {
    // Declined
    character.affinity = Math.max(0, (character.affinity ?? 50) - 8);

    return {
      success: true,
      message: `${character.firstname} looks hurt by your rejection.`,
      affinityChange: -8,
    };
  }
}

function processEmotionalResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { feelingType, intensity, bonusOptions } = callbackData as {
    feelingType: string;
    intensity: string;
    bonusOptions: boolean;
  };

  const intensityMultiplier = intensity === 'intense' ? 1.5 : intensity === 'subtle' ? 0.7 : 1;

  // Adjust for bonus option offset
  const effectiveOption = bonusOptions ? selectedOption : selectedOption + 1;

  if (effectiveOption === 0) {
    // Best response (bonus option)
    const affinityGain = Math.round(15 * intensityMultiplier);
    character.affinity = Math.min(100, (character.affinity ?? 50) + affinityGain);
    character.familiarity = (character.familiarity ?? 0) + 6;

    player.c.social = Math.min(100, (player.c.social ?? 50) + 5);

    return {
      success: true,
      message: `${character.firstname} looks deeply moved by your response.`,
      affinityChange: affinityGain,
      statChanges: { social: 5 },
    };
  } else if (effectiveOption === 1) {
    // Appreciative response
    const affinityGain = Math.round(8 * intensityMultiplier);
    character.affinity = Math.min(100, (character.affinity ?? 50) + affinityGain);
    character.familiarity = (character.familiarity ?? 0) + 3;

    return {
      success: true,
      message: `${character.firstname} appreciates your support.`,
      affinityChange: affinityGain,
    };
  } else if (effectiveOption === 2) {
    // Ask for more
    const affinityGain = Math.round(5 * intensityMultiplier);
    character.affinity = Math.min(100, (character.affinity ?? 50) + affinityGain);
    character.familiarity = (character.familiarity ?? 0) + 4;

    player.c.social = Math.min(100, (player.c.social ?? 50) + 3);

    return {
      success: true,
      message: `${character.firstname} continues sharing with you.`,
      affinityChange: affinityGain,
      statChanges: { social: 3 },
    };
  } else {
    // Awkward response
    character.affinity = Math.max(0, (character.affinity ?? 50) - 3);

    return {
      success: true,
      message: `${character.firstname} looks a bit disappointed by your response.`,
      affinityChange: -3,
    };
  }
}

function processFavorResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { favorType, affinityReward } = callbackData as {
    favorType: string;
    affinityReward: number;
  };

  if (selectedOption === 0) {
    // Helped
    character.affinity = Math.min(100, (character.affinity ?? 50) + affinityReward);
    character.familiarity = (character.familiarity ?? 0) + 4;

    player.c.social = Math.min(100, (player.c.social ?? 50) + 3);

    return {
      success: true,
      message: `${character.firstname} is really grateful for your help!`,
      affinityChange: affinityReward,
      statChanges: { social: 3 },
    };
  } else if (selectedOption === 1) {
    // Wished you could
    character.affinity = Math.max(0, (character.affinity ?? 50) - 2);

    return {
      success: true,
      message: `${character.firstname} understands but is a little disappointed.`,
      affinityChange: -2,
    };
  } else {
    // Declined
    character.affinity = Math.max(0, (character.affinity ?? 50) - 5);

    return {
      success: true,
      message: `${character.firstname} seems let down by your response.`,
      affinityChange: -5,
    };
  }
}

function processGiftResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  // Gifts are message events, no response needed
  return { success: true };
}

function processConfessionResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { canStartDating } = callbackData as {
    canStartDating: boolean;
  };

  // Content safety: romantic relationships are adults only (18+). If either the
  // player or the NPC is under 18, do not start a dating relationship.
  const bothAdults =
    (player.c.ageYears ?? 0) >= 18 && (character.ageYears ?? 0) >= 18;

  if (selectedOption === 0) {
    // Reciprocate feelings - start dating!
    character.affinity = Math.min(100, (character.affinity ?? 50) + 25);
    character.familiarity = (character.familiarity ?? 0) + 10;

    // Update relationship status
    if (canStartDating && bothAdults) {
      character.relationships = ['dating'];
    }

    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 20);

    return {
      success: true,
      message: `You and ${character.firstname} are now dating!`,
      affinityChange: 25,
      statChanges: { happiness: 20 },
      relationshipChange: 'dating',
    };
  } else if (selectedOption === 1) {
    // Need time
    character.affinity = Math.min(100, (character.affinity ?? 50) + 5);

    return {
      success: true,
      message: `${character.firstname} respects that you need time to think.`,
      affinityChange: 5,
    };
  } else {
    // Friend zone
    character.affinity = Math.max(0, (character.affinity ?? 50) - 15);

    return {
      success: true,
      message: `${character.firstname} is heartbroken but tries to understand.`,
      affinityChange: -15,
    };
  }
}

function processScheduledDateResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { dateType, costs } = callbackData as {
    dateType: string;
    costs: { energy: number; money: number };
  };

  if (selectedOption === 0) {
    // Went on the date
    player.c.energy = Math.max(0, (player.c.energy ?? 100) - costs.energy);
    player.c.money = Math.max(0, (player.c.money ?? 0) - costs.money);

    // Big relationship boost for dates
    character.affinity = Math.min(100, (character.affinity ?? 50) + 18);
    character.familiarity = (character.familiarity ?? 0) + 8;

    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 15);

    // Romantic dates are extra special
    const bonusAffinity = dateType === 'romantic' ? 5 : dateType === 'fancy' ? 7 : 0;
    character.affinity = Math.min(100, character.affinity + bonusAffinity);

    return {
      success: true,
      message: `You had an amazing ${dateType} date with ${character.firstname}!`,
      affinityChange: 18 + bonusAffinity,
      statChanges: { happiness: 15 },
    };
  } else if (selectedOption === 1) {
    // Rescheduled
    character.affinity = Math.max(0, (character.affinity ?? 50) - 3);

    return {
      success: true,
      message: `${character.firstname} is a bit disappointed but agrees to reschedule.`,
      affinityChange: -3,
    };
  } else {
    // Cancelled
    character.affinity = Math.max(0, (character.affinity ?? 50) - 10);

    return {
      success: true,
      message: `${character.firstname} is hurt that you cancelled on them.`,
      affinityChange: -10,
    };
  }
}

function processScheduledActivityResponse(
  player: Player,
  character: Person,
  selectedOption: number,
  callbackData: Record<string, unknown>
): EventResponseResult {
  const { activityType, costs } = callbackData as {
    activityType: string;
    costs: { energy: number; money?: number };
  };

  if (selectedOption === 0) {
    // Validate player can afford the activity
    const currentEnergy = player.c.energy ?? 100;
    const currentMoney = player.c.money ?? 0;

    if (currentEnergy < costs.energy) {
      // Can't afford but scheduled - treat as cancelled
      character.affinity = Math.max(0, (character.affinity ?? 50) - 5);
      return {
        success: false,
        message: `You're too exhausted to go. ${character.firstname} is understanding but disappointed.`,
        affinityChange: -5,
      };
    }

    if (costs.money && currentMoney < costs.money) {
      // Can't afford but scheduled - treat as cancelled
      character.affinity = Math.max(0, (character.affinity ?? 50) - 3);
      return {
        success: false,
        message: `You don't have enough money right now. ${character.firstname} suggests doing something cheaper next time.`,
        affinityChange: -3,
      };
    }

    // Did the activity
    player.c.energy = Math.max(0, currentEnergy - costs.energy);
    if (costs.money) {
      player.c.money = Math.max(0, currentMoney - costs.money);
    }

    character.affinity = Math.min(100, (character.affinity ?? 50) + 12);
    character.familiarity = (character.familiarity ?? 0) + 5;

    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 10);
    player.c.social = Math.min(100, (player.c.social ?? 50) + 5);

    return {
      success: true,
      message: `You had a great time with ${character.firstname}!`,
      affinityChange: 12,
      statChanges: { happiness: 10, social: 5 },
    };
  } else if (selectedOption === 1) {
    // Later
    character.affinity = Math.max(0, (character.affinity ?? 50) - 2);

    return {
      success: true,
      message: `${character.firstname} understands but seems a little disappointed.`,
      affinityChange: -2,
    };
  } else {
    // Cancelled
    character.affinity = Math.max(0, (character.affinity ?? 50) - 5);

    return {
      success: true,
      message: `${character.firstname} accepts your cancellation but looks let down.`,
      affinityChange: -5,
    };
  }
}

// ============================================================
// Helper Functions
// ============================================================

function handleExpiredEvent(
  player: Player,
  event: PendingConversationEvent,
  character: Person
): MessageEvent {
  removeEventFromPlayer(player, event.id);

  // Character disappointed if ignored
  character.affinity = Math.max(0, (character.affinity ?? 50) - 5);

  const expirationMessages: Record<PendingEventType, string> = {
    activity_invite: `${event.characterName} seems disappointed you never responded to their invitation.`,
    date_request: `${event.characterName} is hurt that you ignored their date request.`,
    emotional_moment: `${event.characterName} feels like you didn't care about what they shared.`,
    favor_request: `${event.characterName} had to find help elsewhere.`,
    gift_received: ``, // Gifts don't expire meaningfully
    confession: `${event.characterName} assumes your silence means you're not interested...`,
    relationship_upgrade: `${event.characterName} is disappointed you never responded to their question about being official.`,
    relationship_accepted: ``, // Already accepted, nothing to expire
    date_accepted: ``, // Already accepted, nothing to expire
    activity_accepted: ``, // Already accepted, nothing to expire
    confession_accepted: ``, // Already accepted, nothing to expire
    breakup_initiated: ``, // Immediate event, nothing to expire
    breakup_accepted: ``, // Immediate event, nothing to expire
  };

  return {
    id: uuidv4(),
    type: 'messageEvent',
    message: expirationMessages[event.type] || `${event.characterName} seems disappointed.`,
    title: 'Missed Connection',
    date: player.date,
    hour: player.hourOfDay.toString(),
    affinityChange: -5,
  };
}

function removeEventFromPlayer(player: Player, eventId: string): void {
  if (!player.pendingConversationEvents) return;

  const index = player.pendingConversationEvents.findIndex(e => e.id === eventId);
  if (index !== -1) {
    player.pendingConversationEvents.splice(index, 1);
  }
}

/**
 * Add a pending event to player's queue
 * If the event has immediate: true, it will be processed right away
 */
export function addPendingEvent(player: Player, event: PendingConversationEvent): void {
  // Handle immediate events (like relationship acceptances)
  if (event.data?.immediate === true) {
    processImmediateEvent(player, event);
    return; // Don't queue immediate events
  }

  if (!player.pendingConversationEvents) {
    player.pendingConversationEvents = [];
  }

  // Prevent duplicate events from same character of same type
  const existingIndex = player.pendingConversationEvents.findIndex(
    e => e.characterId === event.characterId && e.type === event.type
  );

  if (existingIndex !== -1) {
    // Replace existing event with new one
    player.pendingConversationEvents[existingIndex] = event;
  } else {
    player.pendingConversationEvents.push(event);
  }
}

/**
 * Process an immediate event (no player confirmation needed)
 * Used for things like relationship acceptance where the AI already said yes
 */
function processImmediateEvent(player: Player, event: PendingConversationEvent): void {
  const character = player.r.find(p => p.id === event.characterId);
  if (!character) {
    console.log(`Immediate event: Character ${event.characterId} not found`);
    return;
  }

  console.log(`Processing immediate event: ${event.type} for ${character.firstname}`);

  switch (event.type) {
    case 'relationship_accepted':
    case 'confession_accepted': {
      // Content safety: romantic relationships are adults only (18+). Never
      // upgrade to a romantic relationship if either the player or the NPC is
      // under 18.
      if ((player.c.ageYears ?? 0) < 18 || (character.ageYears ?? 0) < 18) {
        console.log(
          `Romantic upgrade blocked (content-safety 18+): player ${player.c.ageYears}, ${character.firstname} ${character.ageYears}`
        );
        break;
      }
      // Update the character's relationship
      const newRelationship = event.data?.upgradesTo as string ?? event.data?.newRelationship as string;
      if (newRelationship) {
        // Update relationships array
        if (!character.relationships) {
          character.relationships = [];
        }
        // Remove old dating relationships
        character.relationships = character.relationships.filter(
          r => !['dating_match', 'dating', 'crush', 'friend', 'close_friend'].includes(r.toLowerCase())
        );
        // Add new relationship
        character.relationships.push(newRelationship);
        console.log(`Relationship upgraded to ${newRelationship} for ${character.firstname}`);
      }
      break;
    }

    case 'date_accepted':
    case 'activity_accepted': {
      // Schedule the activity/date
      // For now, just log it - the game loop will handle scheduling
      console.log(`${event.type}: ${character.firstname} agreed to ${event.data?.activityType ?? event.data?.dateType}`);
      break;
    }

    case 'breakup_initiated':
    case 'breakup_accepted': {
      // Downgrade the relationship to "ex"
      const downgradesTo = event.data?.downgradesTo as string ?? 'ex';
      if (!character.relationships) {
        character.relationships = [];
      }
      // Remove all romantic relationships
      character.relationships = character.relationships.filter(
        r => !['dating_match', 'dating', 'boyfriend', 'girlfriend', 'partner'].includes(r.toLowerCase())
      );
      // Add ex status
      character.relationships.push(downgradesTo);
      console.log(`Relationship ended - ${character.firstname} is now ${downgradesTo}`);
      break;
    }

    default:
      console.log(`Unknown immediate event type: ${event.type}`);
  }
}

/**
 * Check if player has any pending events from a specific character
 */
export function hasPendingEventFrom(player: Player, characterId: string): boolean {
  return player.pendingConversationEvents?.some(e => e.characterId === characterId) ?? false;
}

/**
 * Get count of pending events
 */
export function getPendingEventCount(player: Player): number {
  return player.pendingConversationEvents?.length ?? 0;
}
