/**
 * School Year Transition Events
 * School progression and grade transitions
 * Ported from Python events/school_year/transitions.py
 *
 * Events:
 * - school: School year transitions and grade progression
 * - graduate5th: 5th grade graduation
 * - graduate8th: 8th grade graduation
 * - graduate12th: 12th grade graduation (high school)
 * - college: College year transitions
 * - collegeParty: College party
 * - collegeGreekLife: Joining Greek life
 * - collegeMissHome: Missing home in college
 * - collegeMinor: Choosing a college minor
 * - driversLessons: Driver's education
 * - driversTest: Taking driver's test
 * - positiveInteraction: Positive social interaction
 * - lowEnergyEvents: Low energy coping mechanisms
 * - extendedFamily: Extended family relationship events
 * - funeral: Attending a funeral
 */

import { Player } from '../../models/index.js';
import {
  createMessageEvent,
  createQuestionEvent,
  createAnswerOption,
  EventResult,
} from '../base.js';

// School name arrays (would normally be loaded from config)
const elementarySchools = [
  'Oak Elementary',
  'Pine Elementary',
  'Maple Elementary',
  'Cedar Elementary',
];
const highSchools = [
  'Central High',
  'North High',
  'South High',
  'East High',
  'West High',
];

/**
 * School year transitions and grade progression
 * Triggers on September 1st for school start, June 1st for school end
 */
