from datetime import datetime, timezone
from sqlalchemy.orm import Session
from fastapi import HTTPException, status

from src.utils.pagination import QueryPaginator
from src.apps.base.models.country import Country
from uuid import UUID
from sqlalchemy.exc import IntegrityError
from typing import Optional
from src.apps.wine.wine.models.wine import WineDb
from src.apps.wine.variety.models.variety import Variety
from src.core.exceptions import APIException
from src.apps.wine.variety.schemas.variety import VarietyUpdateSchema,VarietyCreateSchema,VarietyOutputSchema as VarietyOutSchema
from src.utils.constants import API_PREFIXES
from src.core.config import settings

async def get_varieties(
    db: Session,
    page: int = 1,
    per_page: int = 10,
) -> any:
    try:
        offset = (page - 1) * per_page
        query = db.query(Variety).order_by(Variety.date_created.desc())
        query = query.filter(Variety.deleted_at == None)
        paginator = QueryPaginator(
            query=query, schema=VarietyOutSchema, url="".join([str(settings.api_base_url()), API_PREFIXES.VARIETY]), offset=offset, limit=per_page, use_orm=True
        )
        return paginator.paginate()
    except Exception as e:
        raise APIException(
            module="get_varieties",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to fetch varieties."
        )

async def get_variety_by_id(
    db: Session,
    variety_id: int
) -> VarietyOutSchema:
    try:
        variety = db.query(Variety).filter(Variety.id == variety_id,Variety.deleted_at == None).first()
        if not variety:
            raise APIException(
                module="get_variety_by_id",
                error={"exception": "Variety not found"},
                status_code=status.HTTP_404_NOT_FOUND,
                message="Variety not found."
            )
        return variety
    except Exception as e:
        raise APIException(
            module="get_variety_by_id",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to fetch variety."
        )
        
async def create_variety(
    db: Session,
    variety_data: VarietyCreateSchema
) -> VarietyOutSchema:
    try:
        new_variety = Variety(**variety_data.model_dump())
        db.add(new_variety)
        db.commit()
        db.refresh(new_variety)
        return VarietyOutSchema.model_validate(new_variety)
    except IntegrityError as e:
        db.rollback()
        raise APIException(
            module="create_variety",
            error={"exception": "Variety already exists"},
            status_code=status.HTTP_400_BAD_REQUEST,
            message="Variety already exists."
        )
    except Exception as e:
        raise APIException(
            module="create_variety",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to create variety."
        )
        
async def update_variety(
    db: Session,    
    variety_id: int,
    variety_data: VarietyUpdateSchema
) -> VarietyOutSchema:
    try:
        variety = await get_variety_by_id(db, variety_id)
        for key, value in variety_data.model_dump().items():
            setattr(variety, key, value)
        
        db.commit()
        db.refresh(variety)
        return VarietyOutSchema.model_validate(variety)
    except IntegrityError as e:
        db.rollback()
        raise APIException(
            module="update_variety",
            error={"exception": "Variety already exists"},
            status_code=status.HTTP_400_BAD_REQUEST,
            message="Variety already exists."
        )
    except Exception as e:
        raise APIException(
            module="update_variety",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to update variety."
        )
        
async def delete_variety(
    db: Session,
    variety_id: int
) -> VarietyOutSchema:
    try:
        variety = await get_variety_by_id(db, variety_id)
        variety.deleted_at = datetime.now(timezone.utc)
        db.commit()
        return VarietyOutSchema.model_validate(variety)
    except Exception as e:
        raise APIException(
            module="delete_variety",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to delete variety."
        )