from __future__ import annotations

import uuid

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.models.financial_connector import FinancialConnectorConfig
from app.schemas.financial_connector import FinancialConnectorConfigCreate
from app.services.financial_connector_config_audit import (
    append_connector_config_event,
    connector_config_state,
)


class FinancialConnectorConfigError(ValueError):
    pass


class FinancialConnectorConfigService:
    def __init__(self, db: Session) -> None:
        self.db = db

    def create(
        self,
        *,
        tenant_id: str,
        payload: FinancialConnectorConfigCreate,
        actor_id: str,
    ) -> FinancialConnectorConfig:
        normalized_tenant = str(tenant_id or "").strip()
        if not normalized_tenant:
            raise FinancialConnectorConfigError("连接器租户不能为空。")
        provider = payload.provider.strip().lower()
        existing = self.db.scalar(
            select(FinancialConnectorConfig.id).where(
                FinancialConnectorConfig.tenant_id == normalized_tenant,
                FinancialConnectorConfig.provider == provider,
                FinancialConnectorConfig.key_version == payload.key_version,
            )
        )
        if existing is not None:
            raise FinancialConnectorConfigError("该租户、来源和密钥版本的配置已存在。")
        row = FinancialConnectorConfig(
            id=str(uuid.uuid4()),
            tenant_id=normalized_tenant,
            provider=provider,
            environment=payload.environment,
            key_version=payload.key_version,
            secret_ref=payload.secret_ref,
            allowed_event_types_json=sorted(set(payload.allowed_event_types)),
            clock_skew_seconds=payload.clock_skew_seconds,
            status="disabled",
            version=1,
            created_by=str(actor_id or "platform-admin").strip() or "platform-admin",
        )
        self.db.add(row)
        self.db.flush()
        append_connector_config_event(
            self.db,
            row,
            action="created",
            actor_id=row.created_by,
            request_id=payload.request_id,
            reason=payload.reason,
            expected_version=None,
            before={},
            after=connector_config_state(row),
        )
        self.db.flush()
        return row

    def list_for_tenant(self, tenant_id: str) -> list[FinancialConnectorConfig]:
        return list(
            self.db.scalars(
                select(FinancialConnectorConfig)
                .where(FinancialConnectorConfig.tenant_id == str(tenant_id).strip())
                .order_by(
                    FinancialConnectorConfig.provider,
                    FinancialConnectorConfig.key_version,
                )
            ).all()
        )
