"""
Beach endpoints
"""
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List
from uuid import UUID

from app.db.session import get_db
from app.models.beach import BeachPlace, BeachPlacePhoto, BeachPlaceSchedule, BeachPlaceTerrain, BeachTerrainType, BeachBedType
from app.models.company import Company
from app.models.user import Country, Currency
from app.schemas.beach import (
    BeachPlaceCreate, BeachPlaceUpdate, BeachPlace,
    BeachPlacePhotoCreate, BeachPlacePhotoUpdate, BeachPlacePhoto,
    BeachPlaceScheduleCreate, BeachPlaceScheduleUpdate, BeachPlaceSchedule,
    BeachPlaceTerrainCreate, BeachPlaceTerrainUpdate, BeachPlaceTerrain,
    BeachTerrainTypeCreate, BeachTerrainTypeUpdate, BeachTerrainType,
    BeachBedTypeCreate, BeachBedTypeUpdate, BeachBedType
)

router = APIRouter()


# Beach Terrain Type endpoints
@router.post("/terrain-types/", response_model=BeachTerrainType)
def create_beach_terrain_type(
    terrain_type: BeachTerrainTypeCreate,
    db: Session = Depends(get_db)
):
    db_terrain_type = BeachTerrainType(**terrain_type.dict())
    db.add(db_terrain_type)
    db.commit()
    db.refresh(db_terrain_type)
    return db_terrain_type


