"""Tests for package-level API and bootstrap behavior."""

from __future__ import annotations

import importlib


def test_package_root_exports_agent() -> None:
    """`from agentbyte import Agent` should be supported."""
    from agentbyte import Agent
    from agentbyte.agents import Agent as AgentClass

    assert Agent is AgentClass


def test_entity_import_path() -> None:
    """Entity should be importable from the root."""
    from agentbyte import Entity
    from agentbyte.entity import Entity as FlatEntity

    assert Entity is FlatEntity


def test_plan_orchestration_import_paths() -> None:
    """Plan orchestration types should be importable from package roots."""
    from agentbyte import (
        AgentHistoryPolicy,
        ExecutionPlan,
        FinalResultPolicy,
        HandoffOrchestrator,
        HistoryContextPolicy,
        PlanBasedOrchestrator,
        PlanStep,
        ReviewGatePolicy,
        SelectorContextPolicy,
        StepProgressEvaluation,
    )
    from agentbyte.orchestration import (
        AgentHistoryPolicy as FlatAgentHistoryPolicy,
        ExecutionPlan as FlatExecutionPlan,
        FinalResultPolicy as FlatFinalResultPolicy,
        HandoffOrchestrator as FlatHandoffOrchestrator,
        HistoryContextPolicy as FlatHistoryContextPolicy,
        PlanBasedOrchestrator as FlatPlanBasedOrchestrator,
        PlanStep as FlatPlanStep,
        ReviewGatePolicy as FlatReviewGatePolicy,
        SelectorContextPolicy as FlatSelectorContextPolicy,
        StepProgressEvaluation as FlatStepProgressEvaluation,
    )

    assert AgentHistoryPolicy is FlatAgentHistoryPolicy
    assert FinalResultPolicy is FlatFinalResultPolicy
    assert HandoffOrchestrator is FlatHandoffOrchestrator
    assert PlanBasedOrchestrator is FlatPlanBasedOrchestrator
    assert ExecutionPlan is FlatExecutionPlan
    assert HistoryContextPolicy is FlatHistoryContextPolicy
    assert PlanStep is FlatPlanStep
    assert ReviewGatePolicy is FlatReviewGatePolicy
    assert SelectorContextPolicy is FlatSelectorContextPolicy
    assert StepProgressEvaluation is FlatStepProgressEvaluation



def test_session_store_import_paths() -> None:
    """Session stores should be importable from agentbyte, agentbyte.session_store, and agentbyte.webui."""
    from agentbyte import CachedFileSessionStore, FileSessionStore, InMemorySessionStore, SessionStore
    from agentbyte.session_store import CachedFileSessionStore as FlatCached
    from agentbyte.session_store import FileSessionStore as FlatFile
    from agentbyte.session_store import InMemorySessionStore as FlatMemory
    from agentbyte.session_store import SessionStore as FlatStore
    from agentbyte.webui import CachedFileSessionStore as WebUICached
    from agentbyte.webui import FileSessionStore as WebUIFile
    from agentbyte.webui import InMemorySessionStore as WebUIMemory
    from agentbyte.webui import SessionStore as WebUIStore

    assert SessionStore is FlatStore is WebUIStore
    assert InMemorySessionStore is FlatMemory is WebUIMemory
    assert FileSessionStore is FlatFile is WebUIFile
    assert CachedFileSessionStore is FlatCached is WebUICached


def test_preset_import_paths() -> None:
    """Preset builders should be importable from package roots."""
    from agentbyte import (
        build_chat_client,
        get_ai_orchestrator,
        get_orchestrator,
        get_plan_based_orchestrator,
        get_round_robin_orchestrator,
        get_workflow,
    )
    from agentbyte.presets import (
        build_chat_client as FlatBuildClient,
        get_ai_orchestrator as FlatAI,
        get_orchestrator as FlatGetOrchestrator,
        get_plan_based_orchestrator as FlatPlan,
        get_round_robin_orchestrator as FlatRoundRobin,
        get_workflow as FlatWorkflow,
    )

    assert build_chat_client is FlatBuildClient
    assert get_orchestrator is FlatGetOrchestrator
    assert get_round_robin_orchestrator is FlatRoundRobin
    assert get_ai_orchestrator is FlatAI
    assert get_plan_based_orchestrator is FlatPlan
    assert get_workflow is FlatWorkflow


