/**
 * Seasonal & Outdoor Activity Events
 * Seasonal and outdoor recreational activities (ages 5-100)
 */

import { BaseEvent, EventResult, AnswerOption, EventConfig } from '../base.js';
import { Player, Person } from '../../models/index.js';

/**
 * Get all friends from player relationships
 */
function getAllFriends(player: Player): Person[] {
  return (player.r ?? []).filter(
    (person: Person) => person.relationships?.includes('friend')
  );
}

/**
 * Camping Trip Event
 */
export class CampingTripEvent extends BaseEvent {
  readonly id = 'campingTrip';

  getConfig(): EventConfig {
    return {
      minAge: 8,
      maxAge: 70,
      baseChance: 0.0005,
      triggerType: 'random',
    };
  }

  checkConditions(player: Player): boolean {
    const c = player.c;
    const friends = getAllFriends(player);

    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 8 &&
      c.ageYears <= 70 &&
      friends.length > 0 &&
      (player.dayOfWeek === 6 || player.dayOfWeek === 7) && // Weekend
      c.energy >= 30
    );
  }

  getQuestion(): string {
    return 'Friends are planning a camping trip this weekend. Join them?';
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      { option: 'Yes, love camping!', energyCost: 20 },
      { option: 'Go but stay in cabin', moneyCost: 100 },
      { option: 'Not outdoorsy' },
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const friends = getAllFriends(player);

    if (selectedOption === 0) {
      c.energy = Math.max(0, c.energy - 20);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 30);
      c.social = Math.min(100, (c.social ?? 50) + 20);

      // Increase affinity with all friends
      for (const friend of friends) {
        friend.affinity = Math.min(100, (friend.affinity ?? 50) + 25);
      }

      return {
        type: 'messageEvent',
        message:
          "You're going camping! Sleeping under the stars, telling stories around the campfire, and hiking during the day. Your friends are excited!",
      };
    } else if (selectedOption === 1) {
      if ((c.money ?? 0) < 100) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for a cabin rental.",
        };
      }
      c.money = (c.money ?? 0) - 100;
      c.happiness = Math.min(100, (c.happiness ?? 50) + 20);
      c.social = Math.min(100, (c.social ?? 50) + 15);

      // Increase affinity with all friends
      for (const friend of friends) {
        friend.affinity = Math.min(100, (friend.affinity ?? 50) + 20);
      }

      return {
        type: 'messageEvent',
        message:
          "You're joining your friends but staying in a cozy cabin. The best of both worlds!",
      };
    } else {
      c.happiness = Math.max(0, (c.happiness ?? 50) - 10);

      // Decrease affinity with friends
      for (const friend of friends) {
        friend.affinity = Math.max(0, (friend.affinity ?? 50) - 15);
      }

      return {
        type: 'messageEvent',
        message:
          "You decline the camping trip. Your friends are disappointed you won't be joining them.",
      };
    }
  }
}

/**
 * Skiing Vacation Event - Winter only
 */
export class SkiingVacationEvent extends BaseEvent {
  readonly id = 'skiingVacation';

  getConfig(): EventConfig {
    return {
      minAge: 10,
      maxAge: 60,
      baseChance: 0.00033,
      triggerType: 'random',
    };
  }

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 10 &&
      c.ageYears <= 60 &&
      player.season === 'winter' &&
      (c.money ?? 0) >= 300 &&
      c.energy >= 30
    );
  }

  getQuestion(): string {
    return "There's a ski resort offering winter vacation packages. Interested?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      { option: 'Yes, hit the slopes!', moneyCost: 800, energyCost: 30 },
      { option: 'Learn to ski', moneyCost: 500, energyCost: 20 },
      { option: 'Stay in lodge', moneyCost: 300 },
      { option: 'Too expensive' },
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;

    if (selectedOption === 0) {
      c.money = (c.money ?? 0) - 800;
      c.energy = Math.max(0, c.energy - 30);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 35);
      c.health = Math.min(100, (c.health ?? 50) + 15);
      c.stress = Math.max(0, (c.stress ?? 0) - 20);

      return {
        type: 'messageEvent',
        message:
          "Ski vacation booked! You'll hit the slopes soon. The fresh mountain air and thrill of skiing await!",
      };
    } else if (selectedOption === 1) {
      c.money = (c.money ?? 0) - 500;
      c.energy = Math.max(0, c.energy - 20);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 25);
      c.health = Math.min(100, (c.health ?? 50) + 10);

      return {
        type: 'messageEvent',
        message:
          "Ski lessons booked! You'll learn to ski and have a great time on the slopes!",
      };
    } else if (selectedOption === 2) {
      c.money = (c.money ?? 0) - 300;
      c.happiness = Math.min(100, (c.happiness ?? 50) + 20);
      c.stress = Math.max(0, (c.stress ?? 0) - 25);

      return {
        type: 'messageEvent',
        message:
          'Lodge getaway booked! Sipping hot cocoa by the fireplace with beautiful mountain views sounds perfect!',
      };
    } else {
      c.happiness = Math.max(0, (c.happiness ?? 50) - 15);
      return {
        type: 'messageEvent',
        message:
          "You skip the ski vacation due to the cost. Maybe next year when you've saved up more.",
      };
    }
  }
}

