# Copyright (c) 2025 CoReason, Inc.
#
# This software is proprietary and dual-licensed.
# Licensed under the Prosperity Public License 3.0 (the "License").
# A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
# For details, see the LICENSE file.
# Commercial use beyond a 30-day trial requires a separate license.
#
# Source Code: https://github.com/CoReason-AI/coreason_council

import asyncio
from abc import ABC, abstractmethod

from coreason_council.core.models.interaction import Critique, ProposerOutput
from coreason_council.core.models.verdict import Verdict, VerdictOption
from coreason_council.utils.logger import logger


class BaseAggregator(ABC):
    """
    Abstract base class for the Aggregator (The Judge).
    Responsible for synthesizing the final verdict from proposals and critiques.
    """

    @abstractmethod
    async def aggregate(
        self,
        proposals: list[ProposerOutput],
        critiques: list[Critique],
        is_deadlock: bool = False,
    ) -> Verdict:
        """
        Synthesizes a final verdict based on multiple proposals and their critiques.

        Args:
            proposals: A list of initial proposals from Proposers.
            critiques: A list of critiques generated by the Dissenter.
            is_deadlock: Whether the session ended in a deadlock (max rounds reached without consensus).

        Returns:
            Verdict object containing the final answer, confidence score, and citations.
        """
        pass  # pragma: no cover


class MockAggregator(BaseAggregator):
    """
    A mock implementation of an Aggregator for testing and development.
    """

    def __init__(
        self,
        default_content: str = "Mock Verdict",
        default_confidence: float = 0.95,
        default_supporting_evidence: list[str] | None = None,
        default_dissenting_opinions: list[str] | None = None,
        delay_seconds: float = 0.0,
    ) -> None:
        self.default_content = default_content
        self.default_confidence = default_confidence
        self.default_supporting_evidence = default_supporting_evidence or ["Proposer A's logic", "Proposer B's data"]
        self.default_dissenting_opinions = default_dissenting_opinions or ["Minor concern from C"]
        self.delay_seconds = delay_seconds

    async def aggregate(
        self,
        proposals: list[ProposerOutput],
        critiques: list[Critique],
        is_deadlock: bool = False,
    ) -> Verdict:
        logger.info(f"MockAggregator aggregating {len(proposals)} proposals and {len(critiques)} critiques.")

        if self.delay_seconds > 0:
            await asyncio.sleep(self.delay_seconds)

        # Construct a mock content string that references inputs to show they were "processed"
        proposer_ids = ", ".join([p.proposer_id for p in proposals])
        reviewer_ids = ", ".join([c.reviewer_id for c in critiques])

        alternatives = []
        confidence = self.default_confidence

        if is_deadlock:
            content = (
                f"MINORITY REPORT: Deadlock detected. {self.default_content} "
                f"(Options based on: {proposer_ids}; Critiques: {reviewer_ids})"
            )
            confidence = 0.1  # Low confidence for deadlock

            # Split proposers into two arbitrary groups to simulate competing options
            mid = len(proposals) // 2
            group_a = proposals[:mid]
            group_b = proposals[mid:]

            alternatives = [
                VerdictOption(
                    label="Option A",
                    content=f"Option A content based on {[p.proposer_id for p in group_a]}",
                    supporters=[p.proposer_id for p in group_a],
                ),
                VerdictOption(
                    label="Option B",
                    content=f"Option B content based on {[p.proposer_id for p in group_b]}",
                    supporters=[p.proposer_id for p in group_b],
                ),
            ]
        else:
            content = f"{self.default_content} (Based on inputs from: {proposer_ids}; Critiqued by: {reviewer_ids})"

        return Verdict(
            content=content,
            confidence_score=confidence,
            supporting_evidence=self.default_supporting_evidence,
            dissenting_opinions=self.default_dissenting_opinions,
            alternatives=alternatives,
        )
