# app/modules/marketplace/schemas/letzshop.py
"""
Pydantic schemas for Letzshop marketplace integration.

Covers:
- Store credentials management
- Letzshop order import/sync
- Fulfillment queue operations
- Sync logs
"""

from datetime import datetime
from typing import Any

from pydantic import BaseModel, ConfigDict, Field

# ============================================================================
# Credentials Schemas
# ============================================================================


class LetzshopCredentialsCreate(BaseModel):
    """Schema for creating/updating Letzshop credentials."""

    api_key: str = Field(..., min_length=1, description="Letzshop API key")
    api_endpoint: str | None = Field(
        None,
        description="Custom API endpoint (defaults to https://letzshop.lu/graphql)",
    )
    auto_sync_enabled: bool = Field(False, description="Enable automatic order sync")
    sync_interval_minutes: int = Field(
        15, ge=5, le=1440, description="Sync interval in minutes (5-1440)"
    )
    test_mode_enabled: bool = Field(
        False, description="Test mode - disables API mutations"
    )
    default_carrier: str | None = Field(
        None, description="Default carrier (greco, colissimo, xpresslogistics)"
    )
    carrier_greco_label_url: str | None = Field(
        "https://dispatchweb.fr/Tracky/Home/", description="Greco label URL prefix"
    )
    carrier_colissimo_label_url: str | None = Field(
        None, description="Colissimo label URL prefix"
    )
    carrier_xpresslogistics_label_url: str | None = Field(
        None, description="XpressLogistics label URL prefix"
    )


class LetzshopCredentialsUpdate(BaseModel):
    """Schema for updating Letzshop credentials (partial update)."""

    api_key: str | None = Field(None, min_length=1)
    api_endpoint: str | None = None
    auto_sync_enabled: bool | None = None
    sync_interval_minutes: int | None = Field(None, ge=5, le=1440)
    test_mode_enabled: bool | None = None
    default_carrier: str | None = None
    carrier_greco_label_url: str | None = None
    carrier_colissimo_label_url: str | None = None
    carrier_xpresslogistics_label_url: str | None = None


class LetzshopCredentialsResponse(BaseModel):
    """Schema for Letzshop credentials response (API key is masked)."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    api_key_masked: str = Field(..., description="Masked API key for display")
    api_endpoint: str
    auto_sync_enabled: bool
    sync_interval_minutes: int
    test_mode_enabled: bool = False
    default_carrier: str | None = None
    carrier_greco_label_url: str | None = None
    carrier_colissimo_label_url: str | None = None
    carrier_xpresslogistics_label_url: str | None = None
    last_sync_at: datetime | None
    last_sync_status: str | None
    last_sync_error: str | None
    created_at: datetime
    updated_at: datetime


class LetzshopCredentialsStatus(BaseModel):
    """Schema for Letzshop connection status."""

    is_configured: bool
    is_connected: bool
    last_sync_at: datetime | None
    last_sync_status: str | None
    auto_sync_enabled: bool


# ============================================================================
# Letzshop Order Schemas (using unified Order model)
# ============================================================================


class LetzshopOrderItemResponse(BaseModel):
    """Schema for order item in Letzshop order response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    product_id: int
    product_name: str
    product_sku: str | None = None
    gtin: str | None = None
    gtin_type: str | None = None
    quantity: int
    unit_price: float
    total_price: float
    external_item_id: str | None = None  # Letzshop inventory unit ID
    external_variant_id: str | None = None
    item_state: str | None = None  # confirmed_available, confirmed_unavailable


