/**
 * Medical Arc Events (Multi-Stage)
 *
 * Deep narrative arcs for health-related storylines.
 * These are class-based events for fast mode gameplay.
 *
 * Class-based events:
 * - DiagnosisReveal: Multi-stage diagnosis tied to 13 existing health conditions
 * - MedicalEmergency: Sudden emergency requiring immediate decisions
 * - TherapyArc: Multi-stage therapy journey (start -> sessions -> completion)
 * - PregnancyArc: 5-stage pregnancy journey
 * - ParentSickArc: Parent gets seriously ill (moved to family, kept here as health tie-in)
 */

import { Player } from '../../models/Player.js';
import { Person } from '../../models/Person.js';
import {
  BaseEvent,
  EventConfig,
  EventResult,
  AnswerOption,
  createAnswerOption,
  modifyStat,
} from '../base.js';
import { type HealthCondition, getHealthConditions } from '../../services/health/health_manager.js';

// =============================================================================
// Helper: schedule follow-up via oneTimeEvents
// =============================================================================

function scheduleFollowUp(
  player: Player,
  id: string,
  daysFromNow: number,
  hour: number,
  message: string
): void {
  let targetDayOfYear = (player.dayOfYear ?? 1) + daysFromNow;
  if (targetDayOfYear > 365) targetDayOfYear -= 365;

  const baseDate = new Date(2022, 0, 1);
  const targetDate = new Date(baseDate);
  targetDate.setDate(targetDate.getDate() + targetDayOfYear - 1);
  const month = String(targetDate.getMonth() + 1).padStart(2, '0');
  const day = String(targetDate.getDate()).padStart(2, '0');
  const dateStr = `${month}-${day}`;

  player.c.oneTimeEvents = player.c.oneTimeEvents ?? [];
  player.c.oneTimeEvents.push({ id, date: dateStr, hour, message });
}

// =============================================================================
// DiagnosisReveal - Multi-stage diagnosis tied to existing conditions
// =============================================================================

/**
 * Stage 1: Symptoms appear and doctor recommends tests
 * Stage 2 (1 week later via follow-up): Diagnosis confirmed, treatment options
 */
export class DiagnosisReveal extends BaseEvent {
  readonly id = 'diagnosisReveal';

  get mode(): 'fast' { return 'fast'; }

  getConfig(): EventConfig {
    return {
      minAge: 20,
      maxAge: 100,
      baseChance: 0.0003,
      triggerType: 'conditional',
    };
  }

  checkConditions(player: Player): boolean {
    if (player.askedQuestions.has(this.id)) return false;

    // Don't trigger if player already has multiple conditions
    const characterAny = player.character as unknown as { healthConditions?: HealthCondition[] };
    const existing = characterAny.healthConditions ?? [];
    return existing.length < 2;
  }

  getQuestion(player?: Player): string {
    const age = player?.c.ageYears ?? 30;
    if (age > 60) {
      return "You've been experiencing persistent symptoms that worry you. Fatigue, unexplained aches, and things just don't feel right. Your doctor wants to run some tests. How do you respond?";
    }
    return "Something hasn't felt right lately. You've had unusual symptoms that won't go away. Your doctor looks concerned during your visit and recommends running some tests. What do you do?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      createAnswerOption('Get all the tests done ($500)', 'tests', 10, 0, 500),
      createAnswerOption('Get a second opinion first ($300)', 'second', 5, 0, 300),
      createAnswerOption('Do basic tests only ($200)', 'basic', 5, 0, 200),
      createAnswerOption("I'm sure it's nothing, skip tests", 'skip'),
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    if (selectedOption === 3) {
      // Skip - schedule a worsening symptom in 30 days
      scheduleFollowUp(
        player,
        `diagnosisReveal_skipped`,
        30,
        10,
        "The symptoms you ignored have gotten worse. You can't put off seeing a doctor any longer. The uncertainty is affecting your daily life."
      );
      player.c.stress = modifyStat(player.c.stress, 10);
      return {
        type: 'messageEvent',
        message: "You decided to skip the tests. Maybe it'll go away on its own. But the worry lingers in the back of your mind.",
      };
    }

    // Pick a condition from the 13 existing ones
    const conditions = getHealthConditions();
    const ageAppropriate = conditions.filter((c) => {
      // Chronic conditions for older players, acute for younger
      if (player.c.ageYears < 40) return c.averageDuration < 99999;
      return true;
    });
    const condition = ageAppropriate[Math.floor(Math.random() * ageAppropriate.length)];

    // Apply the condition
    const characterAny = player.character as unknown as { healthConditions?: HealthCondition[] };
    characterAny.healthConditions = characterAny.healthConditions ?? [];
    const appliedCondition = { ...condition, date: player.date };
    characterAny.healthConditions.push(appliedCondition);

    player.c.happiness = modifyStat(player.c.happiness, -10);
    player.c.stress = modifyStat(player.c.stress, 15);
    player.money = Math.max(0, player.money - (selectedOption === 0 ? 500 : selectedOption === 1 ? 300 : 200));

    const isChronic = condition.averageDuration >= 99999;

    // Schedule follow-up with treatment progress
    if (isChronic) {
      scheduleFollowUp(
        player,
        `diagnosisReveal_treatment_${condition.id}`,
        14,
        10,
        `Two weeks into managing your ${condition.title}. The medication is helping but it's an adjustment. Your doctor says consistency is key. You're learning to live with this new reality.`
      );
    } else {
      scheduleFollowUp(
        player,
        `diagnosisReveal_recovery_${condition.id}`,
        condition.averageDuration * 7,
        10,
        `After weeks of treatment, your ${condition.title} has cleared up. You feel like yourself again. The experience reminded you not to take your health for granted.`
      );
    }

    const costLabel = selectedOption === 0 ? '$500' : selectedOption === 1 ? '$300' : '$200';

    return {
      type: 'messageEvent',
      message: `The test results are in. You've been diagnosed with ${condition.title}. ${condition.description} The medical bills came to ${costLabel}. Your doctor outlined a treatment plan and you're trying to process it all.`,
      moneyCost: selectedOption === 0 ? 500 : selectedOption === 1 ? 300 : 200,
    };
  }
}

