/**
 * Family Activity Events
 * Family bonding and interaction activities (ages 5-100)
 *
 * These events focus on relationship building with family members.
 * They check for family member existence, modify affinity,
 * and create appropriate schedules or one-time events.
 *
 * Events:
 * - familyGameNight: Weekly/monthly family game night tradition (ages 8+)
 * - familyVacation: Planning a family vacation (ages 8-65)
 * - teachSiblingSkill: Teaching a younger sibling (ages 10-30, requires younger siblings)
 * - helpParentProject: Helping parent with home projects (ages 10-45, requires parents)
 * - familyPhoto: Professional family photo session (ages 5+)
 */

import { Player } from '../../models/Player.js';
import { Person } from '../../models/Person.js';
import {
  createQuestionEvent,
  createAnswerOption,
  checkProbability,
  modifyStat,
  type EventResult,
  type AnswerOption,
} from '../base.js';

// ============================================================================
// Helper Functions
// ============================================================================

/**
 * Extended person type that includes optional title property
 * Used for family relationship lookups where title may be set
 */
type ExtendedPerson = Person & { title?: string };

/**
 * Get all family members from player relationships
 * Uses player.r which contains full Person objects with relationship data
 */
export function getAllFamily(player: Player): Person[] {
  return (player.r ?? []).filter((person: Person) => {
    const relationships = person.relationships ?? [];
    const extPerson = person as ExtendedPerson;
    const title = extPerson.title?.toLowerCase() ?? '';
    return (
      relationships.includes('mother') ||
      relationships.includes('father') ||
      relationships.includes('sibling') ||
      relationships.includes('brother') ||
      relationships.includes('sister') ||
      relationships.includes('spouse') ||
      relationships.includes('child') ||
      title === 'mother' ||
      title === 'father' ||
      title.includes('sibling') ||
      title.includes('brother') ||
      title.includes('sister')
    );
  });
}

/**
 * Get parent from player relationships
 */
export function getParent(player: Player): Person | null {
  const mother = (player.r ?? []).find((p: Person) => {
    const extP = p as ExtendedPerson;
    return (
      (p.relationships ?? []).includes('mother') ||
      extP.title?.toLowerCase() === 'mother'
    );
  });
  const father = (player.r ?? []).find((p: Person) => {
    const extP = p as ExtendedPerson;
    return (
      (p.relationships ?? []).includes('father') ||
      extP.title?.toLowerCase() === 'father'
    );
  });
  return mother ?? father ?? null;
}

/**
 * Get specific relationship from player relationships
 */
export function getRelationship(
  player: Player,
  relationshipType: string
): Person | null {
  return (
    (player.r ?? []).find((p: Person) => {
      const relationships = p.relationships ?? [];
      const extP = p as ExtendedPerson;
      const title = extP.title?.toLowerCase() ?? '';
      return (
        relationships.includes(relationshipType) ||
        title === relationshipType.toLowerCase()
      );
    }) ?? null
  );
}

/**
 * Get younger siblings from player relationships
 */
export function getYoungerSiblings(player: Player): Person[] {
  return (player.r ?? []).filter((person: Person) => {
    const relationships = person.relationships ?? [];
    const extPerson = person as ExtendedPerson;
    const title = extPerson.title?.toLowerCase() ?? '';
    const isSibling =
      relationships.includes('sibling') ||
      relationships.includes('brother') ||
      relationships.includes('sister') ||
      title.includes('sibling') ||
      title.includes('brother') ||
      title.includes('sister');
    return isSibling && person.ageYears < player.c.ageYears;
  });
}

/**
 * Get person by ID from player relationships
 */
export function getPerson(player: Player, id: string | null): Person | null {
  if (!id) return null;
  return (player.r ?? []).find((p) => p.id === id) ?? null;
}

// ============================================================================
// Event Functions
// ============================================================================

/**
 * Family Game Night - Start a weekly family game night tradition
 * Ages 8-100, requires family members
 */
export function familyGameNight(
  player: Player,
  _type: 'message' | 'question' = 'message'
): EventResult {
  const fname = 'familyGameNight';
  const family = getAllFamily(player);

  const check =
    !player.askedQuestions.has(fname) &&
    player.c.ageYears >= 8 &&
    player.c.ageYears <= 100 &&
    family.length > 0 &&
    checkProbability(500);

  if (check) {
    player.askedQuestions.add(fname);
  }

  return createQuestionEvent(
    fname,
    'Your family suggests starting a regular game night tradition. How often?',
    player,
    check,
    {
      answerOptions: [
        createAnswerOption('Yes, every week!'),
        createAnswerOption('Once a month'),
        createAnswerOption('Too busy'),
      ],
    }
  );
}