@router.get("/terrain-types/", response_model=List[BeachTerrainType])
def read_beach_terrain_types(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    terrain_types = db.query(BeachTerrainType).offset(skip).limit(limit).all()
    return terrain_types


@router.get("/terrain-types/{terrain_type_id}", response_model=BeachTerrainType)
def read_beach_terrain_type(
    terrain_type_id: int,
    db: Session = Depends(get_db)
):
    db_terrain_type = db.query(BeachTerrainType).filter(BeachTerrainType.terrain_type_id == terrain_type_id).first()
    if db_terrain_type is None:
        raise HTTPException(status_code=404, detail="Beach terrain type not found")
    return db_terrain_type


@router.put("/terrain-types/{terrain_type_id}", response_model=BeachTerrainType)
def update_beach_terrain_type(
    terrain_type_id: int,
    terrain_type: BeachTerrainTypeUpdate,
    db: Session = Depends(get_db)
):
    db_terrain_type = db.query(BeachTerrainType).filter(BeachTerrainType.terrain_type_id == terrain_type_id).first()
    if db_terrain_type is None:
        raise HTTPException(status_code=404, detail="Beach terrain type not found")
    
    for key, value in terrain_type.dict(exclude_unset=True).items():
        setattr(db_terrain_type, key, value)
    
    db.commit()
    db.refresh(db_terrain_type)
    return db_terrain_type


@router.delete("/terrain-types/{terrain_type_id}")
def delete_beach_terrain_type(
    terrain_type_id: int,
    db: Session = Depends(get_db)
):
    db_terrain_type = db.query(BeachTerrainType).filter(BeachTerrainType.terrain_type_id == terrain_type_id).first()
    if db_terrain_type is None:
        raise HTTPException(status_code=404, detail="Beach terrain type not found")
    
    db.delete(db_terrain_type)
    db.commit()
    return {"message": "Beach terrain type deleted successfully"}


# Beach Bed Type endpoints
@router.post("/bed-types/", response_model=BeachBedType)
def create_beach_bed_type(
    bed_type: BeachBedTypeCreate,
    db: Session = Depends(get_db)
):
    db_bed_type = BeachBedType(**bed_type.dict())
    db.add(db_bed_type)
    db.commit()
    db.refresh(db_bed_type)
    return db_bed_type


@router.get("/bed-types/", response_model=List[BeachBedType])
def read_beach_bed_types(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    bed_types = db.query(BeachBedType).offset(skip).limit(limit).all()
    return bed_types


@router.get("/bed-types/{bed_type_id}", response_model=BeachBedType)
def read_beach_bed_type(
    bed_type_id: int,
    db: Session = Depends(get_db)
):
    db_bed_type = db.query(BeachBedType).filter(BeachBedType.bed_type_id == bed_type_id).first()
    if db_bed_type is None:
        raise HTTPException(status_code=404, detail="Beach bed type not found")
    return db_bed_type


@router.put("/bed-types/{bed_type_id}", response_model=BeachBedType)
def update_beach_bed_type(
    bed_type_id: int,
    bed_type: BeachBedTypeUpdate,
    db: Session = Depends(get_db)
):
    db_bed_type = db.query(BeachBedType).filter(BeachBedType.bed_type_id == bed_type_id).first()
    if db_bed_type is None:
        raise HTTPException(status_code=404, detail="Beach bed type not found")
    
    for key, value in bed_type.dict(exclude_unset=True).items():
        setattr(db_bed_type, key, value)
    
    db.commit()
    db.refresh(db_bed_type)
    return db_bed_type


@router.delete("/bed-types/{bed_type_id}")
def delete_beach_bed_type(
    bed_type_id: int,
    db: Session = Depends(get_db)
):
    db_bed_type = db.query(BeachBedType).filter(BeachBedType.bed_type_id == bed_type_id).first()
    if db_bed_type is None:
        raise HTTPException(status_code=404, detail="Beach bed type not found")
    
    db.delete(db_bed_type)
    db.commit()
    return {"message": "Beach bed type deleted successfully"}


# Beach Place endpoints
@router.post("/", response_model=BeachPlace)
def create_beach_place(
    beach_place: BeachPlaceCreate,
    db: Session = Depends(get_db)
):
    # Verify company exists
    db_company = db.query(Company).filter(Company.company_id == beach_place.company_id).first()
    if db_company is None:
        raise HTTPException(status_code=404, detail="Company not found")
    
    # Verify terrain type exists
    db_terrain_type = db.query(BeachTerrainType).filter(BeachTerrainType.terrain_type_id == beach_place.terrain_type_id).first()
    if db_terrain_type is None:
        raise HTTPException(status_code=404, detail="Beach terrain type not found")
    
    # Verify country exists
    db_country = db.query(Country).filter(Country.country_id == beach_place.country_id).first()
    if db_country is None:
        raise HTTPException(status_code=404, detail="Country not found")
    
    db_beach_place = BeachPlace(**beach_place.dict())
    db.add(db_beach_place)
    db.commit()
    db.refresh(db_beach_place)
    return db_beach_place


@router.get("/", response_model=List[BeachPlace])
def read_beach_places(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    beach_places = db.query(BeachPlace).offset(skip).limit(limit).all()
    return beach_places


@router.get("/{beach_place_id}", response_model=BeachPlace)
def read_beach_place(
    beach_place_id: UUID,
    db: Session = Depends(get_db)
):
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    return db_beach_place


@router.put("/{beach_place_id}", response_model=BeachPlace)
def update_beach_place(
    beach_place_id: UUID,
    beach_place: BeachPlaceUpdate,
    db: Session = Depends(get_db)
):
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    update_data = beach_place.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_beach_place, key, value)
    
    db.commit()
    db.refresh(db_beach_place)
    return db_beach_place


@router.delete("/{beach_place_id}")
def delete_beach_place(
    beach_place_id: UUID,
    db: Session = Depends(get_db)
):
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    db.delete(db_beach_place)
    db.commit()
    return {"message": "Beach place deleted successfully"}


# Beach Place Photo endpoints
@router.post("/photos/", response_model=BeachPlacePhoto)
def create_beach_place_photo(
    photo: BeachPlacePhotoCreate,
    db: Session = Depends(get_db)
):
    # Verify beach place exists
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == photo.beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    db_photo = BeachPlacePhoto(**photo.dict())
    db.add(db_photo)
    db.commit()
    db.refresh(db_photo)
    return db_photo


@router.get("/photos/", response_model=List[BeachPlacePhoto])
def read_beach_place_photos(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    photos = db.query(BeachPlacePhoto).offset(skip).limit(limit).all()
    return photos


@router.get("/photos/{photo_id}", response_model=BeachPlacePhoto)
def read_beach_place_photo(
    photo_id: int,
    db: Session = Depends(get_db)
):
    db_photo = db.query(BeachPlacePhoto).filter(BeachPlacePhoto.photo_id == photo_id).first()
    if db_photo is None:
        raise HTTPException(status_code=404, detail="Beach place photo not found")
    return db_photo


@router.put("/photos/{photo_id}", response_model=BeachPlacePhoto)
def update_beach_place_photo(
    photo_id: int,
    photo: BeachPlacePhotoUpdate,
    db: Session = Depends(get_db)
):
    db_photo = db.query(BeachPlacePhoto).filter(BeachPlacePhoto.photo_id == photo_id).first()
    if db_photo is None:
        raise HTTPException(status_code=404, detail="Beach place photo not found")
    
    update_data = photo.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_photo, key, value)
    
    db.commit()
    db.refresh(db_photo)
    return db_photo


@router.delete("/photos/{photo_id}")
def delete_beach_place_photo(
    photo_id: int,
    db: Session = Depends(get_db)
):
    db_photo = db.query(BeachPlacePhoto).filter(BeachPlacePhoto.photo_id == photo_id).first()
    if db_photo is None:
        raise HTTPException(status_code=404, detail="Beach place photo not found")
    
    db.delete(db_photo)
    db.commit()
    return {"message": "Beach place photo deleted successfully"}


# Beach Place Schedule endpoints
@router.post("/schedules/", response_model=BeachPlaceSchedule)
def create_beach_place_schedule(
    schedule: BeachPlaceScheduleCreate,
    db: Session = Depends(get_db)
):
    # Verify beach place exists
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == schedule.beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    # Verify currency exists
    db_currency = db.query(Currency).filter(Currency.currency_id == schedule.currency_id).first()
    if db_currency is None:
        raise HTTPException(status_code=404, detail="Currency not found")
    
    db_schedule = BeachPlaceSchedule(**schedule.dict())
    db.add(db_schedule)
    db.commit()
    db.refresh(db_schedule)
    return db_schedule


@router.get("/schedules/", response_model=List[BeachPlaceSchedule])
def read_beach_place_schedules(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    schedules = db.query(BeachPlaceSchedule).offset(skip).limit(limit).all()
    return schedules


@router.get("/schedules/{schedule_id}", response_model=BeachPlaceSchedule)
def read_beach_place_schedule(
    schedule_id: int,
    db: Session = Depends(get_db)
):
    db_schedule = db.query(BeachPlaceSchedule).filter(BeachPlaceSchedule.schedule_id == schedule_id).first()
    if db_schedule is None:
        raise HTTPException(status_code=404, detail="Beach place schedule not found")
    return db_schedule


@router.put("/schedules/{schedule_id}", response_model=BeachPlaceSchedule)
def update_beach_place_schedule(
    schedule_id: int,
    schedule: BeachPlaceScheduleUpdate,
    db: Session = Depends(get_db)
):
    db_schedule = db.query(BeachPlaceSchedule).filter(BeachPlaceSchedule.schedule_id == schedule_id).first()
    if db_schedule is None:
        raise HTTPException(status_code=404, detail="Beach place schedule not found")
    
    update_data = schedule.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_schedule, key, value)
    
    db.commit()
    db.refresh(db_schedule)
    return db_schedule


@router.delete("/schedules/{schedule_id}")
def delete_beach_place_schedule(
    schedule_id: int,
    db: Session = Depends(get_db)
):
    db_schedule = db.query(BeachPlaceSchedule).filter(BeachPlaceSchedule.schedule_id == schedule_id).first()
    if db_schedule is None:
        raise HTTPException(status_code=404, detail="Beach place schedule not found")
    
    db.delete(db_schedule)
    db.commit()
    return {"message": "Beach place schedule deleted successfully"}


# Beach Place Terrain endpoints
@router.post("/terrains/", response_model=BeachPlaceTerrain)
def create_beach_place_terrain(
    terrain: BeachPlaceTerrainCreate,
    db: Session = Depends(get_db)
):
    # Verify beach place exists
    db_beach_place = db.query(BeachPlace).filter(BeachPlace.beach_place_id == terrain.beach_place_id).first()
    if db_beach_place is None:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    db_terrain = BeachPlaceTerrain(**terrain.dict())
    db.add(db_terrain)
    db.commit()
    db.refresh(db_terrain)
    return db_terrain


@router.get("/terrains/", response_model=List[BeachPlaceTerrain])
def read_beach_place_terrains(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    terrains = db.query(BeachPlaceTerrain).offset(skip).limit(limit).all()
    return terrains


@router.get("/terrains/{terrain_id}", response_model=BeachPlaceTerrain)
def read_beach_place_terrain(
    terrain_id: UUID,
    db: Session = Depends(get_db)
):
    db_terrain = db.query(BeachPlaceTerrain).filter(BeachPlaceTerrain.terrain_id == terrain_id).first()
    if db_terrain is None:
        raise HTTPException(status_code=404, detail="Beach place terrain not found")
    return db_terrain


@router.put("/terrains/{terrain_id}", response_model=BeachPlaceTerrain)
def update_beach_place_terrain(
    terrain_id: UUID,
    terrain: BeachPlaceTerrainUpdate,
    db: Session = Depends(get_db)
):
    db_terrain = db.query(BeachPlaceTerrain).filter(BeachPlaceTerrain.terrain_id == terrain_id).first()
    if db_terrain is None:
        raise HTTPException(status_code=404, detail="Beach place terrain not found")
    
    update_data = terrain.dict(exclude_unset=True)
    for key, value in update_data.items():
        setattr(db_terrain, key, value)
    
    db.commit()
    db.refresh(db_terrain)
    return db_terrain


@router.delete("/terrains/{terrain_id}")
def delete_beach_place_terrain(
    terrain_id: UUID,
    db: Session = Depends(get_db)
):
    db_terrain = db.query(BeachPlaceTerrain).filter(BeachPlaceTerrain.terrain_id == terrain_id).first()
    if db_terrain is None:
        raise HTTPException(status_code=404, detail="Beach place terrain not found")
    
    db.delete(db_terrain)
    db.commit()
    return {"message": "Beach place terrain deleted successfully"}