export function school(player: Player): EventResult {
  const fname = 'school';
  const c = player.c;
  let check = false;
  let message = '';
  let education = c.education ?? 'None';

  // Start new school year on September 1st
  if (
    (c.occupation === 'student' &&
      !c.education?.includes('college') &&
      player.date === '09-01') ||
    (c.occupation === 'preschool' && c.ageYears >= 4)
  ) {
    check = true;
    education = c.education ?? 'None';

    if ((c.education === 'None' || c.education === '') && c.ageYears >= 5) {
      message = 'You have started kindergarten';
      education = 'kindergarten';
    } else if (c.education === 'kindergarten') {
      const school = elementarySchools[Math.floor(Math.random() * elementarySchools.length)];
      message = 'You have started 1st grade';
      education = '1st';
    } else if (c.education === '1st') {
      message = 'You have started 2nd grade';
      education = '2nd';
    } else if (c.education === '2nd') {
      message = 'You have started 3rd grade';
      education = '3rd';
    } else if (c.education === '3rd') {
      message = 'You have started 4th grade';
      education = '4th';
    } else if (c.education === '4th') {
      message = 'You have started 5th grade';
      education = '5th';
    } else if (c.education === '5th') {
      message = 'You have started 6th grade';
      education = '6th';
    } else if (c.education === '6th') {
      message = 'You have started 7th grade';
      education = '7th';
    } else if (c.education === '7th') {
      message = 'You have started 8th grade';
      education = '8th';
    } else if (c.education === '8th') {
      message = 'You have started highschool';
      education = '9th';
    } else if (c.education === '9th') {
      message = 'You have started 10th grade';
      education = '10th';
    } else if (c.education === '10th') {
      message = 'You have started 11th grade';
      education = '11th';
    } else if (c.education === '11th') {
      message = 'You have started 12th grade';
      education = '12th';
    }

    c.occupation = 'student';
    c.education = education;
  }

  // End school year on June 1st
  if (
    c.occupation === 'student' &&
    !c.education?.includes('college') &&
    player.date === '06-01'
  ) {
    check = true;
    if (c.education !== 'highschool' && c.education !== 'college') {
      message = 'You have finished ' + c.education + ' grade';
      if (c.education === '8th') {
        // Trigger 8th grade graduation
        graduate8th(player);
      }
      if (c.education === '5th') {
        // Trigger 5th grade graduation
        graduate5th(player);
      }
    } else {
      message = 'You have finished school for the year';
      player.dayEvent = 'yearlyGraduation';
    }
  }

  if (check && message) {
    player.updateClient = true;
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * 5th grade graduation
 * Triggers on June 1st for 5th graders
 */
export function graduate5th(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message'
): EventResult {
  const fname = 'graduate5th';
  const c = player.c;

  const check =
    c.occupation === 'student' && c.education === '5th' && player.date === '06-01';

  if (!check) {
    return null;
  }

  const message =
    'You have finished 5th grade! Take this opportunity to reflect on your life so far, and say goodbye to your elementary school friends.';
  const answerOptions = [createAnswerOption('Onward to middle school!')];

  if (type !== 'answer') {
    player.updateClient = true;
    return createQuestionEvent(fname, message, player, check, { answerOptions });
  }

  return null;
}

/**
 * 8th grade graduation
 * Triggers on June 1st for 8th graders
 */
export function graduate8th(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message'
): EventResult {
  const fname = 'graduate8th';
  const c = player.c;

  const check =
    c.occupation === 'student' && c.education === '8th' && player.date === '06-01';

  if (!check) {
    return null;
  }

  const message =
    'You have finished 8th grade! Take this opportunity to reflect on your life so far, and say goodbye to your middle school friends.';
  const answerOptions = [createAnswerOption('Onward to highschool!')];

  if (type !== 'answer') {
    player.updateClient = true;
    return createQuestionEvent(fname, message, player, check, { answerOptions });
  }

  return null;
}

/**
 * 12th grade graduation (high school)
 * Triggers on June 1st for 12th graders
 */
export function graduate12th(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message'
): EventResult {
  const fname = 'graduate12th';
  const c = player.c;

  const check =
    c.occupation === 'student' && c.education === '12th' && player.date === '06-01';

  if (!check) {
    return null;
  }

  const message =
    'You have finished 12th grade! Take this opportunity to reflect on your life so far, and say goodbye to your high school friends.';
  const answerOptions = [createAnswerOption('Onward to college!')];

  if (type !== 'answer') {
    player.updateClient = true;
    return createQuestionEvent(fname, message, player, check, { answerOptions });
  }

  return null;
}

/**
 * College year transitions
 * Handles college progression and graduation
 */
export function college(player: Player): EventResult {
  const fname = 'college';
  const c = player.c;
  let check = false;
  let message = '';
  let education = c.education ?? '';

  // Start new college year on September 1st
  if (
    c.occupation === 'student' &&
    c.college &&
    (c.education === '12th' || c.education?.includes('college')) &&
    player.date === '09-01'
  ) {
    check = true;

    if (c.education === '12th') {
      message = `You have started college at ${c.college}! You are a freshman.`;
      c.job = undefined;
      education = 'college yr 1';
    } else if (c.education === 'college yr 1') {
      message = 'You have started your sophomore year of college.';
      education = 'college yr 2';
    } else if (c.education === 'college yr 2') {
      message = 'You have started your junior year of college.';
      education = 'college yr 3';
    } else if (c.education === 'college yr 3') {
      message = 'You have started your senior year of college.';
      education = 'college yr 4';
    }

    c.occupation = 'student';
    c.education = education;
  }

  // College graduation on June 1st
  if (
    c.occupation === 'student' &&
    c.education === 'college yr 4' &&
    player.date === '06-01'
  ) {
    check = true;
    message = "You have graduated college! Congratulations, it's time to start your career.";
    c.occupation = 'work';
  }

  if (check && message) {
    player.updateClient = true;
    return createMessageEvent(fname, message, player, check);
  }

  return null;
}

/**
 * College party event
 * Triggers on weekends for college freshmen
 */
export function collegeParty(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'collegeParty';
  const c = player.c;

  const check =
    player.weekend && c.education === 'college yr 1' && Math.random() < 0.1;

  if (check && type !== 'answer') {
    const message = "Hey! There's a party tonight, wanna go?";
    const answerOptions = [
      createAnswerOption("I'll be there!"),
      createAnswerOption('No thanks, I should study.'),
    ];
    return createQuestionEvent(fname, message, player, true, { answerOptions });
  }

  if (type === 'answer') {
    const choice = response?.option ?? '';
    if (choice === "I'll be there!") {
      c.happiness = Math.min(100, (c.happiness ?? 50) + 5);
      c.social = Math.min(100, (c.social ?? 50) + 5);
    } else if (choice === 'No thanks, I should study.') {
      c.social = (c.social ?? 50) - 5;
    }
  }

  return null;
}

/**
 * Joining Greek life
 * Triggers on weekends for college freshmen
 */
export function collegeGreekLife(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'collegeGreekLife';
  const c = player.c;

  const check =
    player.weekend && c.education === 'college yr 1' && Math.random() < 0.1;

  if (check && type !== 'answer') {
    const message = 'Would you like to join a fraternity/sorority?';
    const answerOptions = [
      createAnswerOption('Yes!'),
      createAnswerOption('No thanks, I should study.'),
    ];
    return createQuestionEvent(fname, message, player, true, { answerOptions });
  }

  if (type === 'answer') {
    const choice = response?.option ?? '';
    if (choice === 'Yes!') {
      c.happiness = Math.min(100, (c.happiness ?? 50) + 5);
      c.social = Math.min(100, (c.social ?? 50) + 15);
      (c as unknown as Record<string, boolean>).greekLife = true;
    } else if (choice === 'No thanks, I should study.') {
      c.social = (c.social ?? 50) - 5;
    }
  }

  return null;
}

/**
 * Missing home in college
 * Triggers for college freshmen with low social
 */
export function collegeMissHome(player: Player): EventResult {
  const fname = 'collegeMissHome';
  const c = player.c;

  const check =
    c.education === 'college yr 1' && (c.social ?? 50) < 50 && Math.random() < 0.01;

  if (!check) {
    return null;
  }

  const message = 'You miss home, and your family misses you. You should call them.';
  player.events.add(fname);
  return createMessageEvent(fname, message, player, check);
}

/**
 * Choosing a college minor
 * Triggers for college freshmen who don't have a minor
 */
export function collegeMinor(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'collegeMinor';
  const c = player.c;

  const hasMinor = (c as unknown as Record<string, string | undefined>).minor !== undefined;
  const check =
    c.education === 'college yr 1' && Math.random() < 0.1 && !hasMinor;

  if (check && type !== 'answer') {
    const message = 'Would you like to choose a minor?';
    const answerOptions = [
      createAnswerOption('Art'),
      createAnswerOption('Biology'),
      createAnswerOption('Business'),
      createAnswerOption('Chemistry'),
      createAnswerOption('Computer Science'),
      createAnswerOption('Economics'),
      createAnswerOption('English'),
      createAnswerOption('History'),
      createAnswerOption('Mathematics'),
      createAnswerOption('Music'),
      createAnswerOption('Philosophy'),
      createAnswerOption('Physics'),
      createAnswerOption('Political Science'),
      createAnswerOption('Psychology'),
      createAnswerOption('Sociology'),
      createAnswerOption('Theater'),
    ];
    return createQuestionEvent(fname, message, player, true, { answerOptions });
  }

  if (type === 'answer') {
    (c as unknown as Record<string, string>).minor = response?.option ?? '';
    c.energy = Math.max(0, (c.energy ?? 100) - 5);
    player.updateClient = true;
  }

  return null;
}

/**
 * Driver's education sign-up
 * Triggers for ages 15-22
 */
export function driversLessons(player: Player): EventResult {
  const fname = 'driversLessons';
  const c = player.c;

  const check =
    c.ageYears >= 15 &&
    c.ageYears < 22 &&
    !player.events.has(fname) &&
    Math.random() < 0.01;

  if (!check) {
    return null;
  }

  const message = 'Your parents have signed you up for drivers lessons!';
  player.events.add(fname);

  // Add drivers education schedule
  c.schedules.push({
    id: `drivers-ed-${c.id}`,
    title: 'Drivers Education',
    type: 'education',
    duration: Math.floor(Math.random() * 6) + 15, // 15-20 sessions
    location: `school-${c.id}`,
  });

  return createMessageEvent(fname, message, player, check);
}

/**
 * Helper for ordinal suffixes
 */
function ordinalSuffix(num: number): string {
  const j = num % 10;
  const k = num % 100;
  if (j === 1 && k !== 11) return num + 'st';
  if (j === 2 && k !== 12) return num + 'nd';
  if (j === 3 && k !== 13) return num + 'rd';
  return num + 'th';
}

/**
 * Check if schedule is complete
 */
function scheduleComplete(c: { schedules: Array<{ title?: string; executions?: number; duration?: number }> }, title: string): boolean {
  const schedule = c.schedules.find((s) => s.title === title);
  if (!schedule) return false;
  return (schedule.executions ?? 0) >= (schedule.duration ?? 0);
}

/**
 * Taking driver's test
 * Triggers after completing drivers education
 */
export function driversTest(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const fname = 'driversTest';
  const c = player.c;

  const canDrive = (c as unknown as Record<string, boolean>).canDrive ?? false;
  const check =
    !player.askedQuestions.has(fname) &&
    !canDrive &&
    scheduleComplete(c, 'Drivers Education') &&
    Math.random() < 0.1;

  if (type !== 'answer' && check) {
    // Track attempt number
    let attempts = (c as unknown as Record<string, number>).driversTestAttempts ?? 0;
    attempts += 1;
    (c as unknown as Record<string, number>).driversTestAttempts = attempts;

    const message = `Today is your ${ordinalSuffix(attempts)} attempt at the driver's test! How are you feeling?`;
    const answerOptions = [
      createAnswerOption('Nervous'),
      createAnswerOption('Confident'),
    ];
    return createQuestionEvent(fname, message, player, check, { answerOptions });
  }

  if (type === 'answer') {
    const attempts = (c as unknown as Record<string, number>).driversTestAttempts ?? 1;
    // Calculate pass rate: 50% base + 10% per previous attempt (maxes at 90%)
    const passRate = Math.min(0.9, 0.5 + (attempts - 1) * 0.1);

    if (Math.random() < passRate) {
      player.messageQueue.push('You passed your drivers test!');
      (c as unknown as Record<string, boolean>).canDrive = true;
      player.askedQuestions.add(fname); // Only add when passing
    } else {
      player.messageQueue.push('You failed your drivers test!');
      // Don't add to askedQuestions - allow retry
    }

    return createMessageEvent(fname, player.messageQueue[player.messageQueue.length - 1], player, true);
  }

  return null;
}

/**
 * Positive social interaction
 * Triggers when player has friends with high affinity
 */
export function positiveInteraction(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message'
): EventResult {
  const fname = 'positiveInteraction';

  const highAffinityPeople = player.r.filter((p) => (p.affinity ?? 0) > 50);
  const check = highAffinityPeople.length > 0;

  if (check && type !== 'answer' && Math.random() < 0.001) {
    const friendsToPickFrom = player.r.filter((p) => (p.affinity ?? 0) > 1);
    if (friendsToPickFrom.length === 0) return null;

    const friend = friendsToPickFrom[Math.floor(Math.random() * friendsToPickFrom.length)];
    const message = `${friend.firstname} is starting to really like you and wants to hang out!`;
    return createQuestionEvent(fname, message, player, true);
  }

  if (type === 'answer') {
    player.controller = 'active';
  }

  return null;
}

/**
 * Low energy coping mechanisms
 * Triggers when player has very low energy
 */
export function lowEnergyEvents(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string; data?: string }
): EventResult {
  const fname = 'lowEnergyEvents';
  const c = player.c;

  if ((c.energy ?? 100) < 20 && type !== 'answer' && (c.energy ?? 100) >= Math.random() * 1000) {
    const messageOptions: Record<string, string> = {
      rudeness:
        "You notice a sharpness creeping into your tone. Fatigue is making you irritable and you're pushing people away.",
      overeating:
        "Your tiredness is making you reach for comfort foods. You're overeating and it's not making you feel any better.",
      isolation:
        "You're withdrawing from friends and family, opting to be alone. Isolation seems easier when you're this worn out.",
    };

    if (c.occupation === 'work') {
      messageOptions['skip_work'] =
        'You wake up feeling exhausted and decide to skip work today.';
    }
    if (c.occupation === 'student') {
      messageOptions['skip_school'] =
        'You wake up feeling exhausted and decide to skip school today.';
    }
    if (c.ageYears > 21) {
      messageOptions['alcohol'] =
        'Exhaustion sets in and you find yourself reaching for a drink more often than usual.';
    }

    const mechanisms = Object.keys(messageOptions);
    const copingMechanism = mechanisms[Math.floor(Math.random() * mechanisms.length)];
    const message = messageOptions[copingMechanism];

    const answerDict: Record<string, string> = {
      rudeness: "I've run out of patience.",
      overeating: 'I just need some comfort food.',
      isolation: 'I just need some alone time.',
      skip_work: 'I need a personal day.',
      skip_school: "I can't face school today.",
      alcohol: 'Just one more drink to take the edge off.',
    };

    const answerOptions = [createAnswerOption(answerDict[copingMechanism], copingMechanism)];
    return createQuestionEvent(fname, message, player, true, { answerOptions });
  }

  return null;
}

/**
 * Extended family relationship events
 * Triggers for extended family members with low affinity
 */
export function extendedFamily(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string; data?: string }
): EventResult {
  const fname = 'extendedFamily';
  const c = player.c;

  if (type !== 'answer') {
    const found = player.r.filter(
      (r) => (r.familyLevel ?? 0) === 2 && (r.affinity ?? 0) < -50
    );

    if (found.length > 0 && Math.random() < 0.2) {
      const relative = found[Math.floor(Math.random() * found.length)];
      const message = `${relative.firstname} is upset you've been ignoring them, you should have a chat with them!`;
      const answerOptions = [
        createAnswerOption("I'll set some time aside to talk to them", relative.id),
        createAnswerOption("I'm ignoring them for a reason!", relative.id),
      ];
      return createQuestionEvent(fname, message, player, true, { answerOptions });
    }
  }

  if (type === 'answer' && response) {
    const personId = response.data;
    const person = player.r.find((p) => p.id === personId);

    if (person) {
      if (response.option === "I'll set some time aside to talk to them") {
        person.affinity = Math.min(100, (person.affinity ?? 0) + 20);
        c.energy = Math.max(0, (c.energy ?? 100) - 20);
      } else {
        person.affinity = (person.affinity ?? 0) - 10;
      }
    }
  }

  return null;
}