/**
 * Process family game night answer
 */
export function familyGameNightAnswer(
  player: Player,
  response: { option: string }
): void {
  const family = getAllFamily(player);

  if (response.option === 'Yes, every week!') {
    player.c.happiness = modifyStat(player.c.happiness, 10);
    player.c.social = modifyStat(player.c.social, 5);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 5, -100, 100);
    }

    player.messageQueue.push(
      "You've started a weekly family game night tradition! Every Friday evening, the family gathers for board games and fun."
    );
  } else if (response.option === 'Once a month') {
    player.c.happiness = modifyStat(player.c.happiness, 8);
    player.c.social = modifyStat(player.c.social, 3);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 3, -100, 100);
    }

    player.messageQueue.push(
      "You've decided to have family game night once a month. It's a nice tradition!"
    );
  } else {
    player.c.happiness = modifyStat(player.c.happiness, -5);

    // Decrease affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, -3, -100, 100);
    }

    player.messageQueue.push(
      "You're too busy for family game night. Your family seems disappointed."
    );
  }
}

/**
 * Family Vacation - Plan a family vacation this year
 * Ages 8-65, requires family members and at least $500
 */
export function familyVacation(
  player: Player,
  _type: 'message' | 'question' = 'message'
): EventResult {
  const fname = 'familyVacation';
  const family = getAllFamily(player);

  const check =
    !player.askedQuestions.has(fname) &&
    player.c.ageYears >= 8 &&
    player.c.ageYears <= 65 &&
    family.length > 0 &&
    (player.c.money ?? 0) >= 500 &&
    checkProbability(800);

  if (check) {
    player.askedQuestions.add(fname);
  }

  return createQuestionEvent(
    fname,
    'Your family wants to plan a vacation together. What sounds good?',
    player,
    check,
    {
      answerOptions: [
        createAnswerOption('Yes, big trip!', '', 0, 0, 2000),
        createAnswerOption('Weekend getaway', '', 0, 0, 500),
        createAnswerOption('Staycation at home'),
        createAnswerOption("Can't afford it"),
      ],
    }
  );
}

/**
 * Process family vacation answer
 */
export function familyVacationAnswer(
  player: Player,
  response: { option: string }
): void {
  const family = getAllFamily(player);

  if (response.option === 'Yes, big trip!') {
    player.c.money = (player.c.money ?? 0) - 2000;
    player.c.happiness = modifyStat(player.c.happiness, 20);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 10, -100, 100);
    }

    player.messageQueue.push(
      "You've planned an amazing family vacation! Everyone is excited about the trip. You'll leave in a few months."
    );
  } else if (response.option === 'Weekend getaway') {
    player.c.money = (player.c.money ?? 0) - 500;
    player.c.happiness = modifyStat(player.c.happiness, 12);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 8, -100, 100);
    }

    player.messageQueue.push(
      "A weekend getaway with the family sounds perfect! You've booked it for a few weeks from now."
    );
  } else if (response.option === 'Staycation at home') {
    player.c.happiness = modifyStat(player.c.happiness, 8);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 5, -100, 100);
    }

    player.messageQueue.push(
      "You've planned a staycation at home. It'll be relaxing and the family will enjoy quality time together."
    );
  } else {
    player.c.happiness = modifyStat(player.c.happiness, -5);
    player.messageQueue.push(
      "You can't afford a vacation right now. Maybe next year."
    );
  }
}

/**
 * Teach Sibling Skill - Your younger sibling wants you to teach them something
 * Ages 10-30, requires younger siblings and energy >= 10
 */
