from __future__ import annotations

from datetime import datetime, timezone
from typing import Any
from uuid import UUID

from src.connectors.sdk.base_sdk import SDKConnector
from src.connectors.sdk.context import ConnectorContext
from src.connectors.base import ConnectorResult
from src.core.exceptions import ConnectorException
from src.core.logging import get_logger
from src.core.metrics import CONNECTOR_OPERATIONS

logger = get_logger("farmatic_connector")


class FarmaticConnector(SDKConnector):
    connector_type: str = "farmatic"

    def configure(self, config: dict[str, Any]) -> None:
        self._base_url = config.get("base_url", "https://erp.farmatic.local/api/v1")
        self._timeout = config.get("timeout", 45.0)
        super().configure(config)

    async def get_stock(self, pharmacy_id: UUID, medication_id: UUID | None = None, nregistro: str | None = None) -> ConnectorResult:
        try:
            params: dict[str, Any] = {"pharmacy": str(pharmacy_id)}
            if nregistro:
                params["nregistro"] = nregistro
            if medication_id:
                params["medication_id"] = str(medication_id)

            response = await self._request("GET", "/stock", params=params)
            data = response.json()

            self._record_metric("get_stock", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("get_stock", "error")
            logger.error("farmatic_get_stock_error", extra={"pharmacy_id": str(pharmacy_id), "error": str(exc)})
            return ConnectorResult(success=False, error=str(exc))

    async def reserve(self, pharmacy_id: UUID, medication_id: UUID, quantity: int, idempotency_key: str | None = None) -> ConnectorResult:
        try:
            payload: dict[str, Any] = {
                "pharmacy_id": str(pharmacy_id),
                "medication_id": str(medication_id),
                "quantity": quantity,
            }
            if idempotency_key:
                payload["idempotency_key"] = idempotency_key

            response = await self._request("POST", "/reservations", json=payload)
            data = response.json()

            self._record_metric("reserve", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("reserve", "error")
            logger.error("farmatic_reserve_error", extra={"pharmacy_id": str(pharmacy_id), "error": str(exc)})
            return ConnectorResult(success=False, error=str(exc))

    async def cancel_reservation(self, pharmacy_id: UUID, reservation_id: str) -> ConnectorResult:
        try:
            response = await self._request("DELETE", f"/reservations/{reservation_id}", json={"pharmacy_id": str(pharmacy_id)})
            data = response.json()

            self._record_metric("cancel_reservation", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("cancel_reservation", "error")
            logger.error("farmatic_cancel_error", extra={"reservation_id": reservation_id, "error": str(exc)})
            return ConnectorResult(success=False, error=str(exc))

    async def pharmacy_information(self, pharmacy_id: UUID) -> ConnectorResult:
        try:
            response = await self._request("GET", f"/pharmacies/{pharmacy_id}")
            data = response.json()

            self._record_metric("pharmacy_information", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("pharmacy_information", "error")
            logger.error("farmatic_pharmacy_info_error", extra={"pharmacy_id": str(pharmacy_id), "error": str(exc)})
            return ConnectorResult(success=False, error=str(exc))

    async def synchronize(self, pharmacy_id: UUID, strategy: str = "incremental", since: str | None = None) -> ConnectorResult:
        try:
            payload: dict[str, Any] = {
                "pharmacy_id": str(pharmacy_id),
                "strategy": strategy,
            }
            if since:
                payload["since"] = since

            response = await self._request("POST", "/sync", json=payload)
            data = response.json()

            self._record_metric("synchronize", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("synchronize", "error")
            logger.error("farmatic_sync_error", extra={"pharmacy_id": str(pharmacy_id), "error": str(exc)})
            return ConnectorResult(success=False, error=str(exc))

    async def heartbeat(self, pharmacy_id: UUID) -> ConnectorResult:
        try:
            response = await self._request("GET", "/health")
            data = response.json()
            data["connector_type"] = self.connector_type
            data["pharmacy_id"] = str(pharmacy_id)
            data["circuit_breaker"] = self._circuit_breaker.state.value

            self._record_metric("heartbeat", "success")
            return ConnectorResult(success=True, data=data)
        except Exception as exc:
            self._record_metric("heartbeat", "error")
            return ConnectorResult(
                success=False,
                error=str(exc),
                metadata={"circuit_breaker": self._circuit_breaker.state.value},
            )
