"""
QuickBooks Online (QBO) API schemas.

These schemas provide type-safe request/response structures for
QBO connection management and data synchronization.

Usage:
    from lightwave.schema.pydantic.contracts.api.accounting import (
        QBOConnectionSchema,
        QBOConnectionListResponse,
        QBOSyncResponse,
    )

    @router.get("/connections/", response=QBOConnectionListResponse)
    def list_qbo_connections(request):
        connections = QBOConnection.objects.filter(team=request.user.team)
        return QBOConnectionListResponse(
            connections=[QBOConnectionSchema.model_validate(c) for c in connections]
        )
"""

from datetime import datetime
from typing import Any, Literal

from pydantic import Field

from lightwave.schema.pydantic.core.base import (
    APIRequestSchema,
    APIResponseSchema,
    LightwaveBaseSchema,
)

# =============================================================================
# Enums as Type Literals (derived from QBO API)
# =============================================================================

QBOEntityType = Literal[
    "Customer",
    "Invoice",
    "Payment",
    "Vendor",
    "Bill",
    "Estimate",
    "PurchaseOrder",
    "Item",
    "Account",
    "Employee",
    "TimeActivity",
    "JournalEntry",
    "CreditMemo",
    "SalesReceipt",
    "RefundReceipt",
    "Deposit",
    "Transfer",
    "Class",
    "Department",
    "TaxCode",
    "TaxRate",
]

QBOSyncStatus = Literal[
    "queued",
    "running",
    "completed",
    "failed",
    "cancelled",
    "partial",
]


# =============================================================================
# Connection Schemas
# =============================================================================


class QBOConnectionSchema(APIResponseSchema):
    """
    QuickBooks Online connection details.

    Represents an authenticated connection to a QBO company.
    Tokens are never exposed - only connection status and metadata.

    Example response:
        {
            "id": 1,
            "realm_id": "123456789",
            "company_name": "Acme Corp",
            "connected_at": "2024-01-15T10:30:00Z",
            "expires_at": "2024-04-15T10:30:00Z",
            "is_active": true,
            "last_sync_at": "2024-01-20T08:00:00Z",
            "sync_enabled": true
        }
    """

    realm_id: str = Field(..., description="QBO company ID (realm)")
    company_name: str = Field(..., description="QBO company display name")
    connected_at: datetime = Field(..., description="When connection was established")
    expires_at: datetime = Field(..., description="When OAuth tokens expire")
    is_active: bool = Field(..., description="Whether connection is active")
    last_sync_at: datetime | None = Field(None, description="Last successful sync")
    sync_enabled: bool = Field(True, description="Whether auto-sync is enabled")
    webhook_enabled: bool = Field(False, description="Whether webhooks are configured")
    environment: Literal["sandbox", "production"] = Field("production", description="QBO environment")


class QBOConnectionListResponse(APIResponseSchema):
    """
    List of QBO connections for a team.

    Example response:
        {
            "connections": [...],
            "total": 2
        }
    """

    id: int | None = None  # Override - list response
    created_at: datetime | None = None  # Override
    updated_at: datetime | None = None  # Override

    connections: list[QBOConnectionSchema] = Field(default_factory=list, description="QBO connections")
    total: int = Field(0, ge=0, description="Total number of connections")


class QBODisconnectRequest(APIRequestSchema):
    """
    Request to disconnect a QBO connection.

    Example:
        POST /api/accounting/connections/123/disconnect/
        {"revoke_tokens": true}
    """

    revoke_tokens: bool = Field(True, description="Whether to revoke OAuth tokens at QBO")


# =============================================================================
# Sync Schemas
# =============================================================================


class QBOEntitySyncRequest(APIRequestSchema):
    """
    Request to sync specific QBO entities.

    Example:
        POST /api/accounting/sync/
        {
            "entities": ["Customer", "Invoice"],
            "full_sync": false,
            "since": "2024-01-15T00:00:00Z"
        }
    """

    entities: list[QBOEntityType] = Field(
        default_factory=list,
        description="Entity types to sync (empty = all)",
    )
    full_sync: bool = Field(False, description="Force full sync instead of incremental")
    since: datetime | None = Field(None, description="Sync changes since this timestamp")
    dry_run: bool = Field(False, description="Preview changes without applying")


class QBOSyncProgressSchema(LightwaveBaseSchema):
    """
    Progress details for a sync operation.

    Provides real-time progress information during a sync.
    """

    entity_type: QBOEntityType = Field(..., description="Entity being synced")
    total: int = Field(0, ge=0, description="Total items to process")
    processed: int = Field(0, ge=0, description="Items processed so far")
    created: int = Field(0, ge=0, description="Items created")
    updated: int = Field(0, ge=0, description="Items updated")
    skipped: int = Field(0, ge=0, description="Items skipped (no changes)")
    failed: int = Field(0, ge=0, description="Items that failed")

    @property
    def progress_percent(self) -> float:
        """Calculate progress percentage."""
        if self.total == 0:
            return 100.0
        return (self.processed / self.total) * 100


class QBOSyncResponse(APIResponseSchema):
    """
    Response for QBO sync operations.

    Provides status and progress for async sync operations.

    Example response:
        {
            "status": "running",
            "task_id": "abc-123-def",
            "started_at": "2024-01-20T10:30:00Z",
            "progress": [
                {"entity_type": "Customer", "total": 100, "processed": 50, ...},
                {"entity_type": "Invoice", "total": 200, "processed": 0, ...}
            ],
            "entities_synced": 50
        }
    """

    id: int | None = None  # Override
    created_at: datetime | None = None  # Override
    updated_at: datetime | None = None  # Override

    status: QBOSyncStatus = Field(..., description="Current sync status")
    task_id: str | None = Field(None, description="Celery task ID for tracking")
    started_at: datetime | None = Field(None, description="When sync started")
    completed_at: datetime | None = Field(None, description="When sync completed")
    progress: list[QBOSyncProgressSchema] = Field(default_factory=list, description="Per-entity progress")
    entities_synced: int = Field(0, ge=0, description="Total entities synced")
    errors: list[dict[str, Any]] = Field(default_factory=list, description="Sync errors encountered")
    dry_run: bool = Field(False, description="Whether this was a dry run")


class QBOSyncHistorySchema(APIResponseSchema):
    """
    Historical sync record.

    Used for displaying sync history in the UI.
    """

    status: QBOSyncStatus = Field(..., description="Final sync status")
    started_at: datetime = Field(..., description="When sync started")
    completed_at: datetime | None = Field(None, description="When sync completed")
    duration_seconds: int | None = Field(None, description="Sync duration")
    entities_synced: int = Field(0, description="Total entities synced")
    error_count: int = Field(0, description="Number of errors")
    triggered_by: str | None = Field(None, description="User or 'webhook' or 'scheduled'")