export function teachSiblingSkill(
  player: Player,
  _type: 'message' | 'question' = 'message'
): EventResult {
  const fname = 'teachSiblingSkill';
  const youngerSiblings = getYoungerSiblings(player);

  const check =
    !player.askedQuestions.has(fname) &&
    player.c.ageYears >= 10 &&
    player.c.ageYears <= 30 &&
    youngerSiblings.length > 0 &&
    player.c.energy >= 10 &&
    checkProbability(600);

  if (!check) {
    return null;
  }

  // Pick a random younger sibling
  const sibling =
    youngerSiblings[Math.floor(Math.random() * youngerSiblings.length)];

  // Store sibling ID in player for retrieval in answer phase
  (player as unknown as { _temp_sibling_id: string })._temp_sibling_id =
    sibling.id;

  player.askedQuestions.add(fname);

  return createQuestionEvent(
    fname,
    `Your younger sibling ${sibling.firstname} wants you to teach them something. Help?`,
    player,
    true,
    {
      answerOptions: [
        createAnswerOption('Yes, spend time teaching!', '', 10, 0, 0),
        createAnswerOption('Quick lesson only'),
        createAnswerOption('Too busy'),
      ],
      characters: [sibling],
    }
  );
}

/**
 * Process teach sibling skill answer
 */
export function teachSiblingSkillAnswer(
  player: Player,
  response: { option: string }
): void {
  const youngerSiblings = getYoungerSiblings(player);

  // Get the specific sibling from the question phase
  const tempSiblingId = (player as unknown as { _temp_sibling_id?: string })
    ._temp_sibling_id;
  let sibling = getPerson(player, tempSiblingId ?? null);

  // Fallback to random sibling if ID not found
  if (!sibling && youngerSiblings.length > 0) {
    sibling = youngerSiblings[Math.floor(Math.random() * youngerSiblings.length)];
  }

  if (sibling) {
    if (response.option === 'Yes, spend time teaching!') {
      player.c.energy = modifyStat(player.c.energy, -10);
      player.c.happiness = modifyStat(player.c.happiness, 10);
      player.c.social = modifyStat(player.c.social, 5);
      sibling.affinity = modifyStat(sibling.affinity, 8, -100, 100);
      player.messageQueue.push(
        `You spent quality time teaching ${sibling.firstname}. They really appreciated it and learned a lot!`
      );
    } else if (response.option === 'Quick lesson only') {
      player.c.happiness = modifyStat(player.c.happiness, 5);
      player.c.social = modifyStat(player.c.social, 3);
      sibling.affinity = modifyStat(sibling.affinity, 5, -100, 100);
      player.messageQueue.push(
        `You gave ${sibling.firstname} a quick lesson. They learned something new!`
      );
    } else {
      player.c.happiness = modifyStat(player.c.happiness, -3);
      sibling.affinity = modifyStat(sibling.affinity, -5, -100, 100);
      player.messageQueue.push(
        `${sibling.firstname} seems disappointed that you're too busy to help them.`
      );
    }
  }

  // Clean up temp variable
  delete (player as unknown as { _temp_sibling_id?: string })._temp_sibling_id;
}

/**
 * Help Parent Project - Your parent needs help with a home project
 * Ages 10-45, requires at least one parent and energy >= 10
 */
export function helpParentProject(
  player: Player,
  _type: 'message' | 'question' = 'message'
): EventResult {
  const fname = 'helpParentProject';
  const parent = getRelationship(player, 'mother') ?? getRelationship(player, 'father');

  const check =
    !player.askedQuestions.has(fname) &&
    player.c.ageYears >= 10 &&
    player.c.ageYears <= 45 &&
    parent !== null &&
    player.c.energy >= 10 &&
    checkProbability(600);

  if (!check || !parent) {
    return null;
  }

  // Store parent ID for retrieval in answer phase
  (player as unknown as { _temp_parent_id: string })._temp_parent_id = parent.id;

  player.askedQuestions.add(fname);

  // Determine parent title
  const relationships = parent.relationships ?? [];
  const extParent = parent as ExtendedPerson;
  const title = extParent.title?.toLowerCase() ?? '';
  let parentTitle = 'parent';
  if (relationships.includes('mother') || title === 'mother') {
    parentTitle = 'mother';
  } else if (relationships.includes('father') || title === 'father') {
    parentTitle = 'father';
  }

  // Randomize project types for variety
  const projects = [
    'gardening',
    'painting the house',
    'fixing the fence',
    'organizing the garage',
    'remodeling the kitchen',
  ];
  const project = projects[Math.floor(Math.random() * projects.length)];

  return createQuestionEvent(
    fname,
    `Your ${parentTitle} needs help with ${project}. Want to assist?`,
    player,
    true,
    {
      answerOptions: [
        createAnswerOption('Yes, help all day!', '', 20, 0, 0),
        createAnswerOption('Help for a bit', '', 10, 0, 0),
        createAnswerOption('Too busy'),
      ],
      characters: [parent],
    }
  );
}

/**
 * Process help parent project answer
 */
