from fastapi import APIRouter, Depends, Query, Path, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional, Dict, Union, List

from src.address.schemas import ZoneCreate, ZoneUpdateSchema, ZoneOutSchema, CityCreateSchema, CityUpdateSchema, \
    CityResponse
from src.address.service import ZoneService
from src.database import get_db
from src.user.dependencies import require_role
from src.user.models import User

router = APIRouter(prefix="/zone", tags=["Zone"])


@router.get("")
async def list_zones(
    needle: Optional[str] = Query(None),
    sort_order: str = Query("ASC", alias="sort[order]", regex="^(ASC|DESC)$"),
    page: int = Query(1, ge=1),
    limit: int = Query(10, ge=1),
    db: AsyncSession = Depends(get_db),
):
    try:
        result = await ZoneService.get_zone_list(
            db=db,
            needle=needle,
            sort_order=sort_order,
            page=page,
            limit=limit
        )
        return {
                "data": result["items"],
                "total": result["total"],
                "page": page,
                "limit": limit,
                "status": True
        }
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }
@router.get("/{zone_id}", response_model=dict)
async def get_zone_by_id(
        zone_id: int = Path(..., description="Zone ID"),
        db: AsyncSession = Depends(get_db),
        # приклад як додавати ролі які можуть використовувати цей ендпоінт
        #user: User = Depends(require_role("Администратор", "Менеджер"))
):
    return await ZoneService.get_zone_by_id(zone_id, db)

@router.post("", response_model=dict)
async def create_zone(
        data: ZoneCreate,
        db: AsyncSession = Depends(get_db),
):
    return await ZoneService.create_zone(data, db)

@router.patch("/{zone_id}", response_model=Dict[str, Union[ZoneOutSchema, bool, str]])
async def patch_zone(
    zone_id: int = Path(...),
    data: ZoneUpdateSchema = Depends(),
    db: AsyncSession = Depends(get_db),
):
    try:
        return await ZoneService.update_zone(zone_id, data, db)
    except HTTPException as e:
        raise e
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.delete("", response_model=dict)
async def delete_zone(
        zone_id: int = Query(..., description="Zone ID"),
        db: AsyncSession = Depends(get_db),
):
    return await ZoneService.delete_zone(zone_id, db)

@router.get("/{zone_id}/city")
async def get_zone_cities_list(
    zone_id: int = Path(...),
    needle: Optional[str] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(10, ge=1),
    db: AsyncSession = Depends(get_db)
):
    try:
        result = await ZoneService.get_zone_cities_list(
            db=db,
            zone_id=zone_id,
            needle=needle,
            page=page,
            limit=limit
        )
        return {
                "data": result["items"],
                "total": result["total"],
                "page": page,
                "limit": limit,
                "status": True
        }
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }

@router.get("/{zone_id}/city/{city_id}", response_model=dict)
async def get_city_by_id(
        zone_id: int = Path(..., description="Zone ID"),
        city_id: int = Path(..., description="City ID"),
        db: AsyncSession = Depends(get_db),
):
    return await ZoneService.get_city_by_id(zone_id=zone_id, city_id=city_id, db=db)

@router.post("/city", response_model=dict)
async def create_city(data: CityCreateSchema, db: AsyncSession = Depends(get_db)):
    return await ZoneService.create_city_service(data, db)

@router.patch("/{zone_id}/city/{city_id}")
async def update_city(
        zone_id: int = Path(..., description="Zone ID"),
        city_id: int = Path(..., description="City ID"),
        data: CityUpdateSchema = Depends(),
        db: AsyncSession = Depends(get_db),
):
    updated_city = await ZoneService.update_city(zone_id, city_id, data, db)
    return {
        "data": updated_city,
        "status": True
    }

@router.delete("/zone/{zone_id}/city/{city_id}", response_model=dict)
async def delete_city(
        zone_id: int = Path(..., description="Zone ID"),
        city_id: int = Path(..., description="City ID"),
        db: AsyncSession = Depends(get_db),
):
    return await ZoneService.delete_city(zone_id, city_id, db)

@router.post("/synch", response_model=dict)
async def zone_synch(db: AsyncSession = Depends(get_db)):
    try:
        updated_zones = await ZoneService.synchronize_zones(db)
        zones_list = [{"zone_id": z.zone_id, "name": z.name} for z in updated_zones]
        return {
            "data": zones_list,
            "status": True
        }
    except Exception as e:
        return {
            "data": None,
            "status": False,
            "message": str(e)
        }

@router.post("/city/synch", response_model=dict)
async def city_synch(db: AsyncSession = Depends(get_db)):
    try:
        await ZoneService.synchronize_cities(db)
        return {"status": True}
    except Exception as e:
        return {"status": False, "message": str(e)}

@router.post("/{zone_id}/city/synch", response_model=List[CityResponse])
async def synch_cities_in_zone(
    zone_id: int = Path(..., ge=1, description="ID області"),
    db: AsyncSession = Depends(get_db),
):
    new_cities = await ZoneService.synch_cities_in_zone(zone_id, db)
    return new_cities