"""Scoring service for calculating user scores."""

from config import settings
from database import get_prediction, update_user_score, update_prediction_score


async def calculate_result_prediction_score(
    user_id: int,
    match_id: int,
    actual_team1_score: int,
    actual_team2_score: int
) -> int:
    """Calculate the score earned for a result prediction (win/lose/draw).

    Returns the earned score points.
    """
    prediction = await get_prediction(user_id, match_id)
    if not prediction or prediction.get("predict_result") is None:
        return 0

    predict_result = prediction.get("predict_result")

    # Determine actual winner
    actual_winner = "team1" if actual_team1_score > actual_team2_score else "team2" if actual_team2_score > actual_team1_score else "draw"

    earned_score = 0
    if predict_result == actual_winner:
        earned_score += settings.SCORE_CORRECT_WINNER

    # Update prediction score
    await update_prediction_score(prediction["id"], earned_score)

    return earned_score


async def calculate_prediction_score(
    user_id: int,
    match_id: int,
    actual_team1_score: int,
    actual_team2_score: int
) -> int:
    """Calculate the score earned for a prediction.

    Returns the earned score points.
    """
    prediction = await get_prediction(user_id, match_id)
    if not prediction:
        return 0

    predict_team1 = prediction.get("predict_team1", 0)
    predict_team2 = prediction.get("predict_team2", 0)

    earned_score = 0

    # Correct winner: +5
    predict_winner = "team1" if predict_team1 > predict_team2 else "team2" if predict_team2 > predict_team1 else "draw"
    actual_winner = "team1" if actual_team1_score > actual_team2_score else "team2" if actual_team2_score > actual_team1_score else "draw"

    if predict_winner == actual_winner:
        earned_score += settings.SCORE_CORRECT_WINNER

    # Correct goal difference: +3
    predict_diff = abs(predict_team1 - predict_team2)
    actual_diff = abs(actual_team1_score - actual_team2_score)

    if predict_diff == actual_diff:
        earned_score += settings.SCORE_CORRECT_GOAL_DIFF

    # Exact score: +10
    if predict_team1 == actual_team1_score and predict_team2 == actual_team2_score:
        earned_score += settings.SCORE_EXACT_SCORE

    # Update prediction score
    await update_prediction_score(prediction["id"], earned_score)

    return earned_score


async def recalculate_all_scores() -> dict:
    """Recalculate all users' scores based on their predictions.

    Returns dict with statistics of the recalculation.
    """
    from database import get_all_users, get_predictions_for_match, get_match

    users = await get_all_users()
    stats = {"processed_predictions": 0, "total_score_added": 0}

    # Reset all scores first
    async with __import__("aiosqlite").connect(settings.DATABASE_PATH) as db:
        for user in users:
            await db.execute("UPDATE users SET score = 0 WHERE id = ?", (user["id"],))
        await db.commit()

    # Recalculate scores
    from database import DB_PATH, get_all_matches
    import aiosqlite

    async with aiosqlite.connect(DB_PATH) as db:
        db.row_factory = aiosqlite.Row

        # Get all finished matches with their predictions
        cursor = await db.execute("""
            SELECT m.id, m.team1_score, m.team2_score
            FROM matches m
            WHERE m.status = 'finished'
        """)
        finished_matches = await cursor.fetchall()

        for match in finished_matches:
            match_dict = dict(match)
            predictions = await get_predictions_for_match(match_dict["id"])

            for prediction in predictions:
                # Check if it's a result prediction or score prediction
                if prediction.get("predict_result"):
                    earned = await calculate_result_prediction_score(
                        prediction["user_id"],
                        match_dict["id"],
                        match_dict["team1_score"],
                        match_dict["team2_score"]
                    )
                else:
                    earned = await calculate_prediction_score(
                        prediction["user_id"],
                        match_dict["id"],
                        match_dict["team1_score"],
                        match_dict["team2_score"]
                    )

                await update_user_score(prediction["user_id"], earned)
                stats["processed_predictions"] += 1
                stats["total_score_added"] += earned

    return stats