from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field


class SyncEventPayload(BaseModel):
    outbox_id: Optional[str] = None
    entity_type: str
    entity_id: str
    operation: str = "upsert"
    payload: Optional[Dict[str, Any]] = None


class SyncIngestRequest(BaseModel):
    events: List[SyncEventPayload] = Field(default_factory=list)


class SyncIngestResponse(BaseModel):
    message: str
    applied: List[Dict[str, Any]] = Field(default_factory=list)
    failed: List[Dict[str, Any]] = Field(default_factory=list)


class SyncStatusResponse(BaseModel):
    enabled: bool
    """lan_client = push from this server; cloud_hub = receive from LAN nodes; disabled = sync off or wrong mode."""
    ui_mode: str = "disabled"
    realtime_enabled: bool
    cloud_url: Optional[str] = None
    node_id: Optional[str] = None
    node_configured: bool
    pending_events: int
    failed_events: int
    deployment_mode: str
    cloud_sync_master_enabled: bool = True
    registered_nodes: int = 0
    message: Optional[str] = None
    license_key_configured: bool = False


class SyncProvisionMirrorRequest(BaseModel):
    license_key: Optional[str] = Field(
        None,
        description="Required if not already in deploy/license-node.json",
    )
    public_base_url: Optional[str] = Field(
        None,
        description="Optional LAN URL shown on cloud hub (e.g. http://192.168.1.10:8010)",
    )


class SyncProvisionMirrorResponse(BaseModel):
    success: bool
    message: str
    cloud_login_url: Optional[str] = None
    node_configured: bool = False


class SyncRunResponse(BaseModel):
    success: bool
    message: str
    pushed: int = 0
    failed: int = 0


class SyncSettingsPatch(BaseModel):
    realtime_enabled: Optional[bool] = None
