#!/usr/bin/env python
"""
Relationship Manager Module

This module contains all relationship management functions for the BaoLife game.
It handles romantic relationships, dating activities, affinity updates, and
relationship data management.

Functions:
    - updateAffinity: Updates affinity score for a person
    - handleRelationships: Manages relationship events and score updates
    - getRelData: Fetches relationship data by person ID
    - romance: Initiates a romantic relationship with a target
    - getActiveRelationship: Returns the active dating/married relationship
    - breakUp: Ends a relationship with a partner
    - partnerGift: Gives a gift to partner to increase affinity
    - dateNight: Executes a date night activity with partner

Classes:
    - DateIdea: Represents a date activity with costs and rewards

Imports:
    - relationshipClass: Imported from core.models
    - get_person: Imported from character.character_manager

Author: BaoLife Development Team
"""

import random
import uuid
from events import messageFunction

# Import relationshipClass from core.models (avoid duplication)
from core.models import relationshipClass

# Import get_person from character module (avoid duplication)
from character.character_manager import get_person


# ============================================================================
# CLASSES
# ============================================================================


class DateIdea:
    """
    Represents a date activity option with associated costs and benefits.

    Attributes:
        name: Name of the date activity
        energy_cost: Energy points required for this activity
        money_cost: Money cost for this activity
        message: Description message shown to player
        image: URL to image representing this date type
    """
    def __init__(self, name, energy_cost, money_cost, message, image=None):
        self.name = name
        self.energy_cost = energy_cost
        self.money_cost = money_cost
        self.message = message
        self.image = image


# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

def getRelData(player, person_id):
    """
    Fetch relationship data based on person1 or person2 id.

    Args:
        player: The player object
        person_id: The ID of the person you are searching for in the relationships

    Returns:
        Relationship data if found, else None
    """
    for rel in player.relData:
        if rel.person1 == person_id or rel.person2 == person_id or rel.id == person_id:
            return rel
    return None


def getActiveRelationship(player):
    """
    Get the player's current active romantic relationship.

    Args:
        player: The player object

    Returns:
        Active relationship (Dating or Married status) if found, None otherwise
    """
    for relData in player.relData:
        if relData.relationshipStatus == "Dating" or relData.relationshipStatus == "Married":
            return relData
    return None


# ============================================================================
# AFFINITY AND RELATIONSHIP MANAGEMENT
# ============================================================================

def updateAffinity(player, id, value):
    """
    Update the affinity score for a specific person in the player's relationships.

    Args:
        player: The player object
        id: The ID of the person whose affinity to update
        value: The amount to change affinity by (can be positive or negative)

    Returns:
        Updated player object
    """
    for index, item in enumerate(player.r):
        if item.id == id:
            player.r[index].affinity = player.r[index].affinity + value
    return player


def handleRelationships(player, person):
    """
    Handle relationship events and score updates for a person.

    This function:
    - Has a 5% chance of triggering random relationship events
    - Updates relationship score weekly
    - Applies correction mechanism to keep scores balanced

    Args:
        player: The player object
        person: The person object to handle relationship with

    Returns:
        False if no relationship data exists, otherwise modifies relationship in place
    """
    event_chance = random.randint(1, 100)
    rel = getRelData(player, person.id)
    if (not rel):
        return False
    if event_chance > 95:  # 5% chance
        event = random.choice(["Went on a romantic trip", "Had a disagreement", "Met with friends"])
        rel.eventsLog.append(event)

        if event == "Went on a romantic trip":
            rel.relationshipScore += 10
        elif event == "Had a disagreement":
            rel.relationshipScore -= 10
        else:  # "Met with friends"
            rel.relationshipScore += 5

    # Regular Weekly Relationship Score Update (e.g., +1 for every week they are in a relationship)
    rel.relationshipScore += 1

    # Correction mechanism
    if rel.relationshipScore < 40:
        rel.relationshipScore += 2  # Correct upwards by adding 2
    elif rel.relationshipScore > 60:
        rel.relationshipScore -= 2  # Correct downwards by subtracting 2


# ============================================================================
# ROMANTIC ACTIONS
# ============================================================================

def romance(player, partner):
    """
    Attempt to start a romantic relationship with a target person.

    Checks if the target has sufficient affinity (>= 50) and creates a new
    relationship if successful.

    Args:
        player: The player object
        partner: The ID of the person to romance

    Returns:
        True if romance attempt successful, False otherwise
    """
    romanticTarget = get_person(player, partner)
    if romanticTarget:
        # we are checking if this person likes us enough to date us, if so add them as a relationship  ie
        #parents_relationship = relationshipClass(mother.id, father.id, generate_random_date(), "Married", "Happily married for years.")
        #player.relData.append(parents_relationship)
        if romanticTarget.affinity >= 50:
            relationship = relationshipClass(player.c.id, romanticTarget.id, player.date, "Prospect", "You are now dating.")
            player.relData.append(relationship)
            player.c.relationship = relationship.id
            romanticTarget.relationship = relationship.id
            player.messageQueue.append("You have attempted a romance of "+romanticTarget.firstname+" "+romanticTarget.lastname+".")

            # Apply messaging style modifiers for starting dating
            from messaging_style import apply_event_modifiers
            apply_event_modifiers(relationship, 'start_dating')

            return True
    return False


def breakUp(player, partner):
    """
    End a romantic relationship with a partner.

    Args:
        player: The player object
        partner: The ID of the partner to break up with

    Returns:
        True if breakup successful, False otherwise
    """
    # loop through player.classmates to find the correct one
    for relData in player.relData:
        if relData.person2 == partner:
            relData.relationshipStatus = "Broke Up"
            player.c.relationship = None
            # add message to message queue
            player.messageQueue.append("You dumped your partner.")

            # Apply messaging style modifiers for breakup
            from messaging_style import apply_event_modifiers
            apply_event_modifiers(relData, 'breakup')

            return True
    return False


