/**
 * Tutorial Events System for BaoLife
 * Provides gentle guided events for first-time players during their first 24 in-game hours
 * Ported from Python events/tutorial/onboarding.py
 *
 * This module contains the tutorial event generators that create events during
 * the player's first 24 in-game hours. It works in conjunction with:
 * - services/retention/tutorial.ts - Tutorial state management and triggers
 */

import { Player } from '../../models/index.js';
import {
  createMessageEvent,
  createQuestionEvent,
  createAnswerOption,
  EventResult,
} from '../base.js';
import {
  isTutorialMode as isTutorialModeService,
  TUTORIAL_MODE_HOURS,
} from '../../services/retention/tutorial.js';

/**
 * Tutorial event data structure
 */
export interface TutorialEvent {
  type: string;
  eventId: string;
  message: string;
  npcId?: string;
  npcName?: string;
  guaranteedSuccess?: boolean;
  affinityBonus?: number;
  rewardDiamonds?: number;
  tutorialHint?: string;
  simplifiedChoices?: boolean;
  choices?: Array<{
    name: string;
    energy: number;
    benefit: string;
  }>;
  guaranteedGoodGrade?: boolean;
  grade?: string;
  dismissible?: boolean;
  tutorialMode?: boolean;
}

/**
 * Check if player is still in tutorial mode (first 24 in-game hours)
 * Re-exported from tutorial service for convenience
 */
export function isTutorialMode(player: Player, gameHours?: number): boolean {
  return isTutorialModeService(player, gameHours);
}

/**
 * Generate welcome message for new player
 */
export function getWelcomeMessage(player: Player): TutorialEvent {
  const firstname = player.c.firstname ?? 'friend';

  return {
    type: 'tutorial_message',
    eventId: 'welcome',
    message: `Welcome to BaoLife, ${firstname}! Your journey begins now. Make choices, build relationships, and live your best life!`,
    dismissible: true,
  };
}

/**
 * Generate special gentle events for tutorial mode
 */
export function generateTutorialEvent(
  player: Player,
  eventType: 'first_friend' | 'first_activity' | 'first_purchase' | 'first_class'
): TutorialEvent | null {
  if (eventType === 'first_friend') {
    // Find a friendly person
    const friendlyPeople = (player.r ?? []).filter(
      (p) => (p.affinity ?? 0) >= 0 && p.status === 'alive'
    );

    if (friendlyPeople.length === 0) {
      return null;
    }

    const npc = friendlyPeople[Math.floor(Math.random() * friendlyPeople.length)];

    return {
      type: 'tutorial_interaction',
      eventId: 'first_friend',
      npcId: npc.id,
      npcName: npc.firstname,
      message: `Your classmate ${npc.firstname} smiles at you. They seem friendly!`,
      guaranteedSuccess: true,
      affinityBonus: 20,
      rewardDiamonds: 5,
      tutorialHint: 'Making friends increases happiness and opens new activities!',
    };
  }

  if (eventType === 'first_activity') {
    return {
      type: 'tutorial_activity_selection',
      eventId: 'first_activity',
      message: 'Choose your first activity!',
      simplifiedChoices: true,
      choices: [
        { name: 'Study', energy: 5, benefit: 'Increases intelligence' },
        { name: 'Play', energy: 5, benefit: 'Increases happiness' },
        { name: 'Exercise', energy: 5, benefit: 'Increases health' },
      ],
      tutorialHint: 'Activities cost energy but help you grow. Choose wisely!',
    };
  }

  if (eventType === 'first_purchase') {
    return {
      type: 'tutorial_store_visit',
      eventId: 'first_purchase',
      message: "Welcome to the store! Here's 10 diamonds to get you started.",
      rewardDiamonds: 10,
      tutorialHint: 'Buy items to increase your prestige and impress others!',
    };
  }

  if (eventType === 'first_class') {
    return {
      type: 'tutorial_class_result',
      eventId: 'first_class',
      message: "Great job in class! You're a natural learner.",
      guaranteedGoodGrade: true,
      grade: 'A',
      rewardDiamonds: 5,
      tutorialHint: 'Good grades lead to better college and career opportunities!',
    };
  }

  return null;
}