/**
 * Beach Day Event - Summer only
 */
export class BeachDayEvent extends BaseEvent {
  readonly id = 'beachDay';

  getConfig(): EventConfig {
    return {
      minAge: 5,
      maxAge: 100,
      baseChance: 0.00067,
      triggerType: 'random',
    };
  }

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 5 &&
      player.season === 'summer' &&
      (player.dayOfWeek === 6 || player.dayOfWeek === 7) && // Weekend
      c.energy >= 20
    );
  }

  getQuestion(): string {
    return "It's a perfect summer day! Go to the beach?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      { option: 'Yes, all day!', energyCost: 15 },
      { option: 'Quick visit' },
      { option: 'Too hot, stay home' },
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const friends = getAllFriends(player);

    if (selectedOption === 0) {
      c.energy = Math.max(0, c.energy - 15);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 25);
      c.stress = Math.max(0, (c.stress ?? 0) - 15);
      c.health = Math.min(100, (c.health ?? 50) + 10);

      // Increase affinity with companions
      if (friends.length > 0) {
        for (const friend of friends) {
          friend.affinity = Math.min(100, (friend.affinity ?? 50) + 20);
        }
        c.social = Math.min(100, (c.social ?? 50) + 20);
        return {
          type: 'messageEvent',
          message:
            "You're heading to the beach! Swimming, building sandcastles, and soaking up the sun with friends. A perfect summer day!",
        };
      }

      return {
        type: 'messageEvent',
        message:
          "You're going to the beach! Swimming and soaking up the sun. A perfect day to relax!",
      };
    } else if (selectedOption === 1) {
      c.happiness = Math.min(100, (c.happiness ?? 50) + 15);
      c.stress = Math.max(0, (c.stress ?? 0) - 10);
      c.energy = Math.max(0, c.energy - 5);

      return {
        type: 'messageEvent',
        message:
          'You make a quick trip to the beach for a refreshing swim and some sun. Just what you needed!',
      };
    } else {
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);
      return {
        type: 'messageEvent',
        message:
          'You stay home in the air conditioning instead. The beach can wait for a cooler day.',
      };
    }
  }
}

/**
 * Hiking Adventure Event
 */
export class HikingAdventureEvent extends BaseEvent {
  readonly id = 'hikingAdventure';

