"""
Offer Profile Routes
Driver automatic offer configuration
"""
from typing import List
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func

from app.database import get_db
from app.models.driver import Driver
from app.models.offer_profile import OfferProfile
from app.schemas.offer_profile import (
    OfferProfileCreate,
    OfferProfileUpdate,
    OfferProfileResponse,
    OfferProfilePriorityUpdate,
)
from app.schemas.common import MessageResponse, PaginatedResponse
from app.utils.dependencies import get_current_driver
from app.utils.helpers import build_order_by

router = APIRouter()


@router.get("", response_model=PaginatedResponse[OfferProfileResponse])
async def list_offer_profiles(
    page: int = Query(1, ge=1),
    limit: int = Query(20, ge=1, le=100),
    sort_by: str = Query("created_at", description="Field to sort by"),
    order: str = Query("desc", description="Sort order: asc or desc"),
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """List all offer profiles for current driver"""
    driver_filter = OfferProfile.driver_id == driver.id
    count_result = await db.execute(select(func.count(OfferProfile.id)).where(driver_filter))
    total = count_result.scalar() or 0

    offset = (page - 1) * limit
    order_clause = build_order_by(OfferProfile, sort_by, order, {"created_at", "updated_at", "priority", "name", "id"})
    query = select(OfferProfile).where(driver_filter).order_by(order_clause).offset(offset).limit(limit)
    result = await db.execute(query)
    profiles = result.scalars().all()
    items = [
        OfferProfileResponse(
            id=p.id,
            driver_id=p.driver_id,
            name=p.name,
            enabled=p.enabled,
            confirm_offer_manually=p.confirm_offer_manually,
            priority=p.priority,
            start_area=p.start_area,
            destination_area=p.destination_area,
            distance_min_km=p.distance_min_km,
            distance_max_km=p.distance_max_km,
            price_type=p.price_type,
            price_per_km=p.price_per_km,
            fixed_price=p.fixed_price,
            initial_charge=p.initial_charge,
            round_trip_enabled=p.round_trip_enabled,
            round_trip_discount_pct=p.round_trip_discount_pct,
            child_seat_charge=p.child_seat_charge,
            start_time=p.start_time,
            end_time=p.end_time,
            pre_ride_time_min=p.pre_ride_time_min,
            min_lead_time_min=p.min_lead_time_min,
            days_of_week=p.days_of_week if isinstance(p.days_of_week, list) else None,
            for_all_vehicles=p.for_all_vehicles,
            vehicle_ids=p.vehicle_ids if isinstance(p.vehicle_ids, list) else None,
        )
        for p in profiles
    ]
    return PaginatedResponse.create(items, total, page, limit)


@router.put("/priority", response_model=PaginatedResponse[OfferProfileResponse])
async def update_offer_profile_priority(
    data: OfferProfilePriorityUpdate,
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """Update offer profile priority order"""
    for idx, profile_id in enumerate(reversed(data.profile_ids)):
        query = select(OfferProfile).where(
            OfferProfile.id == profile_id,
            OfferProfile.driver_id == driver.id
        )
        result = await db.execute(query)
        profile = result.scalar_one_or_none()
        if profile:
            profile.priority = idx
    await db.commit()
    return await list_offer_profiles(page=1, limit=100, driver=driver, db=db)


@router.post("", response_model=OfferProfileResponse, status_code=status.HTTP_201_CREATED)
async def create_offer_profile(
    data: OfferProfileCreate,
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """Create new offer profile"""
    profile = OfferProfile(
        driver_id=driver.id,
        name=data.name,
        enabled=data.enabled,
        confirm_offer_manually=data.confirm_offer_manually,
        start_area=data.start_area,
        destination_area=data.destination_area,
        distance_min_km=data.distance_min_km,
        distance_max_km=data.distance_max_km,
        price_type=data.price_type,
        price_per_km=data.price_per_km,
        fixed_price=data.fixed_price,
        initial_charge=data.initial_charge,
        round_trip_enabled=data.round_trip_enabled,
        round_trip_discount_pct=data.round_trip_discount_pct,
        child_seat_charge=data.child_seat_charge,
        start_time=data.start_time,
        end_time=data.end_time,
        pre_ride_time_min=data.pre_ride_time_min,
        min_lead_time_min=data.min_lead_time_min,
        days_of_week=data.days_of_week,
        for_all_vehicles=data.for_all_vehicles,
        vehicle_ids=data.vehicle_ids,
    )
    db.add(profile)
    await db.commit()
    await db.refresh(profile)
    return _to_response(profile)


@router.get("/{profile_id}", response_model=OfferProfileResponse)
async def get_offer_profile(
    profile_id: int,
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """Get offer profile by ID"""
    profile = await _get_profile_or_404(db, profile_id, driver.id)
    return _to_response(profile)


@router.put("/{profile_id}", response_model=OfferProfileResponse)
async def update_offer_profile(
    profile_id: int,
    data: OfferProfileUpdate,
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """Update offer profile"""
    profile = await _get_profile_or_404(db, profile_id, driver.id)
    update_data = data.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        if hasattr(profile, field):
            setattr(profile, field, value)
    await db.commit()
    await db.refresh(profile)
    return _to_response(profile)


@router.delete("/{profile_id}", response_model=MessageResponse)
async def delete_offer_profile(
    profile_id: int,
    driver: Driver = Depends(get_current_driver),
    db: AsyncSession = Depends(get_db)
):
    """Delete offer profile"""
    profile = await _get_profile_or_404(db, profile_id, driver.id)
    await db.delete(profile)
    await db.commit()
    return MessageResponse(message="Offer profile deleted successfully")


async def _get_profile_or_404(db: AsyncSession, profile_id: int, driver_id: int) -> OfferProfile:
    query = select(OfferProfile).where(
        OfferProfile.id == profile_id,
        OfferProfile.driver_id == driver_id
    )
    result = await db.execute(query)
    profile = result.scalar_one_or_none()
    if not profile:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Offer profile not found")
    return profile


def _to_response(profile: OfferProfile) -> OfferProfileResponse:
    return OfferProfileResponse(
        id=profile.id,
        driver_id=profile.driver_id,
        name=profile.name,
        enabled=profile.enabled,
        confirm_offer_manually=profile.confirm_offer_manually,
        priority=profile.priority,
        start_area=profile.start_area,
        destination_area=profile.destination_area,
        distance_min_km=profile.distance_min_km,
        distance_max_km=profile.distance_max_km,
        price_type=profile.price_type,
        price_per_km=profile.price_per_km,
        fixed_price=profile.fixed_price,
        initial_charge=profile.initial_charge,
        round_trip_enabled=profile.round_trip_enabled,
        round_trip_discount_pct=profile.round_trip_discount_pct,
        child_seat_charge=profile.child_seat_charge,
        start_time=profile.start_time,
        end_time=profile.end_time,
        pre_ride_time_min=profile.pre_ride_time_min,
        min_lead_time_min=profile.min_lead_time_min,
        days_of_week=profile.days_of_week if isinstance(profile.days_of_week, list) else None,
        for_all_vehicles=profile.for_all_vehicles,
        vehicle_ids=profile.vehicle_ids if isinstance(profile.vehicle_ids, list) else None,
    )
