"""PaddleOCR 真实 worker 的独立事务商业计量适配器。"""

from __future__ import annotations

import hashlib
from dataclasses import dataclass
from datetime import UTC, datetime

from sqlalchemy.orm import Session, sessionmaker

from app.api.deps import CurrentUserContext
from app.services.commercial_direct_operation import (
    CommercialDirectOperationBridge,
    DirectOperationIdentity,
    DirectOperationOutcome,
    DirectOperationResult,
)
from app.services.tenant_registry import required_tenant_id


class OcrCommercialAccessDenied(RuntimeError):
    pass


@dataclass(frozen=True, slots=True)
class OcrOperationContext:
    tenant_id: str
    operation_id: str
    run_id: str
    invocation_seq: int = 1

    def __post_init__(self) -> None:
        object.__setattr__(self, "tenant_id", required_tenant_id(self.tenant_id))
        for field_name in ("operation_id", "run_id"):
            value = str(getattr(self, field_name) or "").strip()
            if not value:
                raise ValueError(f"OcrOperationContext.{field_name} 不能为空。")
            object.__setattr__(self, field_name, value)
        if self.invocation_seq < 1:
            raise ValueError("OcrOperationContext.invocation_seq 必须大于 0。")


@dataclass(frozen=True, slots=True)
class OcrCommercialAttempt:
    identity: DirectOperationIdentity
    page_count: int


class OcrCommercialObserver:
    def __init__(self, bridge: CommercialDirectOperationBridge) -> None:
        self.bridge = bridge

    def permit(
        self,
        context: OcrOperationContext,
        *,
        page_count: int,
        provider: str,
        model_name: str,
        started_at: datetime,
    ) -> OcrCommercialAttempt:
        if isinstance(page_count, bool) or page_count < 1:
            raise ValueError("OCR worker page_count 必须是权威正整数。")
        identity = DirectOperationIdentity(
            tenant_id=context.tenant_id,
            operation_key=(f"{context.operation_id}:ocr-worker:{context.invocation_seq}"),
            run_key=context.run_id,
            tool_type="ocr",
            tool_name="paddle.worker",
            provider=provider,
            model_name=model_name,
            started_at=_utc(started_at),
        )
        permit = self.bridge.permit(
            identity,
            requested_quantity=page_count,
            required_quantity_basis="pages",
        )
        if not permit.allowed:
            raise OcrCommercialAccessDenied(permit.reason)
        return OcrCommercialAttempt(identity=identity, page_count=page_count)

    def complete(
        self,
        attempt: OcrCommercialAttempt,
        *,
        outcome: DirectOperationOutcome,
        completed_at: datetime,
    ) -> DirectOperationResult:
        return self.bridge.complete(
            attempt.identity,
            outcome=outcome,
            authoritative_quantities={"pages": attempt.page_count},
            completed_at=_utc(completed_at),
            usage_source="prepared_ocr_worker_pages",
            usage_availability="available",
        )


def build_ocr_commercial_observer(db: Session) -> OcrCommercialObserver:
    factory = sessionmaker(bind=db.get_bind(), expire_on_commit=False)
    return OcrCommercialObserver(
        CommercialDirectOperationBridge(factory, lookup_session=db)
    )


def trusted_ocr_operation_context(
    current_user: CurrentUserContext,
    *,
    operation_scope: str,
    content_digests: list[str],
    request_id: str = "",
    run_id: str = "",
) -> OcrOperationContext:
    """身份只取认证会话；文件仅使用 SHA256，不把名称或正文写入商业事实。"""

    normalized_scope = str(operation_scope or "").strip()
    if not normalized_scope:
        raise ValueError("operation_scope 不能为空。")
    normalized_digests = [
        item.strip().lower() for item in content_digests if len(str(item or "").strip()) == 64
    ]
    if not normalized_digests:
        raise ValueError("OCR operation 至少需要一个内容摘要。")
    request_component = str(request_id or "").strip()
    if not request_component:
        request_component = hashlib.sha256(
            "\x1f".join(normalized_digests).encode("utf-8")
        ).hexdigest()
    session_component = str(current_user.auth_session_id or "").strip()
    operation_digest = hashlib.sha256(
        "\x1f".join(
            (
                required_tenant_id(current_user.tenant_id),
                session_component,
                normalized_scope,
                request_component,
            )
        ).encode("utf-8")
    ).hexdigest()
    resolved_run_id = str(run_id or "").strip() or (f"ocr-{operation_digest[:32]}")
    return OcrOperationContext(
        tenant_id=current_user.tenant_id,
        operation_id=f"ocr-operation:{operation_digest}",
        run_id=resolved_run_id,
    )


def content_digest(content: bytes) -> str:
    return hashlib.sha256(content).hexdigest()


def _utc(value: datetime) -> datetime:
    return value.replace(tzinfo=UTC) if value.tzinfo is None else value.astimezone(UTC)