/**
 * Get helpful hint based on event type
 */
export function getContextualHint(eventType: string): string {
  const hints: Record<string, string> = {
    work: 'Working earns money. Save up for big purchases!',
    school: 'Education opens better career opportunities.',
    social: 'Building relationships makes life more fulfilling.',
    health: 'Keep your health high to live longer.',
    money: 'Money buys items that increase your prestige.',
    questionEvent: 'Take your time making decisions - they shape your future!',
    messageEvent: 'Pay attention to life events - they tell your story!',
  };

  return hints[eventType] ?? 'Make choices that align with your goals!';
}

/**
 * Apply tutorial mode modifiers to regular events
 */
export function applyTutorialModifiers(
  player: Player,
  eventData: Record<string, unknown>
): Record<string, unknown> {
  if (!isTutorialMode(player)) {
    return eventData;
  }

  const modified = { ...eventData };

  // Make events easier
  if ('difficulty' in modified && typeof modified.difficulty === 'number') {
    modified.difficulty = Math.max(1, (modified.difficulty as number) - 2);
  }

  // Boost rewards
  if ('money_reward' in modified && typeof modified.money_reward === 'number') {
    modified.money_reward = Math.floor((modified.money_reward as number) * 1.5);
  }

  if ('diamonds_reward' in modified && typeof modified.diamonds_reward === 'number') {
    modified.diamonds_reward = Math.floor((modified.diamonds_reward as number) * 1.5);
  }

  // Reduce costs
  if ('energyCost' in modified && typeof modified.energyCost === 'number') {
    modified.energyCost = Math.max(1, Math.floor((modified.energyCost as number) * 0.75));
  }

  // Add tutorial hints
  modified.tutorial_mode = true;
  modified.tutorial_hint = getContextualHint((eventData.type as string) ?? 'general');

  return modified;
}

/**
 * Modify any generated event if player is in tutorial mode
 * Called by main event generator
 * Ported from Python modify_event_for_tutorial()
 *
 * @param player - Player object
 * @param event - Event object or data
 * @returns Modified event (potentially with tutorial modifications)
 */
export function modifyEventForTutorial<T extends Record<string, unknown>>(
  player: Player,
  event: T
): T {
  if (!isTutorialMode(player)) {
    return event;
  }

  // Apply modifiers to the event
  return applyTutorialModifiers(player, event) as T;
}

/**
 * First Conversation Tutorial Event
 * Guaranteed positive outcome to encourage social interaction
 */
export function firstConversation(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'firstConversation';
  const check =
    !player.askedQuestions.has(fname) &&
    isTutorialMode(player) &&
    (player.r ?? []).length > 0;

  if (type !== 'answer' && check) {
    // Find a friendly person
    const friendlyPeople = (player.r ?? []).filter(
      (p) => (p.affinity ?? 0) >= 0 && p.status === 'alive'
    );

    if (friendlyPeople.length > 0) {
      const npc = friendlyPeople[Math.floor(Math.random() * friendlyPeople.length)];
      const message = `${npc.firstname} approaches you with a warm smile. This seems like a great opportunity to make a friend!`;

      const answerOptions = [
        createAnswerOption('Say hello!', '', 3),
        createAnswerOption('Start a conversation', '', 3),
        createAnswerOption('Wave and smile', '', 1),
      ];

      return createQuestionEvent(fname, message, player, check, { answerOptions });
    }
  }

  if (type === 'answer') {
    // Always positive outcome in tutorial mode
    const c = player.c;
    c.happiness = Math.min(100, (c.happiness ?? 50) + 5);

    // Give small diamond reward
    c.diamonds = (c.diamonds ?? 0) + 5;

    return createMessageEvent(
      fname,
      "Great! You've taken your first steps in building relationships. Keep talking to people to grow your friendships! You earned 5 diamonds for making your first connection!",
      player,
      true,
      { diamondCost: -5 } // Negative cost = reward
    );
  }

  return null;
}