class LetzshopOrderResponse(BaseModel):
    """Schema for Letzshop order response (from unified Order model)."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    store_name: str | None = None  # For cross-store views
    order_number: str

    # External references
    external_order_id: str | None = None
    external_shipment_id: str | None = None
    external_order_number: str | None = None

    # Status
    status: str  # pending, processing, shipped, delivered, cancelled

    # Customer info
    customer_email: str
    customer_name: str  # computed: customer_first_name + customer_last_name
    customer_locale: str | None = None

    # Address info
    ship_country_iso: str
    bill_country_iso: str

    # Financial
    total_amount: float
    currency: str = "EUR"

    # Tracking
    tracking_number: str | None = None
    tracking_provider: str | None = None

    # Timestamps
    order_date: datetime
    confirmed_at: datetime | None = None
    shipped_at: datetime | None = None
    cancelled_at: datetime | None = None
    created_at: datetime
    updated_at: datetime

    # Items (for list view, may be empty)
    items: list[LetzshopOrderItemResponse] = Field(default_factory=list)


class LetzshopOrderDetailResponse(LetzshopOrderResponse):
    """Schema for detailed Letzshop order response with all data."""

    # Full customer snapshot
    customer_first_name: str
    customer_last_name: str
    customer_phone: str | None = None

    # Full shipping address
    ship_first_name: str
    ship_last_name: str
    ship_company: str | None = None
    ship_address_line_1: str
    ship_address_line_2: str | None = None
    ship_city: str
    ship_postal_code: str

    # Full billing address
    bill_first_name: str
    bill_last_name: str
    bill_company: str | None = None
    bill_address_line_1: str
    bill_address_line_2: str | None = None
    bill_city: str
    bill_postal_code: str

    # Raw marketplace data
    external_data: dict[str, Any] | None = None

    # Notes
    customer_notes: str | None = None
    internal_notes: str | None = None


class LetzshopOrderStats(BaseModel):
    """Schema for order statistics by status."""

    pending: int = 0
    processing: int = 0
    shipped: int = 0
    delivered: int = 0
    cancelled: int = 0
    total: int = 0
    has_declined_items: int = 0  # Orders with at least one declined item


class LetzshopOrderListResponse(BaseModel):
    """Schema for paginated Letzshop order list."""

    orders: list[LetzshopOrderResponse]
    total: int
    skip: int
    limit: int
    stats: LetzshopOrderStats | None = None


# ============================================================================
# Fulfillment Schemas
# ============================================================================


class FulfillmentConfirmRequest(BaseModel):
    """Schema for confirming order fulfillment."""

    inventory_unit_ids: list[str] = Field(
        ..., min_length=1, description="List of inventory unit IDs to confirm"
    )


class FulfillmentRejectRequest(BaseModel):
    """Schema for rejecting order fulfillment."""

    inventory_unit_ids: list[str] = Field(
        ..., min_length=1, description="List of inventory unit IDs to reject"
    )
    reason: str | None = Field(None, max_length=500, description="Rejection reason")


class FulfillmentTrackingRequest(BaseModel):
    """Schema for setting tracking information."""

    tracking_number: str = Field(..., min_length=1, max_length=100)
    tracking_carrier: str = Field(
        ..., min_length=1, max_length=100, description="Carrier code (e.g., dhl, ups)"
    )


class FulfillmentQueueItemResponse(BaseModel):
    """Schema for fulfillment queue item response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    order_id: int  # FK to unified orders table
    operation: str
    payload: dict[str, Any]
    status: str
    attempts: int
    max_attempts: int
    last_attempt_at: datetime | None
    next_retry_at: datetime | None
    error_message: str | None
    completed_at: datetime | None
    response_data: dict[str, Any] | None
    created_at: datetime
    updated_at: datetime


class FulfillmentQueueListResponse(BaseModel):
    """Schema for paginated fulfillment queue list."""

    items: list[FulfillmentQueueItemResponse]
    total: int
    skip: int
    limit: int


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


