from datetime import date, datetime
from decimal import Decimal
from typing import Literal

from pydantic import BaseModel, ConfigDict, Field


class ShipmentBase(BaseModel):
    reference: str | None = Field(None, max_length=40)
    quote_id: int | None = None
    service_request_id: int | None = None
    account_id: int | None = None
    operation_type: str | None = Field(None, max_length=20)
    transport_mode: str | None = Field(None, max_length=20)
    service_type: str | None = Field(None, max_length=20)
    incoterm: str | None = Field(None, max_length=10)
    origin: str | None = Field(None, max_length=160)
    destination: str | None = Field(None, max_length=160)
    status: str = Field("abierta", max_length=20)
    booking_number: str | None = Field(None, max_length=60)
    carrier_supplier_id: int | None = None
    ground_carrier_supplier_id: int | None = None
    customs_agent_id: int | None = None
    destination_agent_id: int | None = None
    cutoff_date: datetime | None = None
    pickup_at: datetime | None = None
    etd: date | None = None
    previous_etd: date | None = None
    eta: date | None = None
    vessel_flight: str | None = Field(None, max_length=120)
    container_number: str | None = Field(None, max_length=60)
    notes: str | None = None
    actual_cost_total: Decimal | None = None
    cost_currency: str | None = Field(None, max_length=3)
    owner_user_id: str | None = Field(None, max_length=64)


class ShipmentCreate(ShipmentBase):
    pass


class ShipmentUpdate(BaseModel):
    reference: str | None = Field(None, max_length=40)
    account_id: int | None = None
    operation_type: str | None = Field(None, max_length=20)
    transport_mode: str | None = Field(None, max_length=20)
    service_type: str | None = Field(None, max_length=20)
    incoterm: str | None = Field(None, max_length=10)
    origin: str | None = Field(None, max_length=160)
    destination: str | None = Field(None, max_length=160)
    status: str | None = Field(None, max_length=20)
    booking_number: str | None = Field(None, max_length=60)
    carrier_supplier_id: int | None = None
    ground_carrier_supplier_id: int | None = None
    customs_agent_id: int | None = None
    destination_agent_id: int | None = None
    cutoff_date: datetime | None = None
    pickup_at: datetime | None = None
    etd: date | None = None
    eta: date | None = None
    vessel_flight: str | None = Field(None, max_length=120)
    container_number: str | None = Field(None, max_length=60)
    notes: str | None = None
    owner_user_id: str | None = Field(None, max_length=64)


class ShipmentRescheduleInput(BaseModel):
    """Reprogramación de salida cuando no se alcanza el Cut Off (R-E-06)."""
    etd: date | None = None
    cutoff_date: datetime | None = None
    reason: str | None = None


class ShipmentCloseInput(BaseModel):
    """Cierre operativo del embarque con costos finales (R-E-22)."""
    actual_cost_total: Decimal = Field(..., ge=0)
    cost_currency: str = Field("MXN", max_length=3)
    notes: str | None = None


class ShipmentResponse(ShipmentBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    case_id: int | None = None
    closed_at: datetime | None = None
    closed_by: str | None = None
    created_by: str | None = None
    updated_by: str | None = None
    tenant_id: int
    company_id: int
    created_at: datetime
    updated_at: datetime


class ShipmentEventBase(BaseModel):
    shipment_id: int
    event_type: str | None = Field(None, max_length=60)
    title: str = Field(..., min_length=1, max_length=160)
    kind: str = Field("hito", max_length=20)  # hito | decision
    status: str = Field("pendiente", max_length=20)
    outcome: str | None = Field(None, max_length=20)  # autorizado | rechazado
    parent_event_id: int | None = None
    attempt: int = Field(1, ge=1)
    position: int = Field(0, ge=0)
    planned_date: datetime | None = None
    actual_date: datetime | None = None
    notes: str | None = None


class ShipmentEventCreate(ShipmentEventBase):
    pass


class ShipmentEventUpdate(BaseModel):
    event_type: str | None = Field(None, max_length=60)
    title: str | None = Field(None, min_length=1, max_length=160)
    kind: str | None = Field(None, max_length=20)
    status: str | None = Field(None, max_length=20)
    position: int | None = Field(None, ge=0)
    planned_date: datetime | None = None
    actual_date: datetime | None = None
    notes: str | None = None


class ShipmentEventDecisionInput(BaseModel):
    """Resultado de un punto de decisión del flujo (R-E-13, R-E-05, R-I-06)."""
    outcome: Literal["autorizado", "rechazado"]
    notes: str | None = None


class ShipmentEventResponse(ShipmentEventBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    tenant_id: int
    company_id: int
    created_at: datetime
    updated_at: datetime


class ShipmentDocumentBase(BaseModel):
    shipment_id: int
    doc_kind: str = Field("otro", max_length=10)
    doc_type: str = Field(..., max_length=30)
    number: str | None = Field(None, max_length=80)
    issue_date: date | None = None
    file_url: str | None = Field(None, max_length=1024)
    file_key: str | None = Field(None, max_length=512)
    notes: str | None = None


class ShipmentDocumentCreate(ShipmentDocumentBase):
    pass


class ShipmentDocumentUpdate(BaseModel):
    doc_kind: str | None = Field(None, max_length=10)
    doc_type: str | None = Field(None, max_length=30)
    number: str | None = Field(None, max_length=80)
    issue_date: date | None = None
    file_url: str | None = Field(None, max_length=1024)
    file_key: str | None = Field(None, max_length=512)
    notes: str | None = None


class ShipmentDocumentResponse(ShipmentDocumentBase):
    model_config = ConfigDict(from_attributes=True)

    id: int
    tenant_id: int
    company_id: int
    created_at: datetime
    updated_at: datetime