// =============================================================================
// MedicalEmergency - Sudden emergency requiring immediate decisions
// =============================================================================

export class MedicalEmergency extends BaseEvent {
  readonly id = 'medicalEmergency';

  get mode(): 'fast' { return 'fast'; }

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

  checkConditions(player: Player): boolean {
    return !player.askedQuestions.has(this.id);
  }

  getQuestion(player?: Player): string {
    const age = player?.c.ageYears ?? 30;
    if (age < 18) {
      return "You're rushed to the hospital after collapsing at school. The doctors are running tests and your parents are on their way. Everything is happening fast.";
    }
    return "You wake up in the middle of the night with severe chest pains and difficulty breathing. This feels serious. What do you do?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      createAnswerOption('Call 911 immediately', 'emergency', 0, 0, 5000),
      createAnswerOption('Drive yourself to the ER', 'drive', 20, 0, 3000),
      createAnswerOption('Call a family member for help', 'family', 10, 0, 3000),
      createAnswerOption('Wait and see if it passes', 'wait'),
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    if (selectedOption === 3) {
      // Wait - bad outcome
      player.c.health = modifyStat(player.c.health, -20);
      player.c.happiness = modifyStat(player.c.happiness, -15);

      scheduleFollowUp(
        player,
        `medicalEmergency_delayed`,
        1,
        8,
        "You ended up in the hospital anyway, but the delay made things worse. The doctors said waiting could have been fatal. You spend extra days recovering."
      );

      return {
        type: 'messageEvent',
        message: "You tried to wait it out, but the symptoms got worse through the night. By morning, you couldn't ignore it anymore.",
      };
    }

    const costs = [5000, 3000, 3000];
    const cost = costs[selectedOption] ?? 3000;
    player.money = Math.max(0, player.money - cost);
    player.c.health = modifyStat(player.c.health, -10);
    player.c.energy = modifyStat(player.c.energy, -25);
    player.c.stress = modifyStat(player.c.stress, 20);

    // Schedule recovery
    scheduleFollowUp(
      player,
      `medicalEmergency_recovery`,
      7,
      10,
      "A week after your medical emergency, you're recovering well. The experience was scary but the doctors caught it in time. You have a new appreciation for your health."
    );

    const messages = [
      `The ambulance arrived quickly. The paramedics stabilized you and rushed you to the hospital. After hours of tests, they found the problem and started treatment. The bill was $${cost}, but you're alive.`,
      `You drove yourself to the ER, white-knuckling the steering wheel. The triage nurse got you in quickly. After treatment and observation, they let you go home. The bill: $${cost}.`,
      `Your family member rushed over and drove you to the hospital. Having them there made it less terrifying. The doctors treated you and you're stable now. The bill came to $${cost}.`,
    ];

    return {
      type: 'messageEvent',
      message: messages[selectedOption] ?? messages[0],
      moneyCost: cost,
      energyCost: 25,
    };
  }
}

