"""Factory for instantiating PSA providers from stored connection data."""
from __future__ import annotations

from uuid import UUID

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.psa_connection import PsaConnection
from app.services.psa.base import PSAProvider
from app.core.config import settings
from app.services.psa.encryption import decrypt_credentials
from app.services.psa.exceptions import PSAConnectionError


async def get_provider_for_account(
    account_id: UUID, db: AsyncSession
) -> PSAProvider:
    """Look up account's PSA connection, decrypt credentials, instantiate provider."""
    result = await db.execute(
        select(PsaConnection).where(
            PsaConnection.account_id == account_id,
            PsaConnection.is_active.is_(True),
        )
    )
    connection = result.scalar_one_or_none()

    if not connection:
        raise PSAConnectionError(
            "No active PSA connection configured for this account.",
            provider="unknown",
        )

    return _instantiate_provider(connection)


async def get_provider_for_connection(
    connection_id: UUID, db: AsyncSession
) -> PSAProvider:
    """Look up a specific PSA connection by ID, decrypt credentials, instantiate provider."""
    result = await db.execute(
        select(PsaConnection).where(
            PsaConnection.id == connection_id,
            PsaConnection.is_active.is_(True),
        )
    )
    connection = result.scalar_one_or_none()

    if not connection:
        raise PSAConnectionError(
            "PSA connection not found or inactive.",
            provider="unknown",
        )

    return _instantiate_provider(connection)


def _instantiate_provider(connection: PsaConnection) -> PSAProvider:
    """Create the appropriate provider instance from a connection record."""
    if connection.provider == "connectwise":
        from app.services.psa.connectwise.client import ConnectWiseClient
        from app.services.psa.connectwise.provider import ConnectWiseProvider

        creds = decrypt_credentials(connection.credentials_encrypted)
        client = ConnectWiseClient(
            site_url=connection.site_url,
            company_id=connection.company_id,
            public_key=creds["public_key"],
            private_key=creds["private_key"],
            client_id=settings.CW_CLIENT_ID or "",
        )
        return ConnectWiseProvider(client)

    raise PSAConnectionError(
        f"Unsupported PSA provider: {connection.provider}",
        provider=connection.provider,
    )
