/**
 * Outdoor & Adventure Activity Events
 * Ported from Python ws/events/activities/seasonal.py
 *
 * Events:
 * - CampingTripEvent: Friends planning camping trip (ages 8-70)
 * - HikingAdventureEvent: Weekend hiking adventure (ages 10-70)
 * - SkiingVacationEvent: Skiing/snowboarding vacation - Winter only (ages 10-60)
 * - BeachDayEvent: Perfect day for the beach - Summer only (ages 5-100)
 * - AutumnActivitiesEvent: Apple picking and pumpkin patch - Fall only (ages 5-100)
 */

import { BaseEvent, EventResult, AnswerOption, EventConfig, checkProbability } 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')
  );
}

/**
 * Get all family members from player relationships
 */
function getAllFamily(player: Player): Person[] {
  return (player.r ?? []).filter((person: Person) => {
    const relationships = person.relationships ?? [];
    return (
      relationships.includes('mother') ||
      relationships.includes('father') ||
      relationships.includes('sibling') ||
      relationships.includes('spouse') ||
      relationships.includes('child') ||
      relationships.includes('grandparent')
    );
  });
}

/**
 * Check if it's a weekend (Saturday or Sunday)
 */
function isWeekend(player: Player): boolean {
  return player.dayOfWeek === 6 || player.dayOfWeek === 7;
}

/**
 * Outdoor Camping Trip Event
 * Friends planning a camping trip - weekend event
 * Enhanced version with family support and richer messaging
 */
export class OutdoorCampingTripEvent extends BaseEvent {
  readonly id = 'outdoorCampingTrip';

  getConfig(): EventConfig {
    return {
      minAge: 8,
      maxAge: 70,
      baseChance: 0.0005, // 1 in 2000
      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 &&
      isWeekend(player) &&
      c.energy >= 30 &&
      checkProbability(2000)
    );
  }

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

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

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

    if (selectedOption === 0) {
      // Full camping experience
      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) {
      // Cabin option
      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 {
      // Decline
      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.",
      };
    }
  }
}

/**
 * Outdoor Hiking Adventure Event
 * Weekend hiking adventure - good for spring, summer, fall
 * Enhanced version with hiking buddy support
 */
export class OutdoorHikingAdventureEvent extends BaseEvent {
  readonly id = 'outdoorHikingAdventure';

  getConfig(): EventConfig {
    return {
      minAge: 10,
      maxAge: 70,
      baseChance: 0.0005, // 1 in 2000
      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)
      isWeekend(player) &&
      c.energy >= 40 &&
      checkProbability(2000)
    );
  }

  getQuestion(player?: Player): string {
    const friends = player ? getAllFriends(player) : [];
    const hasHikingBuddy = friends.length > 0 && Math.random() < 0.4;

    if (hasHikingBuddy && friends.length > 0) {
      const buddy = friends[Math.floor(Math.random() * friends.length)];
      return `Plan a hiking adventure this weekend? ${buddy.firstname} wants to join!`;
    }
    return 'Plan a hiking adventure this weekend?';
  }

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

  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) {
      // Challenging trail
      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) {
      // Easy nature walk
      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 {
      // Decline
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);

      if (hasHikingBuddy && friends.length > 0) {
        const hikingBuddy = friends[Math.floor(Math.random() * friends.length)];
        hikingBuddy.affinity = Math.max(0, (hikingBuddy.affinity ?? 50) - 10);
        c.social = Math.max(0, (c.social ?? 50) - 5);
        return {
          type: 'messageEvent',
          message: `You decline the hiking invitation. ${hikingBuddy.firstname} is disappointed but understands.`,
        };
      }

      return {
        type: 'messageEvent',
        message:
          'You skip the hiking adventure and stay home instead. Maybe another time.',
      };
    }
  }
}

/**
 * Outdoor Skiing Vacation Event
 * Skiing/snowboarding vacation - Winter only
 * Enhanced version with multiple package options
 */
export class OutdoorSkiingVacationEvent extends BaseEvent {
  readonly id = 'outdoorSkiingVacation';

  getConfig(): EventConfig {
    return {
      minAge: 10,
      maxAge: 60,
      baseChance: 0.00033, // 1 in 3000
      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 &&
      checkProbability(3000)
    );
  }

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

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

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

    if (selectedOption === 0) {
      // Expert skiing
      if ((c.money ?? 0) < 800) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for the full ski package.",
        };
      }
      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) {
      // Beginner lessons
      if ((c.money ?? 0) < 500) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for the ski lessons package.",
        };
      }
      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) {
      // Lodge stay
      if ((c.money ?? 0) < 300) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for the lodge getaway.",
        };
      }
      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 {
      // Decline
      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.",
      };
    }
  }
}

/**
 * Outdoor Beach Day Event
 * Perfect day for the beach - Summer only
 * Enhanced version with family and friends support
 */
