from __future__ import annotations

import uuid
from typing import Optional

from app.clients.pywechat_client import ClientRegistry, OnlineStatus, registry
from app.models.event import EventType, OutboundEvent
from app.repositories.event_store import EventStore, event_store


class SendService:
    def __init__(self, registry: ClientRegistry, store: EventStore):
        self.registry = registry
        self.store = store

    def send_text(
        self,
        account_id: str,
        conversation_id: str,
        text: str,
        record_id: str,
        tenant_code: str = "default",
    ) -> dict:
        client = self.registry.get(account_id)
        if client is None:
            return self._fail(account_id, record_id, tenant_code, conversation_id, f"account {account_id} not registered")
        if client.state.online_status != OnlineStatus.ONLINE:
            return self._fail(account_id, record_id, tenant_code, conversation_id, "account not online")
        if client.state.risk_level >= 80:
            return self._fail(
                account_id,
                record_id,
                tenant_code,
                conversation_id,
                "account risk level too high",
                error_code="RISK_CONTROL_BLOCKED",
            )

        message_id = f"mock-msg-{uuid.uuid4().hex[:16]}"
        channel_result = client.send_text(conversation_id, text)
        self._emit_send_result(account_id, record_id, tenant_code, conversation_id, True, message_id, channel_result)
        return {"accepted": True, "message_id": message_id}

    def send_image(
        self,
        account_id: str,
        conversation_id: str,
        image_url: str,
        record_id: str,
        tenant_code: str = "default",
    ) -> dict:
        client = self.registry.get(account_id)
        if client is None:
            return self._fail(account_id, record_id, tenant_code, conversation_id, f"account {account_id} not registered")
        if client.state.online_status != OnlineStatus.ONLINE:
            return self._fail(account_id, record_id, tenant_code, conversation_id, "account not online")

        message_id = f"mock-img-{image_url.split('/')[-1]}"
        self._emit_send_result(
            account_id,
            record_id,
            tenant_code,
            conversation_id,
            True,
            message_id,
            {"image_url": image_url},
        )
        return {"accepted": True, "message_id": message_id}

    def _fail(
        self,
        account_id: str,
        record_id: str,
        tenant_code: str,
        conversation_id: str,
        error: str,
        error_code: str = "SEND_FAILED",
    ) -> dict:
        self._emit_send_result(
            account_id,
            record_id,
            tenant_code,
            conversation_id,
            False,
            None,
            {"error": error, "error_code": error_code},
        )
        return {"accepted": False, "error": error}

    def _emit_send_result(
        self,
        account_id: str,
        record_id: str,
        tenant_code: str,
        conversation_id: str,
        success: bool,
        message_id: Optional[str],
        channel_result: dict,
    ) -> None:
        event = OutboundEvent(
            event_type=EventType.SEND_RESULT,
            account_id=account_id,
            tenant_code=tenant_code,
            data={
                "record_id": record_id,
                "conversation_id": conversation_id,
                "success": success,
                "message_id": message_id,
                "channel_result": channel_result,
                "error": channel_result.get("error"),
            },
        )
        self.store.save(event)


send_service = SendService(registry, event_store)
