import uuid
from datetime import datetime
from enum import Enum

from pydantic import BaseModel, Field


class PharmacyStatus(str, Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"
    SUSPENDED = "suspended"
    PENDING = "pending"


class ERPType(str, Enum):
    FARMATIC = "farmatic"
    NIXFARMA = "nixfarma"
    UNYCOP = "unycop"
    CUSTOM_REST = "custom_rest"
    CUSTOM_SOAP = "custom_soap"
    CSV = "csv"
    FTP = "ftp"
    SQL = "sql"
    MOCK = "mock"


class ConnectorStatus(str, Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"
    ERROR = "error"
    PENDING = "pending"
    UPDATING = "updating"


class SyncStrategy(str, Enum):
    FULL = "full"
    INCREMENTAL = "incremental"
    EVENT_DRIVEN = "event_driven"
    SCHEDULED = "scheduled"
    HYBRID = "hybrid"


class SyncJobStatus(str, Enum):
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


class ReservationStatus(str, Enum):
    PENDING = "pending"
    CONFIRMED = "confirmed"
    CANCELLED = "cancelled"
    EXPIRED = "expired"


class UserRole(str, Enum):
    SUPERADMIN = "superadmin"
    ADMIN = "admin"
    OPERATOR = "operator"
    VIEWER = "viewer"
    API_CLIENT = "api_client"


class PharmacyEntity(BaseModel):
    id: uuid.UUID | None = None
    code: str
    name: str
    address: str | None = None
    city: str | None = None
    province: str | None = None
    postal_code: str | None = None
    country: str = "ES"
    latitude: float | None = None
    longitude: float | None = None
    phone: str | None = None
    email: str | None = None
    opening_hours: dict | None = None
    status: PharmacyStatus = PharmacyStatus.PENDING
    erp_type: ERPType | None = None
    erp_version: str | None = None
    connector_id: uuid.UUID | None = None
    sync_strategy: SyncStrategy = SyncStrategy.INCREMENTAL
    sync_interval_minutes: int = 30
    last_sync_at: datetime | None = None
    last_sync_status: SyncJobStatus | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class ERPSystemEntity(BaseModel):
    id: uuid.UUID | None = None
    name: str
    erp_type: ERPType
    version: str | None = None
    base_url: str | None = None
    auth_config: dict | None = None
    status: ConnectorStatus = ConnectorStatus.PENDING
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class ConnectorEntity(BaseModel):
    id: uuid.UUID | None = None
    erp_system_id: uuid.UUID
    pharmacy_id: uuid.UUID
    name: str
    connector_type: ERPType
    version: str = "1.0.0"
    config: dict | None = None
    status: ConnectorStatus = ConnectorStatus.PENDING
    last_heartbeat_at: datetime | None = None
    last_error: str | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class ConnectorVersionEntity(BaseModel):
    id: uuid.UUID | None = None
    connector_id: uuid.UUID | None = None
    connector_type: ERPType
    version: str
    changelog: str | None = None
    download_url: str | None = None
    checksum: str | None = None
    is_latest: bool = False
    is_required: bool = False
    released_at: datetime | None = None
    created_at: datetime | None = None


class ConnectorConfigEntity(BaseModel):
    id: uuid.UUID | None = None
    connector_id: uuid.UUID
    key: str
    value: str
    encrypted: bool = False
    description: str | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class MedicationEntity(BaseModel):
    id: uuid.UUID | None = None
    nregistro: str
    name: str
    active_ingredient: str | None = None
    dosage: str | None = None
    form: str | None = None
    atc_code: str | None = None
    prescription_required: bool = False
    manufacturer: str | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class MedicationCatalogEntryEntity(BaseModel):
    id: uuid.UUID | None = None
    pharmacy_id: uuid.UUID
    medication_id: uuid.UUID
    price: float | None = None
    stock: int = 0
    is_available: bool = False
    last_verified_at: datetime | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class InventoryRecordEntity(BaseModel):
    id: uuid.UUID | None = None
    pharmacy_id: uuid.UUID
    medication_id: uuid.UUID
    stock: int = 0
    reserved_stock: int = 0
    available_stock: int = 0
    min_stock: int | None = None
    max_stock: int | None = None
    last_updated_at: datetime | None = None
    source: str | None = None
    batch_id: str | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class InventoryHistoryEntity(BaseModel):
    id: uuid.UUID | None = None
    inventory_record_id: uuid.UUID | None = None
    pharmacy_id: uuid.UUID
    medication_id: uuid.UUID
    previous_stock: int
    new_stock: int
    delta: int
    reason: str | None = None
    source: str | None = None
    created_at: datetime | None = None


class ReservationEntity(BaseModel):
    id: uuid.UUID | None = None
    pharmacy_id: uuid.UUID
    medication_id: uuid.UUID
    user_id: uuid.UUID | None = None
    external_reference: str | None = None
    quantity: int
    status: ReservationStatus = ReservationStatus.PENDING
    expires_at: datetime | None = None
    confirmed_at: datetime | None = None
    cancelled_at: datetime | None = None
    idempotency_key: str | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class SyncJobEntity(BaseModel):
    id: uuid.UUID | None = None
    pharmacy_id: uuid.UUID
    connector_id: uuid.UUID
    strategy: SyncStrategy
    status: SyncJobStatus = SyncJobStatus.PENDING
    started_at: datetime | None = None
    completed_at: datetime | None = None
    items_total: int | None = None
    items_processed: int | None = None
    items_failed: int | None = None
    error_message: str | None = None
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class SyncLogEntity(BaseModel):
    id: uuid.UUID | None = None
    sync_job_id: uuid.UUID
    level: str = "INFO"
    message: str
    details: dict | None = None
    created_at: datetime | None = None


class AuditLogEntity(BaseModel):
    id: uuid.UUID | None = None
    actor_id: uuid.UUID | None = None
    actor_type: str | None = None
    action: str
    resource_type: str
    resource_id: str | None = None
    old_value: dict | None = None
    new_value: dict | None = None
    ip_address: str | None = None
    user_agent: str | None = None
    request_id: str | None = None
    created_at: datetime | None = None


class TechnicalUserEntity(BaseModel):
    id: uuid.UUID | None = None
    username: str
    email: str | None = None
    full_name: str | None = None
    role: UserRole = UserRole.VIEWER
    is_active: bool = True
    scopes: list[str] = Field(default_factory=list)
    last_login_at: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class APIClientEntity(BaseModel):
    id: uuid.UUID | None = None
    name: str
    description: str | None = None
    owner_id: uuid.UUID | None = None
    is_active: bool = True
    scopes: list[str] = Field(default_factory=list)
    rate_limit: int | None = None
    allowed_ips: list[str] = Field(default_factory=list)
    metadata_: dict | None = Field(default=None, alias="metadata")
    created_at: datetime | None = None
    updated_at: datetime | None = None

    model_config = {"populate_by_name": True}


class APIKeyEntity(BaseModel):
    id: uuid.UUID | None = None
    api_client_id: uuid.UUID
    key_prefix: str
    key_hash: bytes
    name: str
    is_active: bool = True
    expires_at: datetime | None = None
    last_used_at: datetime | None = None
    created_at: datetime | None = None