class LetzshopSyncLogResponse(BaseModel):
    """Schema for Letzshop sync log response."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    operation_type: str
    direction: str
    status: str
    records_processed: int
    records_succeeded: int
    records_failed: int
    error_details: dict[str, Any] | None
    started_at: datetime
    completed_at: datetime | None
    duration_seconds: int | None
    triggered_by: str | None
    created_at: datetime


class LetzshopSyncLogListResponse(BaseModel):
    """Schema for paginated sync log list."""

    logs: list[LetzshopSyncLogResponse]
    total: int
    skip: int
    limit: int


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


class LetzshopSyncTriggerRequest(BaseModel):
    """Schema for triggering a sync operation."""

    operation: str = Field(
        "order_import",
        pattern="^(order_import|full_sync)$",
        description="Type of sync operation",
    )


class LetzshopSyncTriggerResponse(BaseModel):
    """Schema for sync trigger response."""

    success: bool
    message: str
    sync_log_id: int | None = None
    orders_imported: int = 0
    orders_updated: int = 0
    errors: list[str] = Field(default_factory=list)


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


class LetzshopConnectionTestRequest(BaseModel):
    """Schema for testing Letzshop connection."""

    api_key: str = Field(..., min_length=1, description="API key to test")
    api_endpoint: str | None = Field(None, description="Custom endpoint to test")


class LetzshopConnectionTestResponse(BaseModel):
    """Schema for connection test response."""

    success: bool
    message: str
    response_time_ms: float | None = None
    error_details: str | None = None


# ============================================================================
# Generic Response Schemas
# ============================================================================


class LetzshopSuccessResponse(BaseModel):
    """Generic success response for Letzshop operations."""

    success: bool
    message: str


class FulfillmentOperationResponse(BaseModel):
    """Response for fulfillment operations (confirm, reject, tracking)."""

    success: bool
    message: str
    confirmed_units: list[str] | None = None
    tracking_number: str | None = None
    tracking_carrier: str | None = None
    errors: list[str] | None = None


# ============================================================================
# Admin Overview Schemas
# ============================================================================


class LetzshopStoreOverview(BaseModel):
    """Schema for store Letzshop integration overview (admin view)."""

    store_id: int
    store_name: str
    store_code: str
    is_configured: bool
    auto_sync_enabled: bool
    last_sync_at: datetime | None
    last_sync_status: str | None
    pending_orders: int
    total_orders: int


class LetzshopStoreListResponse(BaseModel):
    """Schema for paginated store Letzshop overview list."""

    stores: list[LetzshopStoreOverview]
    total: int
    skip: int
    limit: int


# ============================================================================
# Jobs Schemas (Unified view of imports, exports, and syncs)
# ============================================================================


class LetzshopJobItem(BaseModel):
    """Schema for a unified job item (import, export, order sync, or historical import)."""

    id: int
    type: str = Field(
        ..., description="Job type: import, export, order_sync, or historical_import"
    )
    status: str = Field(..., description="Job status")
    created_at: datetime
    started_at: datetime | None = None
    completed_at: datetime | None = None
    records_processed: int = 0
    records_succeeded: int = 0
    records_failed: int = 0
    # Store info
    store_id: int | None = Field(None, description="Store ID")
    store_name: str | None = Field(None, description="Store name")
    store_code: str | None = Field(None, description="Store code")
    # Historical import specific fields
    current_phase: str | None = Field(
        None, description="Current phase for historical imports"
    )
    error_message: str | None = Field(None, description="Error message if failed")
    error_details: dict[str, Any] | None = Field(
        None, description="Error details or export file info"
    )


class LetzshopJobsListResponse(BaseModel):
    """Schema for paginated jobs list."""

    jobs: list[LetzshopJobItem]
    total: int


# ============================================================================
# Historical Import Job Schemas
# ============================================================================


class LetzshopHistoricalImportJobResponse(BaseModel):
    """Schema for historical import job status (polling endpoint)."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    store_id: int
    status: str  # pending, fetching, processing, completed, failed
    current_phase: str | None = None  # "confirmed" or "declined"

    # Fetch progress
    current_page: int = 0
    total_pages: int | None = None
    shipments_fetched: int = 0

    # Processing progress
    orders_processed: int = 0
    orders_imported: int = 0
    orders_updated: int = 0
    orders_skipped: int = 0

    # EAN matching stats
    products_matched: int = 0
    products_not_found: int = 0

    # Phase-specific stats (when complete)
    confirmed_stats: dict[str, Any] | None = None
    declined_stats: dict[str, Any] | None = None

    # Error handling
    error_message: str | None = None

    # Timing
    started_at: datetime | None = None
    completed_at: datetime | None = None
    created_at: datetime
    updated_at: datetime


