from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List
from pydantic import BaseModel
from app.database import get_db
from app.models.mass_template import MassTemplate
from app.models.template_position import TemplatePosition
from app.schemas.mass_template import (
    MassTemplateCreate, MassTemplateUpdate, MassTemplateResponse,
    TemplatePositionCreate, TemplatePositionResponse
)

router = APIRouter(prefix="/api/mass-templates", tags=["Mass Templates"])

def enrich_positions(positions):
    return [
        TemplatePositionResponse(
            id=p.id,
            position_number=p.position_number,
            position_type_code=p.position_type_code,
            position_type_label=p.position_type.label if p.position_type else None,
            position_type_color=p.position_type.color if p.position_type else None,
            sort_order=p.sort_order,
            posisi_id=p.posisi_id,
        )
        for p in positions
    ]

@router.get("/", response_model=List[MassTemplateResponse])
def get_all(db: Session = Depends(get_db)):
    templates = db.query(MassTemplate).order_by(MassTemplate.id).all()
    result = []
    for t in templates:
        result.append(MassTemplateResponse(
            id=t.id, name=t.name, mass_type=t.mass_type,
            day_of_week=t.day_of_week, time=t.time,
            is_first_friday=t.is_first_friday, is_active=t.is_active,
            positions=enrich_positions(t.positions),
        ))
    return result

@router.get("/{template_id}", response_model=MassTemplateResponse)
def get_one(template_id: int, db: Session = Depends(get_db)):
    t = db.query(MassTemplate).filter(MassTemplate.id == template_id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Template tidak ditemukan")
    return MassTemplateResponse(
        id=t.id, name=t.name, mass_type=t.mass_type,
        day_of_week=t.day_of_week, time=t.time,
        is_first_friday=t.is_first_friday, is_active=t.is_active,
        positions=enrich_positions(t.positions),
    )

@router.post("/", response_model=MassTemplateResponse)
def create(data: MassTemplateCreate, db: Session = Depends(get_db)):
    # Cek duplicate hari + jam + is_first_friday
    existing = db.query(MassTemplate).filter(
        MassTemplate.day_of_week == data.day_of_week,
        MassTemplate.time == data.time,
        MassTemplate.is_first_friday == data.is_first_friday,
        MassTemplate.is_active == True
    ).first()
    if existing:
        raise HTTPException(
            status_code=400,
            detail=f"Template dengan hari dan jam yang sama sudah ada: {existing.name}"
        )
    
    template_data = data.model_dump()
    num_positions = template_data.pop('num_positions', 8)
    t = MassTemplate(**template_data)
    db.add(t)
    db.flush()
    for i in range(1, num_positions + 1):
        db.add(TemplatePosition(
            template_id=t.id,
            position_number=str(i),
            position_type_code='regular',
            sort_order=i
        ))
    try:
        db.commit()
        db.refresh(t)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan template misa baru")
    return MassTemplateResponse(
        id=t.id, name=t.name, mass_type=t.mass_type,
        day_of_week=t.day_of_week, time=t.time,
        is_first_friday=t.is_first_friday, is_active=t.is_active,
        positions=enrich_positions(t.positions),
    )

@router.put("/{template_id}", response_model=MassTemplateResponse)
def update(template_id: int, data: MassTemplateUpdate, db: Session = Depends(get_db)):
    t = db.query(MassTemplate).filter(MassTemplate.id == template_id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Template tidak ditemukan")
    for key, value in data.model_dump(exclude_unset=True).items():
        setattr(t, key, value)
    try:
        db.commit()
        db.refresh(t)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal memperbarui template misa")
    return MassTemplateResponse(
        id=t.id, name=t.name, mass_type=t.mass_type,
        day_of_week=t.day_of_week, time=t.time,
        is_first_friday=t.is_first_friday, is_active=t.is_active,
        positions=enrich_positions(t.positions),
    )

@router.delete("/{template_id}")
def delete(template_id: int, db: Session = Depends(get_db)):
    t = db.query(MassTemplate).filter(MassTemplate.id == template_id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Template tidak ditemukan")
    db.delete(t)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus template misa")
    return {"message": "Template dihapus"}

# ── Positions ──────────────────────────────────────────────

class ReorderItem(BaseModel):
    id: int
    position_number: str

@router.put("/{template_id}/positions/reorder")
def reorder_positions(template_id: int, data: List[ReorderItem], db: Session = Depends(get_db)):
    if not data:
        return {"message": "Reorder berhasil"}
    # Batch: pre-fetch all positions in one query instead of N queries in loop
    ids = [item.id for item in data]
    positions_map = {
        p.id: p for p in db.query(TemplatePosition).filter(
            TemplatePosition.id.in_(ids),
            TemplatePosition.template_id == template_id,
        ).all()
    }
    for idx, item in enumerate(data):
        p = positions_map.get(item.id)
        if p:
            p.sort_order = idx
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menyimpan urutan posisi")
    return {"message": "Reorder berhasil"}

@router.post("/{template_id}/positions", response_model=TemplatePositionResponse)
def add_position(template_id: int, data: TemplatePositionCreate, db: Session = Depends(get_db)):
    t = db.query(MassTemplate).filter(MassTemplate.id == template_id).first()
    if not t:
        raise HTTPException(status_code=404, detail="Template tidak ditemukan")
    p = TemplatePosition(template_id=template_id, **data.model_dump())
    db.add(p)
    try:
        db.commit()
        db.refresh(p)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menambahkan posisi ke template")
    return TemplatePositionResponse(
        id=p.id,
        position_number=p.position_number,
        position_type_code=p.position_type_code,
        position_type_label=p.position_type.label if p.position_type else None,
        position_type_color=p.position_type.color if p.position_type else None,
    )

@router.put("/{template_id}/positions/{position_id}", response_model=TemplatePositionResponse)
def update_position(template_id: int, position_id: int, data: TemplatePositionCreate, db: Session = Depends(get_db)):
    p = db.query(TemplatePosition).filter(
        TemplatePosition.id == position_id,
        TemplatePosition.template_id == template_id
    ).first()
    if not p:
        raise HTTPException(status_code=404, detail="Posisi tidak ditemukan")
    for key, value in data.model_dump().items():
        setattr(p, key, value)
    try:
        db.commit()
        db.refresh(p)
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal memperbarui posisi template")
    return TemplatePositionResponse(
        id=p.id,
        position_number=p.position_number,
        position_type_code=p.position_type_code,
        position_type_label=p.position_type.label if p.position_type else None,
        position_type_color=p.position_type.color if p.position_type else None,
    )

@router.delete("/{template_id}/positions/{position_id}")
def delete_position(template_id: int, position_id: int, db: Session = Depends(get_db)):
    p = db.query(TemplatePosition).filter(
        TemplatePosition.id == position_id,
        TemplatePosition.template_id == template_id
    ).first()
    if not p:
        raise HTTPException(status_code=404, detail="Posisi tidak ditemukan")
    db.delete(p)
    try:
        db.commit()
    except Exception:
        db.rollback()
        raise HTTPException(status_code=500, detail="Gagal menghapus posisi dari template")
    return {"message": "Posisi dihapus"}