"""
Diamond Economy System

Handles diamond earning, spending, and tracking.
Diamonds are the premium currency in BaoLife.
"""

from typing import Dict, Any, Optional
import logging
from database import get_database_connection


def award_diamonds(player_id: int, reason: str, amount: int) -> bool:
    """
    Award diamonds to player with tracking.

    Args:
        player_id: The player's ID
        reason: Reason for awarding diamonds (for logging)
        amount: Number of diamonds to award (must be positive)

    Returns:
        True if successful, False otherwise
    """
    # Validate amount is positive
    if amount <= 0:
        logging.error(f"Invalid diamond amount for player {player_id}: {amount} (must be positive)")
        return False

    conn = None
    cursor = None

    try:
        conn = get_database_connection()
        cursor = conn.cursor(dictionary=True)

        # Award diamonds
        cursor.execute(
            "UPDATE players SET diamonds = diamonds + %s WHERE id = %s",
            (amount, player_id)
        )

        # Log transaction
        cursor.execute(
            """INSERT INTO diamond_transactions
               (player_id, transaction_type, amount, reason)
               VALUES (%s, 'earn', %s, %s)""",
            (player_id, amount, reason)
        )

        conn.commit()

        # Get new total
        cursor.execute("SELECT diamonds FROM players WHERE id = %s", (player_id,))
        result = cursor.fetchone()
        new_total = result['diamonds'] if result else amount

        logging.info(f"Player {player_id} earned {amount} diamonds: {reason} (total: {new_total})")

        return True

    except Exception as e:
        if conn:
            conn.rollback()
        logging.error(f"Error awarding diamonds to player {player_id}: {e}", exc_info=True)
        return False

    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def deduct_diamonds(player_id: int, reason: str, amount: int) -> Dict[str, Any]:
    """
    Deduct diamonds from player with validation.

    Args:
        player_id: The player's ID
        reason: Reason for deducting diamonds (for logging)
        amount: Number of diamonds to deduct (must be positive)

    Returns:
        dict with 'success' and 'message' keys
    """
    # Validate amount is positive
    if amount <= 0:
        logging.error(f"Invalid diamond amount for player {player_id}: {amount} (must be positive)")
        return {'success': False, 'message': 'Invalid amount'}

    conn = None
    cursor = None

    try:
        conn = get_database_connection()
        cursor = conn.cursor(dictionary=True)

        # Check current balance
        cursor.execute("SELECT diamonds FROM players WHERE id = %s", (player_id,))
        result = cursor.fetchone()

        if not result:
            return {'success': False, 'message': 'Player not found'}

        current_balance = result['diamonds']

        if current_balance < amount:
            return {
                'success': False,
                'message': f'Insufficient diamonds. Need {amount}, have {current_balance}'
            }

        # Deduct diamonds
        cursor.execute(
            "UPDATE players SET diamonds = diamonds - %s WHERE id = %s",
            (amount, player_id)
        )

        # Log transaction
        cursor.execute(
            """INSERT INTO diamond_transactions
               (player_id, transaction_type, amount, reason)
               VALUES (%s, 'spend', %s, %s)""",
            (player_id, amount, reason)
        )

        conn.commit()

        new_balance = current_balance - amount
        logging.info(f"Player {player_id} spent {amount} diamonds: {reason} (remaining: {new_balance})")

        return {
            'success': True,
            'message': 'Diamonds deducted successfully',
            'new_balance': new_balance
        }

    except Exception as e:
        if conn:
            conn.rollback()
        logging.error(f"Error deducting diamonds from player {player_id}: {e}", exc_info=True)
        return {'success': False, 'message': 'Server error'}

    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def get_diamond_balance(player_id: int) -> Optional[int]:
    """
    Get player's current diamond balance.

    Args:
        player_id: The player's ID

    Returns:
        Diamond balance or None if player not found
    """
    conn = None
    cursor = None

    try:
        conn = get_database_connection()
        cursor = conn.cursor(dictionary=True)

        cursor.execute("SELECT diamonds FROM players WHERE id = %s", (player_id,))
        result = cursor.fetchone()

        return result['diamonds'] if result else None

    except Exception as e:
        logging.error(f"Error getting diamond balance for player {player_id}: {e}")
        return None

    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def get_diamond_transaction_history(player_id: int, limit: int = 50) -> list:
    """
    Get player's diamond transaction history.

    Args:
        player_id: The player's ID
        limit: Maximum number of transactions to return

    Returns:
        List of transaction dictionaries
    """
    conn = None
    cursor = None

    try:
        conn = get_database_connection()
        cursor = conn.cursor(dictionary=True)

        cursor.execute(
            """SELECT transaction_type, amount, reason, created_at
               FROM diamond_transactions
               WHERE player_id = %s
               ORDER BY created_at DESC
               LIMIT %s""",
            (player_id, limit)
        )

        return cursor.fetchall()

    except Exception as e:
        logging.error(f"Error getting transaction history for player {player_id}: {e}")
        return []

    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


# Diamond rewards for various achievements
DIAMOND_REWARDS = {
    'level_up': 10,
    'complete_school_year': 15,
    'graduate_high_school': 25,
    'graduate_college': 50,
    'get_first_job': 15,
    'promotion': 20,
    'become_ceo': 100,
    'get_married': 25,
    'have_first_child': 30,
    'reach_age_milestone': 20,  # Every 10 years
    'daily_login': 5,
    'weekly_streak': 25,
    'monthly_streak': 100,
}


def get_reward_amount(reason: str) -> int:
    """
    Get the diamond reward amount for a specific reason.

    Args:
        reason: The reason/achievement key

    Returns:
        Diamond amount (0 if not found)
    """
    return DIAMOND_REWARDS.get(reason, 0)