class LetzshopHistoricalImportStartResponse(BaseModel):
    """Schema for starting a historical import job."""

    job_id: int
    status: str = "pending"
    message: str = "Historical import job started"


# ============================================================================
# Store Directory Schemas (Letzshop Marketplace Cache)
# ============================================================================


class LetzshopCachedStoreItem(BaseModel):
    """Schema for a cached Letzshop store in list view."""

    id: int
    letzshop_id: str
    slug: str
    name: str
    merchant_name: str | None = None
    email: str | None = None
    phone: str | None = None
    website: str | None = None
    city: str | None = None
    categories: list[str] = []
    is_active: bool = True
    is_claimed: bool = False
    claimed_by_store_id: int | None = None
    last_synced_at: datetime | None = None
    letzshop_url: str


class LetzshopCachedStoreDetail(BaseModel):
    """Schema for detailed cached Letzshop store."""

    id: int
    letzshop_id: str
    slug: str
    name: str
    merchant_name: str | None = None
    description_en: str | None = None
    description_fr: str | None = None
    description_de: str | None = None
    email: str | None = None
    phone: str | None = None
    fax: str | None = None
    website: str | None = None
    street: str | None = None
    street_number: str | None = None
    city: str | None = None
    zipcode: str | None = None
    country_iso: str | None = None
    latitude: str | None = None
    longitude: str | None = None
    categories: list[str] = []
    background_image_url: str | None = None
    social_media_links: list[str] = []
    opening_hours_en: str | None = None
    opening_hours_fr: str | None = None
    opening_hours_de: str | None = None
    representative_name: str | None = None
    representative_title: str | None = None
    is_active: bool = True
    is_claimed: bool = False
    claimed_by_store_id: int | None = None
    claimed_at: datetime | None = None
    last_synced_at: datetime | None = None
    letzshop_url: str


class LetzshopStoreDirectoryStats(BaseModel):
    """Schema for store directory cache statistics."""

    total_stores: int = 0
    active_stores: int = 0
    claimed_stores: int = 0
    unclaimed_stores: int = 0
    unique_cities: int = 0
    last_synced_at: str | None = None


class LetzshopStoreDirectoryStatsResponse(BaseModel):
    """Response schema for store directory stats endpoint."""

    success: bool = True
    stats: LetzshopStoreDirectoryStats


class LetzshopCachedStoreListResponse(BaseModel):
    """Response schema for store directory list endpoint."""

    success: bool = True
    stores: list[LetzshopCachedStoreItem]
    total: int
    page: int
    limit: int
    has_more: bool


class LetzshopCachedStoreDetailResponse(BaseModel):
    """Response schema for store directory detail endpoint."""

    success: bool = True
    store: LetzshopCachedStoreDetail


class LetzshopStoreDirectorySyncResponse(BaseModel):
    """Response schema for store directory sync trigger."""

    success: bool = True
    message: str
    task_id: str | None = None
    mode: str = "celery"


class LetzshopCreateStoreFromCacheResponse(BaseModel):
    """Response schema for creating store from Letzshop cache."""

    success: bool = True
    message: str
    store: dict[str, Any] | None = None
    letzshop_store_slug: str


# ============================================================================
# Product Export Schemas
# ============================================================================


class LetzshopExportRequest(BaseModel):
    """Request body for Letzshop export to pickup folder."""

    include_inactive: bool = Field(
        default=False,
        description="Include inactive products in export"
    )


class LetzshopExportFileInfo(BaseModel):
    """Info about an exported file."""

    language: str
    filename: str | None = None
    path: str | None = None
    size_bytes: int | None = None
    error: str | None = None


class LetzshopExportResponse(BaseModel):
    """Response from Letzshop export to folder."""

    success: bool
    message: str
    store_code: str
    export_directory: str
    files: list[LetzshopExportFileInfo]
    celery_task_id: str | None = None  # Set when using Celery async export
    is_async: bool = Field(default=False, serialization_alias="async")  # True when queued via Celery

    model_config = ConfigDict(populate_by_name=True)
