#
#   Imandra Inc.
#
#   speclogician/logic/api/complement.py
#

import asyncio
from imandrax_api_models import DecomposeRes

from .client import SpecLogicianImandraX
from speclogician.modeling.spec import Spec
from speclogician.modeling.scenario import Scenario
from speclogician.modeling.complement import ScenarioComplement


def assert_decomp_ok(
    res: DecomposeRes,
    *,
    ctx: str = "decompose",
    require_regions: bool = True,
) -> None:
    if getattr(res, "errors", None):
        raise AssertionError(f"{ctx}: decomposition errors: {res.errors}")

    if res.regions_str is None:
        raise AssertionError(f"{ctx}: decomposition produced no regions (regions_str is None)")

    if require_regions and len(res.regions_str) == 0:
        raise AssertionError(f"{ctx}: decomposition returned zero regions")

async def decomp_intersection_async(sc1: Scenario, sc2: Scenario, spec: Spec) -> ScenarioComplement:
    """
    Decompose intersection of two scenarios and assert it succeeded.
    """
    async with SpecLogicianImandraX() as ix:
        res = await ix.decompose_intersection(
            domain_model=spec.domain_model,
            sc1=sc1,
            sc2=sc2,
        )
        return res

def decomp_intersection(sc1: Scenario, sc2: Scenario, spec: Spec) -> ScenarioComplement:
    """
    Sync wrapper around decomp_intersection_async.
    """
    return asyncio.run(decomp_intersection_async(sc1, sc2, spec))

async def decomp_complement_async(spec: Spec) -> ScenarioComplement:
    """
    Decompose complement of all scenarios in the spec and assert it succeeded.
    """
    scenarios = list(spec.scenarios)

    async with SpecLogicianImandraX() as ix:
        res = await ix.decompose_spec_complement(
            domain_model=spec.domain_model,
            scenarios=scenarios,
        )
        return res

def decomp_complement(spec: Spec) -> ScenarioComplement:
    """
    Sync wrapper around decomp_complement_async.
    """
    return asyncio.run(decomp_complement_async(spec))

