from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import List, Optional
from datetime import datetime
from odoo import api
from odoo.addons.fastapi.dependencies import odoo_env


# Pydantic схемы
class CarrierSchema(BaseModel):
    uuid: str
    name: str
    team_name: str
    tax_id: Optional[str] = None
    country: Optional[str] = None
    country_code: Optional[str] = None
    state: str


class TripSchema(BaseModel):
    uuid: str
    name: str
    sequence: int
    carrier: Optional[CarrierSchema] = None
    planned_loading_date: Optional[datetime] = None
    actual_loading_date: Optional[datetime] = None
    planned_unloading_date: Optional[datetime] = None
    actual_unloading_date: Optional[datetime] = None
    real_loading_date: Optional[datetime] = None
    planned_weight: Optional[float] = None
    weight_at_loading: Optional[float] = None
    weight_at_unloading: Optional[float] = None


class StageSchema(BaseModel):
    uuid: str
    name: str
    sequence: int
    stage_type: str  # transport/service
    transport_type: Optional[str] = None  # auto/rail/sea/air
    source_location_name: Optional[str] = None
    source_latitude: Optional[float] = None
    source_longitude: Optional[float] = None
    destination_location_name: Optional[str] = None
    destination_latitude: Optional[float] = None
    destination_longitude: Optional[float] = None
    location_name: Optional[str] = None  # for service stages
    location_latitude: Optional[float] = None
    location_longitude: Optional[float] = None
    selected_carrier: Optional[CarrierSchema] = None
    trips: List[TripSchema] = []


class OrderLineSchema(BaseModel):
    uuid: str
    product_uuid: str
    product_name: str
    quantity: float
    unit: str
    price_unit: float
    subtotal: float
    currency: str
    notes: Optional[str] = None


class OrderTrackingSchema(BaseModel):
    uuid: str
    timestamp: datetime
    description: Optional[str] = None
    location_name: Optional[str] = None
    location_uuid: Optional[str] = None
    carrier_name: Optional[str] = None
    tracking_number: Optional[str] = None


class OrderSchema(BaseModel):
    uuid: str
    name: str
    team_uuid: str
    user_id: str
    source_location_uuid: str
    source_location_name: str
    destination_location_uuid: str
    destination_location_name: str
    total_amount: float
    currency: str
    created_at: datetime
    updated_at: datetime
    notes: Optional[str] = None
    order_lines: List[OrderLineSchema] = []
    stages: List[StageSchema] = []
    tracking_events: List[OrderTrackingSchema] = []


class CreateOrderLineInput(BaseModel):
    product_uuid: str
    quantity: float
    unit: str
    notes: Optional[str] = None


class CreateOrderInput(BaseModel):
    team_uuid: str
    user_id: str
    source_location_uuid: str
    destination_location_uuid: str
    order_lines: List[CreateOrderLineInput]
    notes: Optional[str] = None


router = APIRouter(tags=["orders"])


def build_carrier_schema(carrier) -> CarrierSchema:
    """Построить схему перевозчика"""
    return CarrierSchema(
        uuid=carrier.uuid,
        name=carrier.name,
        team_name=carrier.team_name,
        tax_id=carrier.tax_id if carrier.tax_id else None,
        country=carrier.country_id.name if carrier.country_id else None,
        country_code=carrier.country_id.code if carrier.country_id else None,
        state=carrier.state
    )


def build_trip_schema(trip) -> TripSchema:
    """Построить схему рейса"""
    return TripSchema(
        uuid=trip.uuid,
        name=trip.name,
        sequence=trip.sequence,
        carrier=build_carrier_schema(trip.carrier_id) if trip.carrier_id else None,
        planned_loading_date=trip.planned_loading_date or None,
        actual_loading_date=trip.actual_loading_date or None,
        planned_unloading_date=trip.planned_unloading_date or None,
        actual_unloading_date=trip.actual_unloading_date or None,
        real_loading_date=trip.real_loading_date or None,
        planned_weight=trip.planned_weight or None,
        weight_at_loading=trip.weight_at_loading or None,
        weight_at_unloading=trip.weight_at_unloading or None
    )


def build_stage_schema(stage) -> StageSchema:
    """Построить схему этапа"""
    # Собираем рейсы
    trips = [build_trip_schema(trip) for trip in stage.trip_ids.sorted('sequence')]
    
    return StageSchema(
        uuid=stage.uuid,
        name=stage.name,
        sequence=stage.sequence,
        stage_type=stage.stage_type,
        transport_type=stage.transport_type if stage.transport_type else None,
        source_location_name=stage.source_location_id.name if stage.source_location_id else None,
        source_latitude=stage.source_location_id.latitude if stage.source_location_id else None,
        source_longitude=stage.source_location_id.longitude if stage.source_location_id else None,
        destination_location_name=stage.destination_location_id.name if stage.destination_location_id else None,
        destination_latitude=stage.destination_location_id.latitude if stage.destination_location_id else None,
        destination_longitude=stage.destination_location_id.longitude if stage.destination_location_id else None,
        location_name=stage.location_id.name if stage.location_id else None,
        location_latitude=stage.location_id.latitude if stage.location_id else None,
        location_longitude=stage.location_id.longitude if stage.location_id else None,
        selected_carrier=build_carrier_schema(stage.selected_carrier_id) if stage.selected_carrier_id else None,
        trips=trips
    )