def partnerGift(player, partner):
    """
    Give a gift to your partner to increase affinity.

    Costs $100 and increases affinity by 6-15 points.

    Args:
        player: The player object
        partner: The ID of the partner to give gift to

    Returns:
        messageEvent if successful, False if player doesn't have enough money
    """
    # loop through player.classmates to find the correct one
    for relData in player.relData:
        if relData.person2 == partner:
            # check if player has enough money
            if player.c.money >= 100:
                # subtract money
                player.c.money -= 100
                # add message to message queue
                gained = 5 + random.randint(1, 10)
                partner = get_person(player, partner)
                partner.affinity += gained
                message = "You bought a gift for your partner, gaining "+str(gained)+" affinity."
                imageLink = "https://lichun.app/assets/images/partnerGift.jpeg"
                player.messageQueue.append(message)
                return messageFunction('partnerGift', message, player, True, title='Gift', image=imageLink, moneyCost=100, affinityChange=gained)
            else:
                return False


# ============================================================================
# DATE ACTIVITIES
# ============================================================================

def getDateIdeas():
    """
    Get all available date activity options.

    Returns:
        List of DateIdea objects representing different date activities
    """
    date_ideas = [
        DateIdea("Picnic in the Park", 2, 20, "You enjoyed a relaxing picnic in the park.", 'https://lichun.app/assets/images/picnicDate.png'),
        DateIdea("Movie Night at Home", 1, 0, "You had a cozy movie night at home.", 'https://lichun.app/assets/images/dateNight.png'),
        DateIdea("Hiking Adventure", 3, 10, "You embarked on an exhilarating hiking adventure.", 'https://lichun.app/assets/images/hikingDate.png'),
        DateIdea("Fine Dining Experience", 2, 100, "You had a romantic fine dining experience.", 'https://lichun.app/assets/images/fineDiningDate.png'),
        DateIdea("Visit a Museum or Art Gallery", 2, 50, "You visited a museum or art gallery.", 'https://lichun.app/assets/images/museumDate.png'),
        DateIdea("Cooking Class Together", 3, 70, "You took a cooking class together.", 'https://lichun.app/assets/images/cookingDate.png'),
        DateIdea("Amusement Park Day", 4, 120, "You had a fun day at the amusement park.", 'https://lichun.app/assets/images/amusementParkDate.png'),
        DateIdea("Beach Day", 2, 30, "You spent the day at the beach.", 'https://lichun.app/assets/images/beachDate.png'),
        DateIdea("Attend a Concert or Show", 3, 150, "You attended a concert or show.", 'https://lichun.app/assets/images/concertDate.png'),
        DateIdea("Spa Day for Relaxation", 1, 200, "You enjoyed a relaxing spa day.", 'https://lichun.app/assets/images/spaDate.png'),
    ]
    return date_ideas


def dateNight(player, idea):
    """
    Execute a date night activity with the player's partner.

    Checks if player has sufficient energy and money, then:
    - Increases relationship score
    - Deducts energy and money costs
    - Adds prestige
    - Creates a message event

    Args:
        player: The player object
        idea: The name of the date idea to execute

    Returns:
        messageEvent if successful, False if player lacks resources
    """
    # loop through player.dateIdeas to find the correct one
    for dateIdea in getDateIdeas():
        if dateIdea.name == idea:
            # check if player has enough energy and money
            if player.c.energy >= dateIdea.energy_cost and player.c.money >= dateIdea.money_cost:
                relationship = getActiveRelationship(player)
                score_change = random.randint(1, 10);
                relationship.relationshipScore += score_change
                relationship.eventsLog.append(f"You went on a '{dateIdea.name}' date.")
                # subtract energy and money
                player.c.energy -= dateIdea.energy_cost
                player.c.money -= dateIdea.money_cost
                # add prestige
                player.c.prestige += 5
                # add message to message queue
                message = f"You went on a '{dateIdea.name}' date."
                if idea == "Picnic in the Park":
                    message = "You enjoyed a relaxing picnic in the park."
                elif idea == "Movie Night at Home":
                    message = "You had a cozy movie night at home."
                elif idea == "Hiking Adventure":
                    message = "You embarked on an exhilarating hiking adventure."
                elif idea == "Fine Dining Experience":
                    message = "You had a romantic fine dining experience."
                elif idea == "Visit a Museum or Art Gallery":
                    message = "You visited a museum or art gallery."
                elif idea == "Cooking Class Together":
                    message = "You took a cooking class together."
                elif idea == "Amusement Park Day":
                    message = "You had a fun day at the amusement park."
                elif idea == "Beach Day":
                    message = "You spent the day at the beach."
                elif idea == "Attend a Concert or Show":
                    message = "You attended a concert or show."
                elif idea == "Spa Day for Relaxation":
                    message = "You enjoyed a relaxing spa day."

                message += f" You spent {dateIdea.energy_cost} energy and {dateIdea.money_cost} money."
                message += f" Your relationship score increased by {score_change} points."

                player.messageQueue.append(message)
                #def messageFunction(fname,message,player=False,check=False,title="",image="",energyCost = 0,diamondCost = 0, moneyCost = 0,affinityChange = 0):
                return messageFunction('dateNight', message, player, True, 'Date Night', dateIdea.image, dateIdea.energy_cost, 0, dateIdea.money_cost, 0)
            else:
                return False
