import json
from datetime import datetime
from bson import ObjectId
from bson.errors import InvalidId
from pymongo.errors import DuplicateKeyError
from fastapi import HTTPException
from typing import Optional
from app.v1.services.sequence import get_next_sequence_value_int

from app.v1.models.platform.vehiclesmodel import (
    VehicleBase,
    VehicleUpdate
)
from pymongo import ASCENDING, DESCENDING

COLLECTION_NAME = "vehicles"

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, ObjectId):
            return str(obj)
        return super().default(obj)


def create_vehicle_service(vehicle_data: dict, db) -> dict:
    vehicles_collection = db[COLLECTION_NAME]
    
    try:
        # Clean up data before insertion
        if 'max_speed' in vehicle_data and vehicle_data['max_speed'] is None:
            vehicle_data['max_speed'] = 0  # or None
        if 'engine_capacity' in vehicle_data and vehicle_data['engine_capacity'] is None:
            vehicle_data['engine_capacity'] = 0  # or None

        vehicle_data["model_id"] = get_next_sequence_value_int("model_id", db)
        
        # Insert the vehicle data
        result = vehicles_collection.insert_one(vehicle_data)
        
        # Add the generated ID to the response
        vehicle_data["_id"] = str(result.inserted_id)
        vehicle_data["vehicle_id"] = str(result.inserted_id)
        
        # Convert datetime fields to ISO strings
        for field in ["created_date", "updated_date"]:
            if field in vehicle_data and isinstance(vehicle_data[field], datetime):
                vehicle_data[field] = vehicle_data[field].isoformat()
        
        return {"vehicle_data": vehicle_data}
    except DuplicateKeyError:
        raise HTTPException(status_code=400, detail="Vehicle creation failed")
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")

def get_vehicles_service(account_id: str, skip: int, limit: int, status: Optional[str], created_date_from: Optional[str],
    created_date_to: Optional[str], q: Optional[str], sort_by: Optional[str], sort_order: Optional[str], db) -> dict:
    vehicles_collection = db[COLLECTION_NAME]
    query = {}
    
    if account_id != "all":
        query["account_id"] = account_id

    if status:
        query["status"] = status

    # Date filtering
    if created_date_from or created_date_to:
        date_query = {}
        if created_date_from:
            date_query["$gte"] = datetime.strptime(created_date_from, "%Y-%m-%d")
        if created_date_to:
            date_query["$lte"] = datetime.strptime(created_date_to, "%Y-%m-%d")
        query["created_date"] = date_query
        
    if q:
        regex_query = {"$regex": q, "$options": "i"}
        query["$or"] = [
            {"manufacturer_name": regex_query},
            {"vehicle_type": regex_query},
            {"fuel_type": regex_query}
        ]

    # Sorting logic
    sort_fields = {
        "vehicle_type": "vehicle_type",
        "manufacturer_name": "manufacturer_name",
        "fuel_type": "fuel_type",
        "is_autonomous": "is_autonomous",
        "can_fly": "can_fly",
        "capacity_jobs": "capacity_jobs",
        "number_of_wheels": "number_of_wheels",
        "max_speed": "max_speed",
        "created_date": "created_date"
    }
    sort_field = sort_fields.get(sort_by, "created_date")
    sort_direction = ASCENDING if sort_order == "asc" else DESCENDING

    cursor = vehicles_collection.find(query).sort(sort_field, sort_direction).skip(skip).limit(limit)
    vehicles = list(cursor)
    #vehicles = list(vehicles_collection.find(query).skip(skip).limit(limit))
    
    formatted_vehicles = []
    for vehicle in vehicles:
        vehicle["vehicle_id"] = str(vehicle["_id"])
        vehicle["_id"] = str(vehicle["_id"])
        vehicle.setdefault("account_id", "")
        vehicle.setdefault("user_id", "")
        # Convert datetime fields
        for field in ["created_date", "updated_date"]:
            if field in vehicle and isinstance(vehicle[field], datetime):
                vehicle[field] = vehicle[field].isoformat()
        formatted_vehicles.append(vehicle)

    total_count = vehicles_collection.count_documents(query)
    return {"total_count": total_count, "vehicles": formatted_vehicles}

def read_vehicle_service(vehicle_id: str, db) -> dict:
    try:
        vehicle_object_id = ObjectId(vehicle_id)
    except InvalidId:
        raise HTTPException(status_code=400, detail="Invalid vehicle ID")

    vehicle = db[COLLECTION_NAME].find_one({"_id": vehicle_object_id})
    if not vehicle:
        raise HTTPException(status_code=404, detail="Vehicle not found")

    vehicle["vehicle_id"] = str(vehicle["_id"])
    vehicle["_id"] = str(vehicle["_id"])
    vehicle.setdefault("account_id", "")
    vehicle.setdefault("user_id", "")
    
    # Convert datetime fields
    for field in ["created_date", "updated_date"]:
        if field in vehicle and isinstance(vehicle[field], datetime):
            vehicle[field] = vehicle[field].isoformat()
    
    return vehicle

def update_vehicle_service(vehicle_id: str, vehicle_data: VehicleUpdate, db) -> dict:
    vehicles_collection = db[COLLECTION_NAME]
    
    try:
        vehicle_object_id = ObjectId(vehicle_id)
    except InvalidId:
        raise HTTPException(status_code=400, detail="Invalid vehicle ID")

    existing_vehicle = vehicles_collection.find_one({"_id": vehicle_object_id})
    if not existing_vehicle:
        raise HTTPException(status_code=404, detail="Vehicle not found")

    update_data = {k: v for k, v in vehicle_data.model_dump().items() if v is not None}
    update_data["updated_date"] = datetime.utcnow()

    result = vehicles_collection.update_one(
        {"_id": vehicle_object_id},
        {"$set": update_data}
    )
    
    if result.matched_count == 0:
        raise HTTPException(status_code=404, detail="Vehicle not found")

    updated_vehicle = vehicles_collection.find_one({"_id": vehicle_object_id})
    updated_vehicle["vehicle_id"] = str(updated_vehicle["_id"])
    updated_vehicle["_id"] = str(updated_vehicle["_id"])
    updated_vehicle.setdefault("account_id", "")
    updated_vehicle.setdefault("user_id", "")
    
    # Convert datetime fields
    for field in ["created_date", "updated_date"]:
        if field in updated_vehicle and isinstance(updated_vehicle[field], datetime):
            updated_vehicle[field] = updated_vehicle[field].isoformat()
    
    return updated_vehicle

def delete_vehicle_service(vehicle_id: str, db) -> dict:
    vehicles_collection = db[COLLECTION_NAME]
    
    try:
        vehicle_object_id = ObjectId(vehicle_id)
    except InvalidId:
        raise HTTPException(status_code=400, detail="Invalid vehicle ID")

    vehicle = vehicles_collection.find_one({"_id": vehicle_object_id})
    if not vehicle:
        raise HTTPException(status_code=404, detail="Vehicle not found")

    vehicles_collection.delete_one({"_id": vehicle_object_id})
    vehicle["vehicle_id"] = str(vehicle["_id"])
    vehicle["_id"] = str(vehicle["_id"])
    vehicle.setdefault("account_id", "")
    vehicle.setdefault("user_id", "")
    
    # Convert datetime fields
    for field in ["created_date", "updated_date"]:
        if field in vehicle and isinstance(vehicle[field], datetime):
            vehicle[field] = vehicle[field].isoformat()
    
    return vehicle