// =============================================================================
// TherapyArc - Multi-stage therapy journey
// =============================================================================

/**
 * Stage 1: Decision to start therapy
 * Stage 2 (2 weeks later): First few sessions feedback
 * Stage 3 (8 weeks later): Therapy completion/continuation decision
 */
export class TherapyArc extends BaseEvent {
  readonly id = 'therapyArc';

  get mode(): 'fast' { return 'fast'; }

  getConfig(): EventConfig {
    return {
      minAge: 16,
      maxAge: 100,
      baseChance: 0.0004,
      triggerType: 'conditional',
    };
  }

  checkConditions(player: Player): boolean {
    if (player.askedQuestions.has(this.id)) return false;
    // More likely if stressed or unhappy
    return (player.c.stress ?? 0) > 50 || (player.c.happiness ?? 50) < 35;
  }

  getQuestion(_player?: Player): string {
    return "A friend mentioned their therapist has really helped them. You've been thinking about it for a while. Therapy costs $150 per session, usually weekly. Do you want to give it a try?";
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      createAnswerOption('Yes, book a session ($150)', 'start', 10, 0, 150),
      createAnswerOption('Look into online therapy ($80)', 'online', 5, 0, 80),
      createAnswerOption("I'll think about it", 'think'),
      createAnswerOption("Therapy isn't for me", 'no'),
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    if (selectedOption >= 2) {
      return {
        type: 'messageEvent',
        message: selectedOption === 2
          ? "You told yourself you'd think about therapy. Maybe someday. For now, you're getting by."
          : "You decided therapy isn't your thing. You'll find your own way to deal with things.",
      };
    }

    const isOnline = selectedOption === 1;
    const cost = isOnline ? 80 : 150;
    player.money = Math.max(0, player.money - cost);
    player.c.stress = modifyStat(player.c.stress, -5);
    player.c.energy = modifyStat(player.c.energy, -10);

    // Stage 2: First sessions feedback (2 weeks later)
    scheduleFollowUp(
      player,
      `therapyArc_stage2`,
      14,
      18,
      isOnline
        ? "You've had a few online therapy sessions now. It felt awkward at first, but your therapist is helping you see patterns you couldn't see before. The sessions cost $80 each but it feels worth it."
        : "You've been going to therapy for two weeks. The first session was nerve-wracking, but your therapist made you feel heard. You're starting to understand why you react the way you do. Each session costs $150."
    );

    // Stage 3: Therapy completion (8 weeks later)
    scheduleFollowUp(
      player,
      `therapyArc_stage3`,
      56,
      18,
      "After two months of therapy, you feel like a different person. You've learned coping strategies, processed old wounds, and your relationships have improved. Your therapist asks if you want to continue or transition to monthly check-ins. Either way, the investment in yourself was worth it."
    );

    return {
      type: 'messageEvent',
      message: isOnline
        ? `You signed up for online therapy. Your first session is tonight from the comfort of your couch. It feels like a big step. Cost: $${cost}.`
        : `You booked your first therapy appointment. Walking into that office took courage, but the therapist was warm and understanding. It felt like a weight lifted just by talking. Cost: $${cost}.`,
      moneyCost: cost,
    };
  }
}

// =============================================================================
// PregnancyArc - 5-stage pregnancy journey
// =============================================================================

/**
 * Stage 1: Discovery
 * Stage 2 (4 weeks): First trimester struggles
 * Stage 3 (12 weeks): Gender reveal / midpoint
 * Stage 4 (24 weeks): Third trimester prep
 * Stage 5 (36 weeks): Birth
 */
export class PregnancyArc extends BaseEvent {
  readonly id = 'pregnancyArc';

  get mode(): 'fast' { return 'fast'; }

  getConfig(): EventConfig {
    return {
      minAge: 18,
      maxAge: 45,
      baseChance: 0.0003,
      triggerType: 'conditional',
    };
  }

  checkConditions(player: Player): boolean {
    if (player.askedQuestions.has(this.id)) return false;

    // Must have a partner and be trying or random chance
    const hasPartner = (player.r ?? []).some(
      (p) =>
        p.status === 'alive' &&
        ((p.relationships ?? []).includes('spouse') || (p.relationships ?? []).includes('partner'))
    );

    const isTrying = player.c.tryingForChild === true;
    return hasPartner && (isTrying || Math.random() < 0.3);
  }

