import asyncio
import json
from agents.negotiator_agent import NegotiatorAgent
import database as db

async def run_negotiation(negotiation_id: str, preferences_a: dict, preferences_b: dict,
                          user_a_id: int, user_b_id: int, feature_type: str,
                          personality_a: str = "balanced", personality_b: str = "balanced",
                          on_round_update=None, on_resolution=None,
                          feature_context: str = ""):
    """
    Main negotiation loop with personality-aware agents and analytics tracking.
    """
    await db.update_negotiation_status(negotiation_id, "active")

    # Create personality-aware negotiators
    negotiator_a = NegotiatorAgent(personality=personality_a)
    negotiator_b = NegotiatorAgent(personality=personality_b)

    current_proposal = None
    max_rounds = 7
    satisfaction_timeline = []

    for round_num in range(1, max_rounds + 1):
        await asyncio.sleep(1.5)  # Rate limit protection for Gemini

        if round_num == 1:
            response = await negotiator_a.generate_initial_proposal(
                my_preferences=preferences_a, feature_type=feature_type,
                feature_context=feature_context
            )
            proposer_id = user_a_id
        elif round_num % 2 == 0:
            response = await negotiator_b.evaluate_and_respond(
                received_proposal=current_proposal, my_preferences=preferences_b,
                feature_type=feature_type, round_number=round_num,
                feature_context=feature_context
            )
            proposer_id = user_b_id
        else:
            response = await negotiator_a.evaluate_and_respond(
                received_proposal=current_proposal, my_preferences=preferences_a,
                feature_type=feature_type, round_number=round_num,
                feature_context=feature_context
            )
            proposer_id = user_a_id

        # Handle errors
        if "error" in response:
            response = {
                "action": "counter" if round_num < max_rounds else "escalate",
                "proposal": current_proposal or {"summary": "Let's discuss further", "details": {}},
                "satisfaction_score": 50, "reasoning": "Agent encountered an issue",
                "concessions_made": [], "concessions_requested": []
            }

        action = response.get("action", "counter")
        current_proposal = response.get("proposal", {})
        satisfaction = response.get("satisfaction_score", 50)
        concessions = response.get("concessions_made", [])

        # Track satisfaction for analytics
        # The proposer's score is the one returned; estimate the other party's
        if proposer_id == user_a_id:
            sat_a, sat_b = satisfaction, max(30, 100 - satisfaction * 0.4)
        else:
            sat_b, sat_a = satisfaction, max(30, 100 - satisfaction * 0.4)

        satisfaction_timeline.append({
            "round": round_num, "score_a": sat_a, "score_b": sat_b
        })

        # Save round with analytics data
        await db.save_round(
            negotiation_id=negotiation_id, round_number=round_num,
            proposer_id=proposer_id, proposal=response,
            response_type=action, reasoning=response.get("reasoning", ""),
            satisfaction_a=sat_a, satisfaction_b=sat_b,
            concessions_made=concessions
        )

        # Notify via callback
        round_data = {
            "negotiation_id": negotiation_id, "round_number": round_num,
            "action": action, "proposal": current_proposal,
            "satisfaction_score": satisfaction, "reasoning": response.get("reasoning", ""),
            "proposer_id": proposer_id,
            "satisfaction_a": sat_a, "satisfaction_b": sat_b
        }
        if on_round_update:
            await on_round_update(round_data)

        # Check outcome
        if action == "accept":
            resolution = {
                "status": "resolved", "final_proposal": current_proposal,
                "rounds_taken": round_num, "summary": current_proposal.get("summary", "Agreement reached"),
                "satisfaction_timeline": satisfaction_timeline
            }
            await db.update_negotiation_status(negotiation_id, "resolved", resolution)
            if on_resolution:
                await on_resolution(resolution)
            return resolution

        if action == "escalate":
            resolution = {
                "status": "escalated", "final_proposal": current_proposal,
                "rounds_taken": round_num, "summary": "Agents couldn't fully agree. Options for human decision.",
                "satisfaction_timeline": satisfaction_timeline
            }
            await db.update_negotiation_status(negotiation_id, "escalated", resolution)
            if on_resolution:
                await on_resolution(resolution)
            return resolution

    # Exhausted rounds
    resolution = {
        "status": "escalated", "final_proposal": current_proposal,
        "rounds_taken": max_rounds, "summary": "Max rounds reached. Best proposal for human decision.",
        "satisfaction_timeline": satisfaction_timeline
    }
    await db.update_negotiation_status(negotiation_id, "escalated", resolution)
    if on_resolution:
        await on_resolution(resolution)
    return resolution
