/**
 * Conversation Events for BaoLife
 * Ported from Python conversationEvents.py
 *
 * All conversation events that can be triggered by player interactions
 */

import { Player, Person } from '../../models/index.js';
import { ConversationObj, ConversationCheckResult } from './types.js';
import { getOpenAIResponse } from './ai_response.js';
import { randomChoice } from '../../utils/helpers.js';
import { getPerson } from '../../services/character/character_manager.js';

type ConversationResult = ConversationObj | ConversationCheckResult | false;

/**
 * Activity conversation - Ask what someone has been up to
 */
export async function activity(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'activity';
  const button = "What's up?";

  if (check) {
    const canTrigger = character.status === 'alive';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'What have you been up to lately?',
      'What kind of things have you been doing?',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  const responseText = response;
  conversation.addMessage(responseText, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Check in conversation - Simple greeting
 */
export async function checkIn(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'checkIn';
  const button = 'Check In';

  if (check) {
    const canTrigger = character.status === 'alive' && character.occupation === 'student';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = ['Hey! How are you doing?', "Hey, how's it going?", 'Hey, how are you?'];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Ask about day conversation
 */
export async function askAboutDay(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'askAboutDay';
  const button = 'Ask About Day';

  if (check) {
    const canTrigger = character.status === 'alive';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'Hey, how was your day?',
      'Hey, how has your day been?',
      'Hey, how are you feeling today?',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Flatter conversation - Compliment someone
 */
export async function flatter(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'flatter';
  const button = 'Flatter';

  if (check) {
    const canTrigger = character.status === 'alive';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'Hey, you look really nice today!',
      'Hey, I really like your outfit!',
      "You know, you're really smart!",
      'Your creativity really shines in your work!',
      'You have an incredible sense of humor.',
      'Your perspective always brings fresh insights.',
      'I admire your dedication and passion.',
      'You are really good at what you do.',
      'You always know how to lighten the mood.',
      'Your confidence is really inspiring.',
      'I appreciate your thoughtfulness and kindness.',
      'You have a talent for making people feel comfortable.',
      'Your positivity is infectious.',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Study session conversation
 */
export async function studySession(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'studySession';
  const button = 'Ask to study';

  if (check) {
    const canTrigger = character.status === 'alive' && character.occupation === 'student';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const firstname = person.firstname;
    const message = `Hey ${firstname}, I was wondering if you'd want to study for the upcoming test with me?`;
    conversation.addMessage(message, player.c.id, {
      date: player.date,
      time: player.time,
    });

    if (!person.relationships?.includes('classmate')) {
      conversation.addMessage("Hey, I'm not your classmate...", undefined, {
        date: player.date,
        time: player.time,
      });
      return conversation;
    }

    if ((person.familiarity ?? 0) > 50) {
      if ((person.affinity ?? 50) > 20) {
        conversation.addMessage("Sure, I'd love to! Where do you want to meet?", undefined, {
          date: player.date,
          time: player.time,
        });
        conversation.setAnswerOptions(['The library', 'The park', 'My place']);
      } else if ((person.affinity ?? 50) < -20) {
        conversation.addMessage("Umm, I don't think that's a good idea.", undefined, {
          date: player.date,
          time: player.time,
        });
      } else {
        conversation.addMessage("I'm sorry, but we don't really get along.", undefined, {
          date: player.date,
          time: player.time,
        });
      }
    } else {
      conversation.addMessage("I'm sorry, I don't really know you that well.", undefined, {
        date: player.date,
        time: player.time,
      });
    }
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  const answerOptions = conversation.getAnswerOptions() ?? [];
  const responseIndex = parseInt(response, 10);
  const responseText = answerOptions[responseIndex] ?? response;
  conversation.addMessage(responseText, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question === 1) {
    if (
      responseIndex === 0 ||
      responseIndex === 1 ||
      Math.floor(Math.random() * 10) > 5 ||
      (person.affinity ?? 50) > 60
    ) {
      conversation.addMessage("Great! I'll meet you there.", undefined, {
        date: player.date,
        time: player.time,
      });
      player.messageQueue = player.messageQueue ?? [];
      player.messageQueue.push(
        `You have a study session with ${person.firstname} at the ${responseText}.`
      );
      person.affinity = Math.min(100, (person.affinity ?? 50) + 10);
    } else {
      conversation.addMessage("Umm, I don't think I'm comfortable with that.", undefined, {
        date: player.date,
        time: player.time,
      });
      person.affinity = Math.max(0, (person.affinity ?? 50) - 10);
    }
  }
  return conversation;
}

/**
 * Chat conversation - Generic chat
 */
export async function chat(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'chat';
  const button = 'Chat';

  if (check) {
    const canTrigger = character.status === 'alive';
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  // Check if conversation exists
  const existingConversation = player.conversations.find((conv) => {
    const convChar = typeof conv.character === 'string' ? conv.character : conv.character?.id;
    return convChar === character.id;
  }) as ConversationObj | undefined;

  if (!existingConversation) {
    console.log('No existing conversation');
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const firstname = person.firstname.charAt(0).toUpperCase() + person.firstname.slice(1).toLowerCase();
    const messages = [
      `Hey ${firstname}, what keeps you busy in life?`,
      `Hey ${firstname}, tell me about yourself.`,
      `Hey ${firstname}, what do you like to do for fun?`,
    ];

    const message = response !== false ? response : randomChoice(messages);
    console.log('Message: ' + message);
    conversation.addMessage(message, player.c.id, {
      date: player.date,
      time: player.time,
    });
    return conversation;
  }

  console.log('Continuing existing conversation');
  await getOpenAIResponse(existingConversation, person, player);
  return existingConversation;
}

/**
 * Deep conversation - Meaningful life discussions
 */
export async function deepConversation(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'deepConversation';
  const button = "Let's talk about life";


  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 16;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      "I've been thinking a lot about life lately. Want to talk about it?",
      'Can we have a real conversation about something meaningful?',
      'What do you think the meaning of life is?',
      'I want to talk about something deeper than usual.',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Gossip session
 */
export async function gossipSession(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'gossipSession';
  const button = 'Did you hear about...';

  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 12;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'Did you hear what happened?',
      'I have some gossip to share...',
      "You'll never believe what I heard!",
      'So I heard something interesting today...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Venting session - Stress relief
 */
export async function ventingSession(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'ventingSession';
  const button = 'I need to vent';

  if (check) {
    const canTrigger =
      character.status === 'alive' &&
      player.c.ageYears >= 12 &&
      ((player.c.happiness ?? 50) < 50 || (player.c.stress ?? 0) > 50);
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    // Apply stress relief
    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 10);
    player.c.stress = Math.max(0, (player.c.stress ?? 0) - 15);

    const messages = [
      "I'm so stressed right now, can I just vent for a minute?",
      'I really need to get something off my chest...',
      "I'm having a rough time, can I talk to you about it?",
      'Everything is just overwhelming me right now...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Ask advice conversation
 */
export async function askAdvice(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'askAdvice';
  const button = 'Can I ask your advice?';

  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 10;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'I could really use your advice on something...',
      'Can I get your opinion on something?',
      "I have a problem and I'd like to hear your perspective.",
      'What would you do if you were in my situation?',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Reminisce conversation - For close relationships
 */
export async function reminisce(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'reminisce';
  const button = 'Remember when...';


  if (check) {
    const canTrigger =
      character.status === 'alive' &&
      player.c.ageYears >= 10 &&
      (character.familiarity ?? 0) > 60;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'Remember when we used to hang out all the time?',
      "I was thinking about all the good times we've had together...",
      'Do you remember that time when...?',
      'I miss the old days when we would...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Apologize conversation - Repair relationship
 */
export async function apologizeConvo(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'apologizeConvo';
  const button = 'I need to apologize';


  if (check) {
    const canTrigger =
      character.status === 'alive' &&
      player.c.ageYears >= 8 &&
      (character.affinity ?? 50) < 30;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'I owe you an apology...',
      "I'm really sorry about how things have been between us.",
      'I want to make things right between us.',
      'Can we talk? I feel bad about what happened...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Share dream conversation
 */
export async function shareDream(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'shareDream';
  const button = 'I had the weirdest dream';


  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 8;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'I had the strangest dream last night!',
      "You'll never believe the dream I had...",
      'I keep having this weird dream...',
      'So I had this really bizarre dream about...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Ask favor conversation
 */
export async function askFavor(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'askFavor';
  const button = 'Can you help me with something?';


  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 10;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'I need a favor... can you help me out?',
      'Would you be able to help me with something?',
      'I could really use your help with something...',
      'Can I ask you for a favor?',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Debate opinion conversation
 */
export async function debateOpinion(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'debateOpinion';
  const button = 'I disagree about...';


  if (check) {
    const canTrigger = character.status === 'alive' && player.c.ageYears >= 14;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.conversations.push(conversation);

    const messages = [
      'I actually disagree with you about that...',
      "Can we debate this for a second? I see it differently.",
      'I have a different perspective on this topic.',
      'I think we might have different opinions on this...',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * Share excitement conversation
 */
export async function shareExcitement(
  player: Player,
  character: Person,
  response: string | false = false,
  check = false
): Promise<ConversationResult> {
  const fname = 'shareExcitement';
  const button = "You won't believe what happened!";

  if (check) {
    const canTrigger =
      character.status === 'alive' &&
      player.c.ageYears >= 6 &&
      (player.c.happiness ?? 50) > 70;
    if (!canTrigger) return false;
    return { button, fname };
  }

  const person = getPerson(player, character.id) ?? character;

  if (!response) {
    const conversation = new ConversationObj(character, fname);
    player.c.happiness = Math.min(100, (player.c.happiness ?? 50) + 5);
    player.conversations.push(conversation);

    const messages = [
      "You won't believe what just happened!",
      'I have the best news to share!',
      "I'm so excited, I have to tell you something!",
      'Guess what?! Something amazing happened!',
    ];
    conversation.addMessage(randomChoice(messages), player.c.id, {
      date: player.date,
      time: player.time,
    });
    await getOpenAIResponse(conversation, person, player);
    return conversation;
  }

  const conversation = player.conversations[player.conversations.length - 1] as ConversationObj;
  conversation.addMessage(response, player.c.id, {
    date: player.date,
    time: player.time,
  });
  conversation.question += 1;

  if (conversation.question >= 0) {
    await getOpenAIResponse(conversation, person, player);
  }
  return conversation;
}

/**
 * All conversation event functions
 */
export const conversationEvents = {
  activity,
  checkIn,
  askAboutDay,
  flatter,
  studySession,
  chat,
  deepConversation,
  gossipSession,
  ventingSession,
  askAdvice,
  reminisce,
  apologizeConvo,
  shareDream,
  askFavor,
  debateOpinion,
  shareExcitement,
};

/**
 * Parse available conversations for a character
 */
export async function parseConversations(
  player: Player,
  character: Person
): Promise<ConversationCheckResult[]> {
  const results: ConversationCheckResult[] = [];

  for (const [_fname, fn] of Object.entries(conversationEvents)) {
    try {
      const result = await fn(player, character, false, true);
      if (result !== false && 'button' in result) {
        results.push(result);
      }
    } catch (error) {
      console.error(`Error checking conversation: ${error}`);
    }
  }

  return results;
}

/**
 * Initialize a conversation by type
 */
export function conversationInit(
  player: Player,
  character: Person,
  cType?: string,
  response: string | false = false
): Promise<ConversationResult> | undefined {
  if (cType && cType in conversationEvents) {
    return (conversationEvents as Record<string, typeof activity>)[cType](
      player,
      character,
      response
    );
  }
  return undefined;
}