@router.get("/orders/team/{team_uuid}", response_model=List[OrderSchema])
async def get_team_orders(team_uuid: str, env: api.Environment = Depends(odoo_env)):
    """Получить все заказы команды"""
    try:
        orders = env['marketplace.order'].search([('team_uuid', '=', team_uuid)])
        
        result = []
        for order in orders:
            # Собираем данные о позициях заказа
            order_lines = []
            for line in order.order_lines:
                order_lines.append(OrderLineSchema(
                    uuid=line.uuid,
                    product_uuid=line.product_id.uuid,
                    product_name=line.product_id.name,
                    quantity=line.quantity,
                    unit=line.unit,
                    price_unit=line.price_unit,
                    subtotal=line.subtotal,
                    currency=line.currency_id.name,
                    notes=line.notes or None
                ))
            
            # Собираем события трекинга
            tracking_events = []
            for event in order.tracking_events:
                tracking_events.append(OrderTrackingSchema(
                    uuid=event.uuid,
                    status=event.status,
                    timestamp=event.timestamp,
                    description=event.description or None,
                    location_name=event.location_id.name if event.location_id else None,
                    location_uuid=event.location_id.uuid if event.location_id else None,
                    carrier_name=event.carrier_name or None,
                    tracking_number=event.tracking_number or None
                ))
            
            # Собираем этапы
            stages = [build_stage_schema(stage) for stage in order.stage_ids.sorted('sequence')]
            
            result.append(OrderSchema(
                uuid=order.uuid,
                name=order.name,
                team_uuid=order.team_uuid,
                user_id=order.user_id,
                source_location_uuid=order.source_location_id.uuid,
                source_location_name=order.source_location_id.name,
                destination_location_uuid=order.destination_location_id.uuid,
                destination_location_name=order.destination_location_id.name,
                total_amount=order.total_amount,
                currency=order.currency_id.name,
                created_at=order.created_at,
                updated_at=order.updated_at,
                notes=order.notes or None,
                order_lines=order_lines,
                stages=stages,
                tracking_events=tracking_events
            ))
        
        return result
    
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error fetching team orders: {str(e)}")


@router.get("/orders/{order_uuid}", response_model=OrderSchema)
async def get_order_by_uuid(order_uuid: str, env: api.Environment = Depends(odoo_env)):
    """Получить заказ по UUID"""
    try:
        order = env['marketplace.order'].search([('uuid', '=', order_uuid)], limit=1)
        
        if not order:
            raise HTTPException(status_code=404, detail="Order not found")
        
        # Собираем данные аналогично get_team_orders
        order_lines = []
        for line in order.order_lines:
            order_lines.append(OrderLineSchema(
                uuid=line.uuid,
                product_uuid=line.product_id.uuid,
                product_name=line.product_id.name,
                quantity=line.quantity,
                unit=line.unit,
                price_unit=line.price_unit,
                subtotal=line.subtotal,
                currency=line.currency_id.name,
                notes=line.notes or None
            ))

        tracking_events = []
        for event in order.tracking_events:
            tracking_events.append(OrderTrackingSchema(
                uuid=event.uuid,
                status=event.status,
                timestamp=event.timestamp,
                description=event.description or None,
                location_name=event.location_id.name if event.location_id else None,
                location_uuid=event.location_id.uuid if event.location_id else None,
                carrier_name=event.carrier_name or None,
                tracking_number=event.tracking_number or None
            ))
        
        # Собираем этапы
        stages = [build_stage_schema(stage) for stage in order.stage_ids.sorted('sequence')]
        
        return OrderSchema(
            uuid=order.uuid,
            name=order.name,
            team_uuid=order.team_uuid,
            user_id=order.user_id,
            source_location_uuid=order.source_location_id.uuid,
            source_location_name=order.source_location_id.name,
            destination_location_uuid=order.destination_location_id.uuid,
            destination_location_name=order.destination_location_id.name,
            total_amount=order.total_amount,
            currency=order.currency_id.name,
            created_at=order.created_at,
            updated_at=order.updated_at,
            notes=order.notes or None,
            order_lines=order_lines,
            stages=stages,
            tracking_events=tracking_events
        )
    
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error fetching order: {str(e)}")


@router.post("/orders", response_model=OrderSchema)
async def create_order(order_input: CreateOrderInput, env: api.Environment = Depends(odoo_env)):
    """Создать новый заказ"""
    try:
        # Проверяем что локации существуют
        source_location = env['logistics.node'].search([('uuid', '=', order_input.source_location_uuid)], limit=1)
        destination_location = env['logistics.node'].search([('uuid', '=', order_input.destination_location_uuid)], limit=1)
        
        if not source_location or not destination_location:
            raise HTTPException(status_code=400, detail="Invalid location UUIDs")
        
        # Создаем заказ
        order = env['marketplace.order'].create({
            'team_uuid': order_input.team_uuid,
            'user_id': order_input.user_id,
            'source_location_id': source_location.id,
            'destination_location_id': destination_location.id,
            'notes': order_input.notes
        })
        
        # Создаем позиции заказа
        for line_input in order_input.order_lines:
            product = env['marketplace.product'].search([('uuid', '=', line_input.product_uuid)], limit=1)
            if product:
                env['marketplace.order.line'].create({
                    'order_id': order.id,
                    'product_id': product.id,
                    'quantity': line_input.quantity,
                    'unit': line_input.unit,
                    'notes': line_input.notes
                })
        
        # Создаем первое событие трекинга
        order._create_tracking_event('created', 'Order created')
        
        # Возвращаем созданный заказ
        return await get_order_by_uuid(order.uuid, env)
    
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error creating order: {str(e)}")