from abc import ABC, abstractmethod
from typing import Any
from uuid import UUID

from pydantic import BaseModel


class ConnectorResult(BaseModel):
    success: bool
    data: Any | None = None
    error: str | None = None
    metadata: dict | None = None


class StockInfo(BaseModel):
    medication_id: UUID
    nregistro: str
    name: str
    stock: int
    reserved_stock: int = 0
    available_stock: int = 0
    price: float | None = None
    last_updated: str | None = None


class PharmacyInfo(BaseModel):
    pharmacy_id: UUID
    code: str
    name: str
    address: str | None = None
    phone: str | None = None
    email: str | None = None
    opening_hours: dict | None = None
    latitude: float | None = None
    longitude: float | None = None


class SyncResult(BaseModel):
    success: bool
    items_total: int = 0
    items_processed: int = 0
    items_failed: int = 0
    error_message: str | None = None
    metadata: dict | None = None


class ReservationResult(BaseModel):
    success: bool
    reservation_id: str | None = None
    error: str | None = None


class BaseInventoryConnector(ABC):
    connector_type: str = "base"

    @abstractmethod
    async def get_stock(self, pharmacy_id: UUID, medication_id: UUID | None = None, nregistro: str | None = None) -> ConnectorResult:
        ...

    @abstractmethod
    async def reserve(self, pharmacy_id: UUID, medication_id: UUID, quantity: int, idempotency_key: str | None = None) -> ConnectorResult:
        ...

    @abstractmethod
    async def cancel_reservation(self, pharmacy_id: UUID, reservation_id: str) -> ConnectorResult:
        ...

    @abstractmethod
    async def pharmacy_information(self, pharmacy_id: UUID) -> ConnectorResult:
        ...

    @abstractmethod
    async def synchronize(self, pharmacy_id: UUID, strategy: str = "incremental", since: str | None = None) -> ConnectorResult:
        ...

    @abstractmethod
    async def heartbeat(self, pharmacy_id: UUID) -> ConnectorResult:
        ...
