"""Inactive ARR1 compatibility adapters; never imported by the ARR2 Web runtime."""

from __future__ import annotations

import os
import tempfile
import uuid
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Dict, Protocol

from arr_ingestion.contracts import IngestionError
from arr_ingestion.direct_contracts import SubmissionGrant
from arr_ingestion.repository import JobRegistration
from arr_processing.callbacks import AgentResultWriteback
from arr_processing.contracts import ProcessingRequest
from arr_processing.errors import ProcessingError
from arr_processing.runner import processing_dispatch_idempotency_key
from arr_storage.store import ManagedObjectStore
from arr_web.contracts import PortalError, validate_upload_filename, validate_xml_payload


class AgentResultCoordinator(Protocol):
    def accept(self, raw_signed_result: bytes) -> Dict[str, Any]:
        ...


class ProcessingStarter(Protocol):
    def start(self, request: ProcessingRequest) -> Any:
        ...


class DirectJobRepository(Protocol):
    def register_job(self, registration: JobRegistration) -> None:
        ...

    def issue_grant(
        self, job_id: str, attempt_no: int, *, ttl_seconds: int
    ) -> SubmissionGrant:
        ...


@dataclass
class ProcessingAgentResultCoordinator:
    writeback: AgentResultWriteback

    def accept(self, raw_signed_result: bytes) -> Dict[str, Any]:
        try:
            return self.writeback.accept(raw_signed_result).to_dict()
        except (IngestionError, ProcessingError) as error:
            code = error.code
            if code in {"PROCESSING_SIGNATURE_INVALID", "PROCESSING_SIGNATURE_EXPIRED"}:
                status, message = 401, "Agent 结果签名无效或已过期"
            elif code.endswith("_NOT_FOUND") or code in {
                "JOB_NOT_FOUND",
                "PROCESSING_JOB_NOT_FOUND",
            }:
                status, message = 404, "Agent 结果对应的业务任务不存在"
            elif "CONFLICT" in code or code in {
                "JOB_TERMINAL",
                "PROCESSING_RESULT_MISMATCH",
            }:
                status, message = 409, "Agent 结果与现有业务任务冲突"
            elif getattr(error, "retryable", False) or code.startswith("DATABASE_"):
                status, message = 503, "Agent 结果暂时无法写入，请使用相同回调重试"
            else:
                status, message = 422, "Agent 结果未通过业务验收"
            raise PortalError(code, message, status) from None


@dataclass
class ObjectStoreUploadCoordinator:
    """Frozen ARR1 upload/grant/remote-dispatch adapter for compatibility tests."""

    object_store: ManagedObjectStore
    ingestion_repository: DirectJobRepository
    processing_starter: ProcessingStarter
    processor_version: str
    rule_set_sha256: str
    submission_grant_ttl_seconds: int = 900

    def submit(self, original_filename: str, payload: bytes) -> Dict[str, Any]:
        uploaded_filename = validate_upload_filename(original_filename)
        validate_xml_payload(payload)
        job_id = "arrjob-" + uuid.uuid4().hex
        attempt_no = 1
        with tempfile.TemporaryDirectory(prefix="arr-web-upload-") as temporary:
            source_path = Path(temporary) / "source.xml"
            descriptor = os.open(source_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
            try:
                with os.fdopen(descriptor, "wb") as target:
                    descriptor = -1
                    target.write(payload)
                    target.flush()
                    os.fsync(target.fileno())
            finally:
                if descriptor >= 0:
                    os.close(descriptor)
            stored = self.object_store.upload_committed(
                job_id=job_id,
                attempt_no=attempt_no,
                role="source_xml",
                source=source_path,
                original_filename="source.xml",
            )
        source_file_id = "arr_file_" + uuid.uuid4().hex
        request_without_grant = ProcessingRequest(
            job_id=job_id,
            attempt_no=attempt_no,
            source_file_id=source_file_id,
            processor_version=self.processor_version,
            rule_set_sha256=self.rule_set_sha256,
        )
        self.ingestion_repository.register_job(
            JobRegistration(
                job_id=job_id,
                source=stored.to_artifact_ref(),
                processor_version=self.processor_version,
                rule_set_sha256=self.rule_set_sha256,
                attempt_no=attempt_no,
                idempotency_key=processing_dispatch_idempotency_key(request_without_grant),
                uploaded_filename=uploaded_filename,
            )
        )
        grant = self.ingestion_repository.issue_grant(
            job_id, attempt_no, ttl_seconds=self.submission_grant_ttl_seconds
        )
        request = ProcessingRequest(
            job_id=job_id,
            attempt_no=attempt_no,
            source_file_id=source_file_id,
            processor_version=self.processor_version,
            rule_set_sha256=self.rule_set_sha256,
            submission_grant=grant.submission_grant,
        )
        record = self.processing_starter.start(request)
        return {
            "job_id": job_id,
            "status": str(getattr(record, "remote_status", "queued")),
            "attempt_no": attempt_no,
            "source_sha256": stored.sha256,
            "source_byte_size": stored.byte_size,
        }
