import os
import uuid
from fastapi import APIRouter, Depends, UploadFile, File, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.database import get_db
from app.core.security import require_permission
from app.modules.production_masters import schemas, service

router = APIRouter()


def _view():
    return Depends(require_permission('PRODUCTION_MASTERS', 'view'))


def _edit():
    return Depends(require_permission('PRODUCTION_MASTERS', 'edit'))


def _create():
    return Depends(require_permission('PRODUCTION_MASTERS', 'create'))


def _delete():
    return Depends(require_permission('PRODUCTION_MASTERS', 'delete'))


# ── Body types ──

@router.get("/body-types", response_model=list[schemas.BodyTypeOut])
async def list_body_types(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_body_types(db)


@router.post("/body-types", response_model=schemas.BodyTypeOut, status_code=201)
async def create_body_type(payload: schemas.BodyTypeCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_body_type(db, payload)


@router.put("/body-types/{body_type_id}", response_model=schemas.BodyTypeOut)
async def update_body_type(body_type_id: uuid.UUID, payload: schemas.BodyTypeUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_body_type(db, body_type_id, payload)


@router.delete("/body-types/{body_type_id}", status_code=204)
async def delete_body_type(body_type_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_body_type(db, body_type_id)


# ── Customer segments ──

@router.get("/segments", response_model=list[schemas.SegmentOut])
async def list_segments(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_segments(db)


@router.post("/segments", response_model=schemas.SegmentOut, status_code=201)
async def create_segment(payload: schemas.SegmentCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_segment(db, payload)


@router.put("/segments/{segment_id}", response_model=schemas.SegmentOut)
async def update_segment(segment_id: uuid.UUID, payload: schemas.SegmentUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_segment(db, segment_id, payload)


@router.delete("/segments/{segment_id}", status_code=204)
async def delete_segment(segment_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_segment(db, segment_id)


# ── RTOs ──

@router.get("/rtos", response_model=list[schemas.RtoOut])
async def list_rtos(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_rtos(db)


@router.post("/rtos", response_model=schemas.RtoOut, status_code=201)
async def create_rto(payload: schemas.RtoCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_rto(db, payload)


@router.put("/rtos/{rto_id}", response_model=schemas.RtoOut)
async def update_rto(rto_id: uuid.UUID, payload: schemas.RtoUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_rto(db, rto_id, payload)


@router.delete("/rtos/{rto_id}", status_code=204)
async def delete_rto(rto_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_rto(db, rto_id)


# ── Vehicle models ──

@router.get("/models", response_model=list[schemas.ModelOut])
async def list_models(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_models(db)


@router.post("/models", response_model=schemas.ModelOut, status_code=201)
async def create_model(payload: schemas.ModelCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_model(db, payload)


@router.post("/models/upload-image")
async def upload_model_image(
    file: UploadFile = File(...),
    _=_create(),
):
    """
    Upload an image for a production model.
    """
    import shutil
    import os
    try:
        # Ensure directory exists
        os.makedirs("uploads/models", exist_ok=True)
        
        # Generate unique filename
        ext = file.filename.split('.')[-1] if '.' in file.filename else 'png'
        filename = f"{uuid.uuid4().hex}.{ext}"
        file_path = os.path.join("uploads/models", filename)
        
        # Save file
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
            
        return {"image_url": f"/{file_path.replace(os.sep, '/')}"}
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Failed to upload image: {str(e)}")


@router.put("/models/{model_id}", response_model=schemas.ModelOut)
async def update_model(model_id: uuid.UUID, payload: schemas.ModelUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_model(db, model_id, payload)


@router.delete("/models/{model_id}", status_code=204)
async def delete_model(model_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_model(db, model_id)


# ── Special features + options ──

@router.get("/features", response_model=list[schemas.FeatureOut])
async def list_features(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_features(db)


@router.post("/features", response_model=schemas.FeatureOut, status_code=201)
async def create_feature(payload: schemas.FeatureCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_feature(db, payload)


@router.put("/features/{feature_id}", response_model=schemas.FeatureOut)
async def update_feature(feature_id: uuid.UUID, payload: schemas.FeatureUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_feature(db, feature_id, payload)


@router.delete("/features/{feature_id}", status_code=204)
async def delete_feature(feature_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_feature(db, feature_id)


@router.post("/features/{feature_id}/options", response_model=schemas.FeatureOptionOut, status_code=201)
async def create_feature_option(feature_id: uuid.UUID, payload: schemas.FeatureOptionCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_feature_option(db, feature_id, payload)


@router.put("/features/{feature_id}/options/{option_id}", response_model=schemas.FeatureOptionOut)
async def update_feature_option(
    feature_id: uuid.UUID, option_id: uuid.UUID, payload: schemas.FeatureOptionUpdate,
    _=_edit(), db: AsyncSession = Depends(get_db),
):
    return await service.update_feature_option(db, feature_id, option_id, payload)


@router.delete("/features/{feature_id}/options/{option_id}", status_code=204)
async def delete_feature_option(
    feature_id: uuid.UUID, option_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db),
):
    await service.delete_feature_option(db, feature_id, option_id)


@router.post("/features/upload-image")
async def upload_feature_image(
    file: UploadFile = File(...),
    _=_create(),
):
    import shutil
    
    # Ensure directory exists
    os.makedirs("uploads/features", exist_ok=True)
    
    # Use original filename
    filename = file.filename
    file_path = os.path.join("uploads/features", filename)
    
    # Save file
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
        
    return {"image_url": f"/uploads/features/{filename}"}


@router.post("/body-types/upload-image")
async def upload_body_type_image(
    file: UploadFile = File(...),
    _=_create(),
):
    import shutil
    
    # Ensure directory exists
    os.makedirs("uploads/body_types", exist_ok=True)
    
    # Use original filename
    filename = file.filename
    file_path = os.path.join("uploads/body_types", filename)
    
    # Save file
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
        
    return {"image_url": f"/uploads/body_types/{filename}"}


# ── Model <-> body-type / segment relationship maps ──

@router.get("/model-body-types", response_model=list[schemas.ModelBodyTypeOut])
async def list_model_body_types(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_model_body_types(db)


@router.post("/model-body-types", response_model=schemas.ModelBodyTypeOut, status_code=201)
async def add_model_body_type(payload: schemas.ModelBodyTypeLink, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.add_model_body_type(db, payload)


@router.delete("/model-body-types/{link_id}", status_code=204)
async def remove_model_body_type(link_id: uuid.UUID, _=_edit(), db: AsyncSession = Depends(get_db)):
    await service.remove_model_body_type(db, link_id)


@router.get("/model-segments", response_model=list[schemas.ModelSegmentOut])
async def list_model_segments(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_model_segments(db)


@router.post("/model-segments", response_model=schemas.ModelSegmentOut, status_code=201)
async def add_model_segment(payload: schemas.ModelSegmentLink, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.add_model_segment(db, payload)


@router.delete("/model-segments/{link_id}", status_code=204)
async def remove_model_segment(link_id: uuid.UUID, _=_edit(), db: AsyncSession = Depends(get_db)):
    await service.remove_model_segment(db, link_id)


@router.get("/feature-segments", response_model=list[schemas.FeatureSegmentOut])
async def list_feature_segments(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_feature_segments(db)


@router.post("/feature-segments", response_model=schemas.FeatureSegmentOut, status_code=201)
async def add_feature_segment(payload: schemas.FeatureSegmentAdd, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.add_feature_segment(db, payload)


@router.delete("/feature-segments/{link_id}", status_code=204)
async def remove_feature_segment(link_id: uuid.UUID, _=_edit(), db: AsyncSession = Depends(get_db)):
    await service.remove_feature_segment(db, link_id)


# ── Seating Layouts ──

@router.get("/seating-layouts", response_model=list[schemas.SeatingLayoutOut])
async def list_seating_layouts(_=_view(), db: AsyncSession = Depends(get_db)):
    return await service.list_seating_layouts(db)


@router.get("/seating-layouts/search", response_model=list[schemas.SeatingLayoutOut])
async def search_seating_layouts(
    chassis_model: str,
    body_type: str,
    segment: str,
    door_type: str,
    seat_type: str,
    _=_view(), 
    db: AsyncSession = Depends(get_db)
):
    return await service.search_seating_layouts(db, chassis_model, body_type, segment, door_type, seat_type)


@router.post("/seating-layouts", response_model=schemas.SeatingLayoutOut, status_code=201)
async def create_seating_layout(payload: schemas.SeatingLayoutCreate, _=_create(), db: AsyncSession = Depends(get_db)):
    return await service.create_seating_layout(db, payload)


@router.put("/seating-layouts/{layout_id}", response_model=schemas.SeatingLayoutOut)
async def update_seating_layout(layout_id: uuid.UUID, payload: schemas.SeatingLayoutUpdate, _=_edit(), db: AsyncSession = Depends(get_db)):
    return await service.update_seating_layout(db, layout_id, payload)


@router.delete("/seating-layouts/{layout_id}", status_code=204)
async def delete_seating_layout(layout_id: uuid.UUID, _=_delete(), db: AsyncSession = Depends(get_db)):
    await service.delete_seating_layout(db, layout_id)


@router.post("/seating-layouts/upload-image")
async def upload_seating_layout_image(
    file: UploadFile = File(...),
    _=_create(),
):
    import shutil
    import os
    os.makedirs("uploads/seating_layouts", exist_ok=True)
    filename = file.filename
    file_path = os.path.join("uploads/seating_layouts", filename)
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"url": f"/uploads/seating_layouts/{filename}"}


@router.post("/seating-layouts/upload-pdf")
async def upload_seating_layout_pdf(
    file: UploadFile = File(...),
    _=_create(),
):
    import shutil
    import os
    os.makedirs("uploads/seating_layouts", exist_ok=True)
    filename = file.filename
    file_path = os.path.join("uploads/seating_layouts", filename)
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"url": f"/uploads/seating_layouts/{filename}"}

# ── Seat Model Configurations ──

@router.get('/seat-model-configs', response_model=list[schemas.SeatModelConfigurationOut], dependencies=[_view()])
async def list_seat_model_configs(db: AsyncSession = Depends(get_db)):
    return await service.list_seat_model_configs(db)

@router.post('/seat-model-configs', response_model=schemas.SeatModelConfigurationOut, dependencies=[_edit()])
async def create_seat_model_config(payload: schemas.SeatModelConfigurationCreate, db: AsyncSession = Depends(get_db)):
    return await service.create_seat_model_config(db, payload)

@router.put('/seat-model-configs/{config_id}', response_model=schemas.SeatModelConfigurationOut, dependencies=[_edit()])
async def update_seat_model_config(config_id: uuid.UUID, payload: schemas.SeatModelConfigurationUpdate, db: AsyncSession = Depends(get_db)):
    return await service.update_seat_model_config(db, config_id, payload)

@router.delete('/seat-model-configs/{config_id}', dependencies=[_edit()])
async def delete_seat_model_config(config_id: uuid.UUID, db: AsyncSession = Depends(get_db)):
    await service.delete_seat_model_config(db, config_id)
    return {"ok": True}

@router.post('/seat-model-configs/upload-image', dependencies=[_edit()])
async def upload_seat_config_image(file: UploadFile = File(...)):
    import shutil
    import os
    os.makedirs("uploads/seat_configs", exist_ok=True)
    filename = file.filename
    file_path = os.path.join("uploads/seat_configs", filename)
    with open(file_path, "wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"image_url": f"/uploads/seat_configs/{filename}"}