export function helpParentProjectAnswer(
  player: Player,
  response: { option: string }
): void {
  // Get the specific parent from the question phase
  const tempParentId = (player as unknown as { _temp_parent_id?: string })
    ._temp_parent_id;
  let parent = getPerson(player, tempParentId ?? null);

  // Fallback to finding a parent if ID not found
  if (!parent) {
    parent =
      getRelationship(player, 'mother') ?? getRelationship(player, 'father');
  }

  if (parent) {
    // Re-determine parent title
    const relationships = parent.relationships ?? [];
    const extParent = parent as ExtendedPerson;
    const title = extParent.title?.toLowerCase() ?? '';
    let parentTitle = 'parent';
    if (relationships.includes('mother') || title === 'mother') {
      parentTitle = 'mother';
    } else if (relationships.includes('father') || title === 'father') {
      parentTitle = 'father';
    }

    if (response.option === 'Yes, help all day!') {
      player.c.energy = modifyStat(player.c.energy, -20);
      player.c.happiness = modifyStat(player.c.happiness, 10);
      player.c.social = modifyStat(player.c.social, 5);
      parent.affinity = modifyStat(parent.affinity, 8, -100, 100);
      player.messageQueue.push(
        `You helped your ${parentTitle} all day with the project. They're grateful and you feel accomplished!`
      );
    } else if (response.option === 'Help for a bit') {
      player.c.energy = modifyStat(player.c.energy, -10);
      player.c.happiness = modifyStat(player.c.happiness, 5);
      player.c.social = modifyStat(player.c.social, 3);
      parent.affinity = modifyStat(parent.affinity, 5, -100, 100);
      player.messageQueue.push(
        `You helped your ${parentTitle} for a while. They appreciate the assistance!`
      );
    } else {
      player.c.happiness = modifyStat(player.c.happiness, -5);
      parent.affinity = modifyStat(parent.affinity, -5, -100, 100);
      player.messageQueue.push(
        `Your ${parentTitle} is disappointed you're too busy to help.`
      );
    }
  }

  // Clean up temp variable
  delete (player as unknown as { _temp_parent_id?: string })._temp_parent_id;
}

/**
 * Family Photo - Family wants to take professional photos
 * Ages 5-100, requires family members and at least $50
 */
export function familyPhoto(
  player: Player,
  _type: 'message' | 'question' = 'message'
): EventResult {
  const fname = 'familyPhoto';
  const family = getAllFamily(player);

  const check =
    !player.askedQuestions.has(fname) &&
    player.c.ageYears >= 5 &&
    player.c.ageYears <= 100 &&
    family.length > 0 &&
    (player.c.money ?? 0) >= 50 &&
    checkProbability(700);

  if (check) {
    player.askedQuestions.add(fname);
  }

  return createQuestionEvent(
    fname,
    'Your family wants to schedule a professional photo session together. Are you in?',
    player,
    check,
    {
      answerOptions: [
        createAnswerOption('Yes, sounds fun!', '', 0, 0, 50),
        createAnswerOption('Okay, if I have to', '', 0, 0, 50),
        createAnswerOption('Refuse'),
      ],
    }
  );
}

/**
 * Process family photo answer
 */
export function familyPhotoAnswer(
  player: Player,
  response: { option: string }
): void {
  const family = getAllFamily(player);

  if (response.option === 'Yes, sounds fun!') {
    player.c.money = (player.c.money ?? 0) - 50;
    player.c.happiness = modifyStat(player.c.happiness, 5);
    player.c.social = modifyStat(player.c.social, 3);

    // Increase affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 5, -100, 100);
    }

    player.messageQueue.push(
      "You're excited for the family photo session! It's scheduled for a few weeks from now. Should be fun!"
    );
  } else if (response.option === 'Okay, if I have to') {
    player.c.money = (player.c.money ?? 0) - 50;
    player.c.happiness = modifyStat(player.c.happiness, 3);

    // Small increase in affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, 3, -100, 100);
    }

    player.messageQueue.push(
      "You agreed to participate in the family photos. It's scheduled for a few weeks from now."
    );
  } else {
    player.c.happiness = modifyStat(player.c.happiness, -5);

    // Decrease affinity with all family members
    for (const member of family) {
      member.affinity = modifyStat(member.affinity, -5, -100, 100);
    }

    player.messageQueue.push(
      'You refused to participate in family photos. Your family is really disappointed.'
    );
  }
}
