from datetime import datetime
from uuid import UUID
from sqlalchemy.orm import Session
from fastapi import HTTPException, status
from src.core.exceptions import APIException
from src.apps.base.models.country import Country
from src.core.config import settings
from src.utils.constants import API_PREFIXES
from src.apps.base.schemas.country import (
    CountryCreateSchema,
    CountryUpdateSchema,
    CountryOutSchema
)
from src.utils.pagination import QueryPaginator
from src.apps.base.models.regions import Region


async def get_country_by_id(db: Session, country_id: int) -> Country:
    try:
        country = db.query(Country).filter(
            Country.id == country_id,
            Country.deleted_at.is_(None)
        ).first()
        if not country:
            raise APIException(
                module="Country",
                error={"exception": "Country not found"},
                status_code=status.HTTP_404_NOT_FOUND,
                message="Country not found."
            )
        return country
    except Exception as e:
        raise APIException(
            module="Country",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Error fetching country by ID."
        )


async def get_all_countries(
    db: Session,
    page: int = 1,
    per_page: int = 10,
):
    try:
        offset = (page - 1) * per_page
        query = db.query(Country).filter(Country.deleted_at.is_(None))

        paginator = QueryPaginator(
            query=query,
            schema=CountryOutSchema,
            url="".join([str(settings.api_base_url()), API_PREFIXES.COUNTRY]),
            offset=offset,
            limit=per_page,
            use_orm=True
        )
        return paginator.paginate()
    except Exception as e:
        raise APIException(
            module="get_all_countries",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Failed to fetch countries."
        )


async def create_country(db: Session, payload: CountryCreateSchema) -> Country:
    # Check for existing country (both active and soft-deleted)
    try:
        existing = db.query(Country).filter(
            (Country.name == payload.name)
        ).first()
    except Exception as e:
        raise APIException(
            module="Country",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Error checking for existing country."
        )
    
    if existing:
        if existing.deleted_at is not None:
            # Restore soft-deleted record
            try:
                existing.name = payload.name
                existing.deleted_at = None
                existing.updated_at = datetime.utcnow()
                db.commit()
                db.refresh(existing)
                return existing
            except Exception as e:
                raise APIException(
                    module="Country",
                    error={"exception": str(e)},
                    status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                    message="Error restoring soft-deleted country."
                )
        else:
            raise APIException(
                module="Country",
                error={"exception": "Country already exists."},
                status_code=status.HTTP_400_BAD_REQUEST,
                message="Country with this name already exists."
            )

    # Create new country
    try:
        country = Country(**payload.dict())
        db.add(country)
        db.commit()
        db.refresh(country)
        return country
    except Exception as e:
        raise APIException(
            module="Country",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Error creating country."
        )



async def update_country(db: Session, country_id: int, payload: CountryUpdateSchema) -> Country:
    country = await get_country_by_id(db, country_id)
    try:
        update_data = payload.dict(exclude_unset=True)

        for field, value in update_data.items():
            setattr(country, field, value)

        db.commit()
        db.refresh(country)
        return country
    except Exception as e:
        raise APIException(
            module="Country",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Error updating country."
        )



async def delete_country(db: Session, country_id: int) -> None:
    country = await get_country_by_id(db, country_id)
    
    # has_linked_regions = db.query(Region).filter(
    #     Region.country_code == country.country_code,
    #     Region.is_deleted == False
    # ).count() > 0

    # # Check if any region is linked to this country
    # if has_linked_regions:
    #     raise HTTPException(
    #         status_code=status.HTTP_400_BAD_REQUEST,
    #         detail="Cannot delete country as it is linked to existing regions"
    #     )

    # Soft delete
    try: 
        country.is_deleted = True
        country.deleted_at = datetime.utcnow()
        db.commit()
        db.refresh(country)
        return None
    except Exception as e:
        raise APIException(
            module="Country",
            error={"exception": str(e)},
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            message="Error deleting country."
        )