  getQuestion(player?: Player): string {
    const partner = (player?.r ?? []).find(
      (p) =>
        p.status === 'alive' &&
        ((p.relationships ?? []).includes('spouse') || (p.relationships ?? []).includes('partner'))
    );
    const partnerName = partner?.firstname ?? 'your partner';

    if (player?.c.sex === 'Female') {
      return `You've been feeling off for weeks. The test is positive. You're pregnant. How do you tell ${partnerName}?`;
    }
    return `${partnerName} sits you down with a nervous smile and shows you a positive pregnancy test. You're going to be a parent. How do you react?`;
  }

  getAnswerOptions(): AnswerOption[] {
    return [
      createAnswerOption('Overjoyed! Start planning immediately', 'joy'),
      createAnswerOption('Happy but nervous about the responsibility', 'nervous'),
      createAnswerOption('Shocked, need time to process', 'shocked'),
      createAnswerOption('This wasn\'t planned, discuss options', 'discuss'),
    ];
  }

  processAnswer(player: Player, selectedOption: number): EventResult {
    const partner = (player.r ?? []).find(
      (p) =>
        p.status === 'alive' &&
        ((p.relationships ?? []).includes('spouse') || (p.relationships ?? []).includes('partner'))
    );
    const partnerName = partner?.firstname ?? 'your partner';

    if (selectedOption === 3) {
      player.c.stress = modifyStat(player.c.stress, 15);
      return {
        type: 'messageEvent',
        message: `You and ${partnerName} had a long, honest conversation about the pregnancy. It wasn't easy, but you're working through it together.`,
      };
    }

    player.c.pregnant = true;
    // Term the pregnancy ~9 months (252 days) out. checkPregnancyTerm (run daily
    // on both loops) creates the real child and credits child_born AT birth.
    player.c.pregnancyDueDay = (player.c.ageDays ?? 0) + 252;

    const happinessBoost = selectedOption === 0 ? 15 : selectedOption === 1 ? 8 : 3;
    player.c.happiness = modifyStat(player.c.happiness, happinessBoost);
    player.c.stress = modifyStat(player.c.stress, selectedOption === 0 ? -5 : 10);
    if (partner) {
      partner.affinity = modifyStat(partner.affinity, 10, -100, 100);
    }

    // Stage 2: First trimester (4 weeks)
    scheduleFollowUp(
      player,
      `pregnancyArc_stage2`,
      28,
      10,
      `First trimester is rough. Morning sickness, fatigue, and mood swings. ${partnerName} is being supportive but you can tell they're nervous too. The first ultrasound is coming up.`
    );

    // Stage 3: Midpoint (12 weeks)
    scheduleFollowUp(
      player,
      `pregnancyArc_stage3`,
      84,
      14,
      `You're past the first trimester and feeling better. The baby is growing and you can feel movement now. ${partnerName} teared up at the last ultrasound. You've started setting up the nursery.`
    );

    // Stage 4: Third trimester (24 weeks)
    scheduleFollowUp(
      player,
      `pregnancyArc_stage4`,
      168,
      10,
      `The third trimester is here. You're huge, uncomfortable, and excited. ${partnerName} assembled the crib (it only took three tries). The baby shower was wonderful. Almost there.`
    );

    // Stage 5: Birth (36 weeks)
    scheduleFollowUp(
      player,
      `pregnancyArc_stage5`,
      252,
      6,
      `It's time! After hours of labor, your baby is born. The tiny cry fills the room and everything changes. ${partnerName} is crying. You're crying. The nurses are smiling. Your family is complete in a new way. Welcome to parenthood.`
    );
    // Child creation + child_born credit happen at BIRTH via checkPregnancyTerm
    // (driven daily on both loops off player.c.pregnancyDueDay), not here at
    // conception — so the milestone fires ~9 months later when the baby arrives.

    const reactions = [
      `You and ${partnerName} are over the moon! You immediately started looking at baby names and nursery ideas. This is the beginning of an incredible journey.`,
      `You're happy but the reality is hitting you. A baby changes everything. ${partnerName} squeezed your hand and said "We'll figure it out together."`,
      `The shock hasn't worn off yet. A baby. You and ${partnerName} sat in stunned silence for a while before a smile slowly crept across both your faces.`,
    ];

    return {
      type: 'messageEvent',
      message: reactions[selectedOption] ?? reactions[0],
    };
  }
}

// =============================================================================
// Exports
// =============================================================================

export const diagnosisRevealInstance = new DiagnosisReveal();
export const medicalEmergencyInstance = new MedicalEmergency();
export const therapyArcInstance = new TherapyArc();
export const pregnancyArcInstance = new PregnancyArc();

export const medicalArcClassEvents = [
  diagnosisRevealInstance,
  medicalEmergencyInstance,
  therapyArcInstance,
  pregnancyArcInstance,
];