/**
 * First Activity Choice Tutorial Event
 * Simplified choices with clear benefits
 */
export function firstActivityChoice(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'firstActivityChoice';
  const check =
    !player.askedQuestions.has(fname) && isTutorialMode(player) && player.c.ageYears >= 5;

  if (type !== 'answer' && check) {
    const message = 'You have some free time! What would you like to do?';

    const answerOptions = [
      createAnswerOption('Study (Gain Intelligence)', '', 5),
      createAnswerOption('Play (Gain Happiness)', '', 5),
      createAnswerOption('Exercise (Gain Health)', '', 5),
    ];

    return createQuestionEvent(fname, message, player, check, { answerOptions });
  }

  if (type === 'answer') {
    const c = player.c;
    const choice = response?.option ?? '';
    let resultMessage = '';

    if (choice.includes('Study')) {
      c.intelligence = Math.min(100, (c.intelligence ?? 50) + 10);
      resultMessage = 'You studied hard and feel smarter! Intelligence increased.';
    } else if (choice.includes('Play')) {
      c.happiness = Math.min(100, (c.happiness ?? 50) + 10);
      resultMessage = 'You had fun playing! Happiness increased.';
    } else if (choice.includes('Exercise')) {
      c.health = Math.min(100, (c.health ?? 50) + 10);
      resultMessage = 'You exercised and feel healthier! Health increased.';
    }

    // Tutorial reward
    c.diamonds = (c.diamonds ?? 0) + 3;
    resultMessage += ' You earned 3 diamonds for completing your first activity!';

    return createMessageEvent(fname, resultMessage, player, true, { diamondCost: -3 });
  }

  return null;
}

/**
 * Tutorial Complete Event
 * Triggered when player completes tutorial (24 hours)
 */
export function tutorialComplete(player: Player): EventResult {
  const fname = 'tutorialComplete';
  const ageHours = player.c.ageHours ?? 0;
  const check =
    !player.askedQuestions.has(fname) && ageHours >= 24 && ageHours < 25;

  if (check) {
    const c = player.c;

    // Award completion bonus
    c.diamonds = (c.diamonds ?? 0) + 25;

    const message =
      "You've completed your first day! You're getting the hang of life. Keep going! You earned 25 diamonds for completing the tutorial!";

    return createMessageEvent(fname, message, player, check, { diamondCost: -25 });
  }

  return null;
}

/**
 * Check which tutorial events should be triggered based on player state
 */
export function checkTutorialTriggers(
  player: Player
): Array<(player: Player, type?: 'message' | 'question' | 'answer') => EventResult> {
  if (!isTutorialMode(player)) {
    return [];
  }

  const eventsToCheck: Array<
    (player: Player, type?: 'message' | 'question' | 'answer') => EventResult
  > = [];

  // Check first conversation
  if (!player.askedQuestions.has('firstConversation') && (player.r ?? []).length > 0) {
    eventsToCheck.push(firstConversation);
  }

  // Check first activity
  if (!player.askedQuestions.has('firstActivityChoice') && player.c.ageYears >= 5) {
    eventsToCheck.push(firstActivityChoice);
  }

  // Check tutorial completion
  if (!player.askedQuestions.has('tutorialComplete') && (player.c.ageHours ?? 0) >= 24) {
    eventsToCheck.push(tutorialComplete);
  }

  return eventsToCheck;
}

// ===== Additional Tutorial Events =====

/**
 * Tutorial Energy Explained
 * Trigger: First time energy < 20
 */