export class OutdoorBeachDayEvent extends BaseEvent {
  readonly id = 'outdoorBeachDay';

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

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 5 &&
      player.season === 'summer' &&
      isWeekend(player) &&
      c.energy >= 20 &&
      checkProbability(1500)
    );
  }

  getQuestion(player?: Player): string {
    const friends = player ? getAllFriends(player) : [];
    const family = player ? getAllFamily(player) : [];
    const hasCompanions = friends.length > 0 || family.length > 0;

    if (hasCompanions) {
      return "It's a perfect summer day! Friends and family want to go to the beach.";
    }
    return "It's a perfect summer day! Go to the beach?";
  }

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

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const friends = getAllFriends(player);
    const family = getAllFamily(player);
    const companions = [...friends, ...family];
    const hasCompanions = companions.length > 0;

    if (selectedOption === 0) {
      // All day at the beach
      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 (hasCompanions) {
        for (const person of companions) {
          person.affinity = Math.min(100, (person.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 and family. 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) {
      // Quick visit
      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);

      // Small affinity boost if with companions
      if (hasCompanions && Math.random() < 0.5) {
        const companion = companions[Math.floor(Math.random() * companions.length)];
        companion.affinity = Math.min(100, (companion.affinity ?? 50) + 10);
        c.social = Math.min(100, (c.social ?? 50) + 10);
        return {
          type: 'messageEvent',
          message: `You make a quick trip to the beach with ${companion.firstname}. A refreshing swim and some sun - just what you needed!`,
        };
      }

      return {
        type: 'messageEvent',
        message:
          'You make a quick trip to the beach for a refreshing swim and some sun. Just what you needed!',
      };
    } else {
      // Decline
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);

      if (hasCompanions) {
        c.social = Math.max(0, (c.social ?? 50) - 5);
        return {
          type: 'messageEvent',
          message:
            'You stay home in the air conditioning instead. Your friends and family are disappointed but understand.',
        };
      }

      return {
        type: 'messageEvent',
        message:
          'You stay home in the air conditioning instead. The beach can wait for a cooler day.',
      };
    }
  }
}

/**
 * Outdoor Autumn Activities Event
 * Apple picking and pumpkin patch - Fall only, family-friendly weekend activity
 * Enhanced version with family priority and friend support
 */
export class OutdoorAutumnActivitiesEvent extends BaseEvent {
  readonly id = 'outdoorAutumnActivities';

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

  checkConditions(player: Player): boolean {
    const c = player.c;
    return (
      !player.askedQuestions.has(this.id) &&
      c.ageYears >= 5 &&
      player.season === 'autumn' &&
      isWeekend(player) &&
      (c.money ?? 0) >= 20 &&
      c.energy >= 15 &&
      checkProbability(2000)
    );
  }

  getQuestion(player?: Player): string {
    const family = player ? getAllFamily(player) : [];
    const friends = player ? getAllFriends(player) : [];
    const hasFamily = family.length > 0;

    if (hasFamily) {
      return 'The family wants to go apple picking and visit the pumpkin patch! Join them?';
    } else if (friends.length > 0) {
      return 'Friends are organizing an autumn outing to go apple picking and visit a pumpkin patch. Interested?';
    }
    return "There's an apple orchard and pumpkin patch nearby. Visit today?";
  }

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

  processAnswer(player: Player, selectedOption: number): EventResult {
    const c = player.c;
    const family = getAllFamily(player);
    const friends = getAllFriends(player);
    const hasFamily = family.length > 0;
    const hasCompanions = hasFamily || friends.length > 0;

    if (selectedOption === 0) {
      // Full autumn day
      if ((c.money ?? 0) < 50) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for the full autumn day.",
        };
      }
      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
      if (hasFamily) {
        for (const member of family) {
          member.affinity = Math.min(100, (member.affinity ?? 50) + 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 with the family. Fall memories in the making!',
        };
      } else 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) + 15);
        return {
          type: 'messageEvent',
          message:
            "Autumn outing planned! Apple picking and pumpkin patch with friends. You'll come home with fresh apples, perfect pumpkins, and great memories!",
        };
      }

      return {
        type: 'messageEvent',
        message:
          "Autumn day planned! Apple picking and exploring the pumpkin patch. You'll enjoy the crisp fall air and seasonal fun!",
      };
    } else if (selectedOption === 1) {
      // Just pumpkin patch
      if ((c.money ?? 0) < 20) {
        return {
          type: 'messageEvent',
          message: "You don't have enough money for the pumpkin patch visit.",
        };
      }
      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 with companions
      if (hasCompanions) {
        const companions = [...family, ...friends].slice(0, 2);
        for (const person of companions) {
          person.affinity = Math.min(100, (person.affinity ?? 50) + 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!",
        };
      }

      return {
        type: 'messageEvent',
        message:
          "Pumpkin patch visit planned! You'll pick out the perfect pumpkin for fall decorating!",
      };
    } else {
      // Decline
      c.happiness = Math.max(0, (c.happiness ?? 50) - 5);

      if (hasFamily) {
        const membersToAffect = family.slice(0, 2);
        for (const member of membersToAffect) {
          member.affinity = Math.max(0, (member.affinity ?? 50) - 10);
        }
        c.social = Math.max(0, (c.social ?? 50) - 10);
        return {
          type: 'messageEvent',
          message:
            'You skip the autumn activities. The family is disappointed but understands.',
        };
      } else if (friends.length > 0) {
        const friend = friends[Math.floor(Math.random() * friends.length)];
        friend.affinity = Math.max(0, (friend.affinity ?? 50) - 5);
        c.social = Math.max(0, (c.social ?? 50) - 5);
        return {
          type: 'messageEvent',
          message:
            'You skip the autumn outing. Your friends wish you\'d join but understand.',
        };
      }

      return {
        type: 'messageEvent',
        message: 'You skip the autumn activities. Fall will come again next year.',
      };
    }
  }
}

// Export all outdoor/adventure events
export const outdoorEvents = [
  new OutdoorCampingTripEvent(),
  new OutdoorHikingAdventureEvent(),
  new OutdoorSkiingVacationEvent(),
  new OutdoorBeachDayEvent(),
  new OutdoorAutumnActivitiesEvent(),
];