  getConfig(): EventConfig {
    return {
      minAge: 10,
      maxAge: 70,
      baseChance: 0.0005,
      triggerType: 'random',
    };
  }

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 10 &&
      c.ageYears <= 70 &&
      player.season !== 'winter' && // Not winter (too cold)
      (player.dayOfWeek === 6 || player.dayOfWeek === 7) && // Weekend
      c.energy >= 40
    );
  }

  getQuestion(): string {
    return 'Plan a hiking adventure this weekend?';
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      { option: 'Yes, challenging trail!', energyCost: 30 },
      { option: 'Easy nature walk', energyCost: 10 },
      { option: 'Not interested' },
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const friends = getAllFriends(player);
    const hasHikingBuddy = friends.length > 0 && Math.random() < 0.4;

    if (selectedOption === 0) {
      c.energy = Math.max(0, c.energy - 30);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 30);
      c.health = Math.min(100, (c.health ?? 50) + 20);
      c.stress = Math.max(0, (c.stress ?? 0) - 20);

      if (hasHikingBuddy && friends.length > 0) {
        const hikingBuddy = friends[Math.floor(Math.random() * friends.length)];
        hikingBuddy.affinity = Math.min(100, (hikingBuddy.affinity ?? 50) + 25);
        c.social = Math.min(100, (c.social ?? 50) + 15);
        return {
          type: 'messageEvent',
          message: `You and ${hikingBuddy.firstname} are tackling a challenging mountain trail! The steep climbs will test your endurance, but the summit view will be worth it!`,
        };
      }

      return {
        type: 'messageEvent',
        message:
          "You're tackling a challenging mountain trail! The steep climbs will test your endurance, but reaching the summit will be worth it!",
      };
    } else if (selectedOption === 1) {
      c.energy = Math.max(0, c.energy - 10);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 20);
      c.health = Math.min(100, (c.health ?? 50) + 10);
      c.stress = Math.max(0, (c.stress ?? 0) - 15);

      if (hasHikingBuddy && friends.length > 0) {
        const hikingBuddy = friends[Math.floor(Math.random() * friends.length)];
        hikingBuddy.affinity = Math.min(100, (hikingBuddy.affinity ?? 50) + 15);
        c.social = Math.min(100, (c.social ?? 50) + 10);
        return {
          type: 'messageEvent',
          message: `You and ${hikingBuddy.firstname} are going on a peaceful nature walk! Fresh air, beautiful scenery, and gentle exercise - perfect!`,
        };
      }

      return {
        type: 'messageEvent',
        message:
          "You're going on a peaceful nature walk! The fresh air and beautiful scenery will be refreshing!",
      };
    } else {
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);
      return {
        type: 'messageEvent',
        message:
          'You skip the hiking adventure and stay home instead. Maybe another time.',
      };
    }
  }
}

/**
 * Autumn Activities Event - Fall only
 */
export class AutumnActivitiesEvent extends BaseEvent {
  readonly id = 'autumnActivities';

  getConfig(): EventConfig {
    return {
      minAge: 5,
      maxAge: 100,
      baseChance: 0.0005,
      triggerType: 'random',
    };
  }

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 5 &&
      player.season === 'autumn' &&
      (player.dayOfWeek === 6 || player.dayOfWeek === 7) && // Weekend
      (c.money ?? 0) >= 20 &&
      c.energy >= 15
    );
  }

  getQuestion(): string {
    return "There's an apple orchard and pumpkin patch nearby. Visit today?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      { option: 'Yes, full autumn day!', moneyCost: 50, energyCost: 15 },
      { option: 'Just pumpkin patch', moneyCost: 20 },
      { option: 'Not interested' },
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const friends = getAllFriends(player);

    if (selectedOption === 0) {
      c.money = (c.money ?? 0) - 50;
      c.energy = Math.max(0, c.energy - 15);
      c.happiness = Math.min(100, (c.happiness ?? 50) + 25);
      c.stress = Math.max(0, (c.stress ?? 0) - 15);

      // Increase affinity with family/friends
      for (const person of player.r ?? []) {
        if (person.affinity !== undefined) {
          person.affinity = Math.min(100, person.affinity + 25);
        }
      }
      c.social = Math.min(100, (c.social ?? 50) + 20);

      return {
        type: 'messageEvent',
        message:
          'Perfect autumn day planned! Apple picking, pumpkin patch, hay rides, and fresh cider. Fall memories in the making!',
      };
    } else if (selectedOption === 1) {
      c.money = (c.money ?? 0) - 20;
      c.happiness = Math.min(100, (c.happiness ?? 50) + 15);
      c.stress = Math.max(0, (c.stress ?? 0) - 10);

      // Small affinity boost
      if ((player.r ?? []).length > 0) {
        const companions = (player.r ?? []).slice(0, 2);
        for (const person of companions) {
          if (person.affinity !== undefined) {
            person.affinity = Math.min(100, person.affinity + 10);
          }
        }
        c.social = Math.min(100, (c.social ?? 50) + 10);
      }

      return {
        type: 'messageEvent',
        message:
          "Quick pumpkin patch visit planned! You'll pick out perfect pumpkins and enjoy the autumn atmosphere!",
      };
    } else {
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);
      return {
        type: 'messageEvent',
        message:
          'You skip the autumn activities. Fall will come again next year.',
      };
    }
  }
}

// Export all seasonal events
export const seasonalEvents = [
  new CampingTripEvent(),
  new SkiingVacationEvent(),
  new BeachDayEvent(),
  new HikingAdventureEvent(),
  new AutumnActivitiesEvent(),
];
