from decimal import Decimal
from types import SimpleNamespace

import pytest

from src.domain.codegen.execution import CodegenExecutionError, CodegenExecutionProvider, resolve_codegen_execution
from src.domain.codegen.execution_pricing import ExecutionUsage, calculate_execution_price


def settings(**overrides):
    values = dict(
        codegen_execution_provider="github",
        codegen_execution_target="hosted",
        codegen_execution_runner_class="linux_standard",
        codegen_execution_config_version="1",
        codegen_execution_backend="github_actions",
        codegen_allow_local_dev=False,
        environment="prod",
    )
    values.update(overrides)
    return SimpleNamespace(**values)


def test_default_is_github_hosted():
    target = resolve_codegen_execution(settings())
    assert target.provider is CodegenExecutionProvider.GITHUB
    assert target.target == "hosted"


def test_unadmitted_target_is_rejected():
    with pytest.raises(CodegenExecutionError):
        resolve_codegen_execution(settings(codegen_execution_target="arbitrary-runner-label"))


def test_invalid_provider_is_rejected():
    with pytest.raises(CodegenExecutionError):
        resolve_codegen_execution(settings(codegen_execution_provider="ssh"))


def test_self_hosted_target_is_representable_but_admitted():
    target = resolve_codegen_execution(settings(codegen_execution_provider="self_hosted", codegen_execution_target="codegen-pool-a"))
    assert target.snapshot()["provider"] == "self_hosted"


def test_local_legacy_path_is_rejected_in_production():
    with pytest.raises(CodegenExecutionError):
        resolve_codegen_execution(settings(codegen_execution_backend="server"))


def test_local_dev_requires_explicit_opt_in():
    with pytest.raises(CodegenExecutionError):
        resolve_codegen_execution(settings(codegen_execution_provider="local_dev", codegen_execution_target="development"))
    target = resolve_codegen_execution(settings(codegen_execution_provider="local_dev", codegen_execution_target="development", codegen_allow_local_dev=True, environment="dev"))
    assert target.provider is CodegenExecutionProvider.LOCAL_DEV


def test_execution_pricing_keeps_provider_cost_distinct_from_credits():
    price = calculate_execution_price(
        ExecutionUsage("github", "hosted", "linux_standard", 121),
        pricing_version="github-linux-test",
        provider_rate_usd_per_minute=Decimal("0.008"),
        credits_per_minute=1,
    )
    assert price.provider_cost_microusd == 16134
    assert price.credit_charge == 3