def test_workflow_subworkflow_step_import_paths() -> None:
    """SubWorkflowStep should be importable from workflow package roots."""
    from agentbyte.workflow import SubWorkflowStep
    from agentbyte.workflow.steps import SubWorkflowStep as StepsSubWorkflowStep
    from agentbyte.workflow.steps.subworkflow import SubWorkflowStep as ModuleSubWorkflowStep

    assert SubWorkflowStep is StepsSubWorkflowStep is ModuleSubWorkflowStep


def test_workflow_agent_import_paths() -> None:
    """WorkflowAgent should be importable from workflow package roots."""
    from agentbyte.workflow import WorkflowAgent
    from agentbyte.workflow.agent import WorkflowAgent as ModuleWorkflowAgent

    assert WorkflowAgent is ModuleWorkflowAgent


def test_workflow_schema_loader_symbols_importable() -> None:
    """Declarative workflow loader symbols should be importable from the workflow package root."""
    from agentbyte.workflow import (
        WorkflowBuilder,
        WorkflowLoader,
        WorkflowSchemaBuildError,
        WorkflowStepRegistry,
    )

    assert WorkflowBuilder is not None
    assert WorkflowLoader is not None
    assert WorkflowSchemaBuildError is not None
    assert WorkflowStepRegistry is not None


def test_workflow_context_is_canonical_public_context_name() -> None:
    """Workflow package roots should expose WorkflowContext, not Context."""
    workflow_module = importlib.import_module("agentbyte.workflow")
    workflow_core_module = importlib.import_module("agentbyte.workflow.core")

    from agentbyte.workflow import WorkflowContext
    from agentbyte.workflow.core import WorkflowContext as CoreWorkflowContext
    from agentbyte.workflow.core.models import WorkflowContext as ModelWorkflowContext

    assert WorkflowContext is CoreWorkflowContext is ModelWorkflowContext
    assert not hasattr(workflow_module, "Context")
    assert not hasattr(workflow_core_module, "Context")


def test_llm_root_exports_expected_public_api() -> None:
    """`agentbyte.llm` should preserve the intended stable root export surface."""
    from agentbyte.llm import (
        AuthenticationError,
        AzureOpenAIChatCompletionClient,
        AzureOpenAIEmbeddingClient,
        AzureOpenAISettings,
        AzureServicePrincipalSettings,
        BaseChatCompletionClient,
        BaseEmbeddingClient,
        ChatCompletionChunk,
        ChatCompletionResult,
        EmbeddingResult,
        InvalidRequestError,
        ModelClientError,
        OpenAIChatCompletionClient,
        OpenAIEmbeddingClient,
        OpenAISettings,
        RateLimitError,
        RetryPolicy,
        create_token_provider_from_string,
        get_certificate_token_provider,
        get_default_token_provider,
    )

    assert BaseChatCompletionClient is not None
    assert BaseEmbeddingClient is not None
    assert OpenAIChatCompletionClient is not None
    assert OpenAIEmbeddingClient is not None
    assert AzureOpenAIChatCompletionClient is not None
    assert AzureOpenAIEmbeddingClient is not None
    assert OpenAISettings is not None
    assert AzureOpenAISettings is not None
    assert AzureServicePrincipalSettings is not None
    assert get_default_token_provider is not None
    assert get_certificate_token_provider is not None
    assert create_token_provider_from_string is not None
    assert ChatCompletionResult is not None
    assert ChatCompletionChunk is not None
    assert EmbeddingResult is not None
    assert ModelClientError is not None
    assert RateLimitError is not None
    assert AuthenticationError is not None
    assert InvalidRequestError is not None
    assert RetryPolicy is not None