export function tutorialEnergyExplained(player: Player): EventResult {
  const fname = 'tutorialEnergyExplained';
  const check = !player.askedQuestions.has(fname) && (player.c.energy ?? 100) < 20;

  if (check) {
    const message =
      "Your energy is running low! When you're tired, activities cost more effort and you'll feel worse. Make sure to rest!";
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Money Explained
 * Trigger: First question with moneyCost
 */
export function tutorialMoneyExplained(player: Player): EventResult {
  const fname = 'tutorialMoneyExplained';
  const check = !player.askedQuestions.has(fname);

  if (check) {
    const message =
      'This choice costs money! You earn money through jobs and can spend it on activities and items. Choose wisely!';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Relationship Explained
 * Trigger: First NPC interaction
 */
export function tutorialRelationshipExplained(player: Player): EventResult {
  const fname = 'tutorialRelationshipExplained';
  const hasRelationships = (player.r ?? []).length > 0;
  const hasAffinity = (player.r ?? []).some((p) => p.affinity !== undefined);
  const check = !player.askedQuestions.has(fname) && hasRelationships && hasAffinity;

  if (check) {
    const message =
      'Each person has an affinity toward you that changes based on your interactions. Higher affinity means better relationships!';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Stats Explained
 * Trigger: After first stat change (ageHours >= 2)
 */
export function tutorialStatsExplained(player: Player): EventResult {
  const fname = 'tutorialStatsExplained';
  const check = !player.askedQuestions.has(fname) && (player.c.ageHours ?? 0) >= 2;

  if (check) {
    const message =
      'Your choices affect your stats! Keep an eye on happiness, health, intelligence, and social skills.';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Diamonds Earned
 * Trigger: First time earning diamonds
 */
export function tutorialDiamondsEarned(player: Player): EventResult {
  const fname = 'tutorialDiamondsEarned';
  const check = !player.askedQuestions.has(fname) && (player.c.diamonds ?? 0) > 0;

  if (check) {
    const message =
      'You earned diamonds! These are special currency for premium choices that unlock better outcomes.';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Game Speed Explained
 * Trigger: After 1 hour of game time
 */
export function tutorialGameSpeedExplained(player: Player): EventResult {
  const fname = 'tutorialGameSpeedExplained';
  const check = !player.askedQuestions.has(fname) && (player.c.ageHours ?? 0) >= 1;

  if (check) {
    const message =
      'You can control how fast time passes! Use the speed controls to slow down during important moments or speed up during routine times.';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Schedules Intro
 * Trigger: First schedule added
 */
export function tutorialSchedulesIntro(player: Player): EventResult {
  const fname = 'tutorialSchedulesIntro';
  const hasSchedules = (player.c.schedules ?? []).length > 0;
  const check = !player.askedQuestions.has(fname) && hasSchedules;

  if (check) {
    const message =
      "You've started a recurring activity! This will happen automatically on scheduled days. Check your schedules to see what's coming up.";
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial Events Intro
 * Trigger: After 3rd event
 */
export function tutorialEventsIntro(player: Player): EventResult {
  const fname = 'tutorialEventsIntro';
  const eventsCount = player.askedQuestions.size;
  const check = !player.askedQuestions.has(fname) && eventsCount >= 3;

  if (check) {
    const message =
      'Events are how life unfolds! Some happen automatically, others require your choices. Every decision shapes your story.';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial One Time Events
 * Trigger: First oneTimeEvent scheduled
 */
export function tutorialOneTimeEvents(player: Player): EventResult {
  const fname = 'tutorialOneTimeEvents';
  const hasOneTimeEvents = (player.c.oneTimeEvents ?? []).length > 0;
  const check = !player.askedQuestions.has(fname) && hasOneTimeEvents;

  if (check) {
    const message =
      'Some events are scheduled for the future! Keep an eye on your calendar for upcoming moments.';
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * Tutorial First Milestone
 * Trigger: First major milestone completed
 * Awards 5 diamonds
 */
export function tutorialFirstMilestone(player: Player): EventResult {
  const fname = 'tutorialFirstMilestone';

  // Check if player has completed any major milestone events
  const majorMilestones = [
    'learnedWalk',
    'learnedBike',
    'learnedSwim',
    'firstDayOfSchool',
    'lostFirstTooth',
    'likeSchool',
    'firstCrush',
    'firstKiss',
  ];

  const hasMilestone = majorMilestones.some((milestone) =>
    player.askedQuestions.has(milestone)
  );
  const check = !player.askedQuestions.has(fname) && hasMilestone;

  if (check) {
    const c = player.c;

    // Award 5 diamonds
    c.diamonds = (c.diamonds ?? 0) + 5;

    const message =
      'Congratulations on your first major milestone! These special moments mark important progress in your life journey. You earned 5 diamonds!';
    return createMessageEvent(fname, message, player, check, { diamondCost: -5 });
  }

  return null;
}

/**
 * Extended check for tutorial triggers
 * Includes all new tutorial events
 */
export function checkAllTutorialTriggers(
  player: Player
): Array<(player: Player) => EventResult> {
  if (!isTutorialMode(player)) {
    return [];
  }

  const eventsToCheck: Array<(player: Player) => EventResult> = [];

  // Original tutorial events
  if (!player.askedQuestions.has('firstConversation') && (player.r ?? []).length > 0) {
    eventsToCheck.push((p) => firstConversation(p, 'question'));
  }

  if (!player.askedQuestions.has('firstActivityChoice') && player.c.ageYears >= 5) {
    eventsToCheck.push((p) => firstActivityChoice(p, 'question'));
  }

  if (!player.askedQuestions.has('tutorialComplete') && (player.c.ageHours ?? 0) >= 24) {
    eventsToCheck.push(tutorialComplete);
  }

  // New tutorial events
  if (!player.askedQuestions.has('tutorialGameSpeedExplained') && (player.c.ageHours ?? 0) >= 1) {
    eventsToCheck.push(tutorialGameSpeedExplained);
  }

  if (!player.askedQuestions.has('tutorialStatsExplained') && (player.c.ageHours ?? 0) >= 2) {
    eventsToCheck.push(tutorialStatsExplained);
  }

  if (!player.askedQuestions.has('tutorialEventsIntro') && player.askedQuestions.size >= 3) {
    eventsToCheck.push(tutorialEventsIntro);
  }

  if (!player.askedQuestions.has('tutorialEnergyExplained') && (player.c.energy ?? 100) < 20) {
    eventsToCheck.push(tutorialEnergyExplained);
  }

  if (
    !player.askedQuestions.has('tutorialRelationshipExplained') &&
    (player.r ?? []).length > 0
  ) {
    eventsToCheck.push(tutorialRelationshipExplained);
  }

  if (
    !player.askedQuestions.has('tutorialDiamondsEarned') &&
    (player.c.diamonds ?? 0) > 0
  ) {
    eventsToCheck.push(tutorialDiamondsEarned);
  }

  if (
    !player.askedQuestions.has('tutorialSchedulesIntro') &&
    (player.c.schedules ?? []).length > 0
  ) {
    eventsToCheck.push(tutorialSchedulesIntro);
  }

  if (
    !player.askedQuestions.has('tutorialOneTimeEvents') &&
    (player.c.oneTimeEvents ?? []).length > 0
  ) {
    eventsToCheck.push(tutorialOneTimeEvents);
  }

  // tutorialFirstMilestone has its own complex check
  eventsToCheck.push(tutorialFirstMilestone);

  // tutorialMoneyExplained is triggered externally when a choice with moneyCost appears
  eventsToCheck.push(tutorialMoneyExplained);

  return eventsToCheck;
}

/**
 * All tutorial event functions
 */
export const tutorialEvents = {
  firstConversation,
  firstActivityChoice,
  tutorialComplete,
  tutorialEnergyExplained,
  tutorialMoneyExplained,
  tutorialRelationshipExplained,
  tutorialStatsExplained,
  tutorialDiamondsEarned,
  tutorialGameSpeedExplained,
  tutorialSchedulesIntro,
  tutorialEventsIntro,
  tutorialOneTimeEvents,
  tutorialFirstMilestone,
};