/**
 * Attending a funeral
 * Triggers when a known person has died
 */
export function funeral(
  player: Player,
  type: 'message' | 'question' | 'answer' = 'message',
  response?: { option?: string }
): EventResult {
  const c = player.c;

  for (const person of player.r) {
    const fname = `funeral---${person.firstname}${person.lastname}`;

    if (type !== 'answer' && person.status !== 'alive' && !player.events.has(fname)) {
      const message = `${person.firstname} ${person.lastname} has passed away, would you like to attend their funeral?`;
      const answerOptions = [
        createAnswerOption('Yes'),
        createAnswerOption('No'),
      ];
      return createQuestionEvent(fname, message, player, true, { answerOptions });
    }

    if (
      type === 'answer' &&
      response?.option &&
      player.events.has(fname) === false
    ) {
      player.events.add(fname);

      if (response.option === 'Yes') {
        c.happiness = (c.happiness ?? 50) - 15;
        c.social = (c.social ?? 50) - 15;

        // Add funeral schedule
        c.schedules.push({
          id: `funeral-${person.id}`,
          title: 'Funeral',
          type: 'event',
          duration: 1,
          location: `cemetery-${c.id}`,
        });
      } else {
        player.messageQueue.push('You did not attend the funeral.');
      }

      return createMessageEvent(fname, player.messageQueue[player.messageQueue.length - 1] ?? 'Funeral scheduled.', player, true);
    }
  }

  return null;
}

/**
 * All transition event functions
 */
export const transitionEvents = {
  school,
  graduate5th,
  graduate8th,
  graduate12th,
  college,
  collegeParty,
  collegeGreekLife,
  collegeMissHome,
  collegeMinor,
  driversLessons,
  driversTest,
  positiveInteraction,
  lowEnergyEvents,
  extendedFamily,
  funeral,
};