def test_llm_canonical_provider_package_import_paths() -> None:
    """Canonical provider package imports should remain stable."""
    from agentbyte.llm.azure.auth import get_certificate_token_provider
    from agentbyte.llm.azure.chat import (
        AzureOpenAIChatCompletionClient,
        AzureOpenAIChatCompletionClientConfig,
    )
    from agentbyte.llm.azure.embedding import (
        AzureOpenAIEmbeddingClient,
        AzureOpenAIEmbeddingClientConfig,
    )
    from agentbyte.llm.azure.settings import (
        AzureOpenAISettings,
        AzureServicePrincipalSettings,
    )
    from agentbyte.llm.openai.chat import (
        OpenAIChatCompletionClient,
        OpenAIChatCompletionClientConfig,
    )
    from agentbyte.llm.openai.embedding import (
        OpenAIEmbeddingClient,
        OpenAIEmbeddingClientConfig,
    )
    from agentbyte.llm.openai.settings import OpenAISettings

    assert OpenAIChatCompletionClient is not None
    assert OpenAIChatCompletionClientConfig is not None
    assert OpenAIEmbeddingClient is not None
    assert OpenAIEmbeddingClientConfig is not None
    assert OpenAISettings is not None
    assert AzureOpenAIChatCompletionClient is not None
    assert AzureOpenAIChatCompletionClientConfig is not None
    assert AzureOpenAIEmbeddingClient is not None
    assert AzureOpenAIEmbeddingClientConfig is not None
    assert AzureOpenAISettings is not None
    assert AzureServicePrincipalSettings is not None
    assert get_certificate_token_provider is not None


def test_llm_legacy_flat_module_shims_remain_available() -> None:
    """Legacy flat LLM module paths should continue to import during the transition."""
    from agentbyte.llm.auth import get_default_token_provider
    from agentbyte.llm.azure_openai import AzureOpenAIChatCompletionClient
    from agentbyte.llm.azure_openai_embedding import AzureOpenAIEmbeddingClient
    from agentbyte.llm.openai import OpenAIChatCompletionClient
    from agentbyte.llm.openai_embedding import OpenAIEmbeddingClient
    from agentbyte.llm.settings import (
        AzureOpenAISettings,
        AzureServicePrincipalSettings,
        OpenAISettings,
    )

    assert OpenAIChatCompletionClient is not None
    assert OpenAIEmbeddingClient is not None
    assert AzureOpenAIChatCompletionClient is not None
    assert AzureOpenAIEmbeddingClient is not None
    assert get_default_token_provider is not None
    assert OpenAISettings is not None
    assert AzureOpenAISettings is not None
    assert AzureServicePrincipalSettings is not None


def test_package_root_otel_bootstrap_calls_auto_instrument(
    monkeypatch,
) -> None:
    """Importing package root should trigger auto-instrumentation when enabled."""
    monkeypatch.setenv("AGENTBYTE_ENABLE_OTEL", "true")

    import agentbyte.middleware as middleware

    called = {"value": False}

    def _fake_auto_instrument() -> None:
        called["value"] = True

    monkeypatch.setattr(middleware, "auto_instrument", _fake_auto_instrument)

    import agentbyte

    importlib.reload(agentbyte)
    assert called["value"] is True


def test_package_root_otel_bootstrap_instruments_agent_init(
    monkeypatch,
) -> None:
    """Importing package root with OTel enabled patches Agent.__init__."""
    monkeypatch.setenv("AGENTBYTE_ENABLE_OTEL", "true")

    from agentbyte.agents.agent import Agent as AgentClass

    original_init = getattr(
        AgentClass.__init__,
        "__agentbyte_original_init__",
        AgentClass.__init__,
    )
    AgentClass.__init__ = original_init

    try:
        import agentbyte

        importlib.reload(agentbyte)
        assert getattr(AgentClass.__init__, "__agentbyte_otel_instrumented__", False) is True
    finally:
        AgentClass.__init__ = original_init
