from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from .. import schemas, security, serialize
from ..db import get_db
from ..models import DeliveryZone, Order, User
from ..services import audit, get_setting, set_setting

router = APIRouter(prefix="/api/admin", dependencies=[Depends(security.staff_user)])


def _zone(z: DeliveryZone):
    return {"id": z.id, "name": z.name, "fee": float(z.fee), "eta": z.eta, "active": z.active}


@router.get("/zones")
def zones(db: Session = Depends(get_db)):
    return [_zone(z) for z in db.scalars(select(DeliveryZone).order_by(DeliveryZone.name))]


@router.post("/zones")
def add_zone(body: schemas.ZoneIn, db: Session = Depends(get_db), user: User = Depends(security.staff_user)):
    z = DeliveryZone(**body.model_dump())
    db.add(z)
    try:
        db.flush()
    except IntegrityError:
        db.rollback()
        raise HTTPException(409, "A delivery area with that name already exists.")
    audit(db, user.email, "zone_create", f"{z.name} {z.fee}")
    db.commit()
    return _zone(z)


@router.put("/zones/{zid}")
def edit_zone(zid: int, body: schemas.ZoneIn, db: Session = Depends(get_db), user: User = Depends(security.staff_user)):
    z = db.get(DeliveryZone, zid)
    if not z:
        raise HTTPException(404, "Delivery area not found.")
    for k, v in body.model_dump().items():
        setattr(z, k, v)
    audit(db, user.email, "zone_update", f"{z.name} {z.fee} active={z.active}")
    try:
        db.commit()
    except IntegrityError:
        db.rollback()
        raise HTTPException(409, "A delivery area with that name already exists.")
    return _zone(z)


@router.get("/settings")
def get_settings(db: Session = Depends(get_db)):
    return {"store_name": get_setting(db, "store_name", "Abrokyire Aba Ghana"),
            "free_delivery_over": float(get_setting(db, "free_delivery_over", "250")),
            "contact_phone": get_setting(db, "contact_phone", ""),
            "momo_instructions": get_setting(db, "momo_instructions", "")}


@router.put("/settings")
def put_settings(body: schemas.SettingsIn, db: Session = Depends(get_db), user: User = Depends(security.owner_user)):
    set_setting(db, "store_name", body.store_name.strip())
    set_setting(db, "free_delivery_over", str(body.free_delivery_over))
    set_setting(db, "contact_phone", body.contact_phone.strip())
    set_setting(db, "momo_instructions", body.momo_instructions.strip())
    audit(db, user.email, "settings_update", f"free delivery over {body.free_delivery_over}")
    db.commit()
    return get_settings(db)


# --------------------------------------------------------------------- team

@router.get("/team")
def team(db: Session = Depends(get_db), user: User = Depends(security.owner_user)):
    rows = db.scalars(select(User).where(User.role.in_(["owner", "staff"])).order_by(User.name))
    return [{**serialize.user(u), "active": u.active, "last_login": u.last_login.isoformat() if u.last_login else None}
            for u in rows]


@router.post("/team")
def add_team(body: schemas.StaffIn, db: Session = Depends(get_db), user: User = Depends(security.owner_user)):
    if body.role not in ("staff", "owner"):
        raise HTTPException(400, "Role must be staff or owner.")
    problem = security.password_problem(body.password)
    if problem:
        raise HTTPException(400, problem)
    email = body.email.strip().lower()
    if db.scalar(select(User.id).where(User.email == email)):
        raise HTTPException(409, "That email is already in use.")
    u = User(name=body.name.strip(), email=email, role=body.role, password_hash=security.hash_password(body.password))
    db.add(u)
    audit(db, user.email, "team_add", f"{email} as {body.role}")
    db.commit()
    return serialize.user(u)


@router.patch("/team/{uid}")
def edit_team(uid: int, body: schemas.StaffUpdate, db: Session = Depends(get_db), user: User = Depends(security.owner_user)):
    u = db.get(User, uid)
    if not u or u.role == "customer":
        raise HTTPException(404, "Team member not found.")
    if u.id == user.id and (body.active is False or (body.role and body.role != "owner")):
        raise HTTPException(400, "You cannot lock yourself out or lower your own role.")
    if body.active is not None:
        u.active = body.active
    if body.role:
        if body.role not in ("staff", "owner"):
            raise HTTPException(400, "Role must be staff or owner.")
        u.role = body.role
    if body.password:
        problem = security.password_problem(body.password)
        if problem:
            raise HTTPException(400, problem)
        u.password_hash = security.hash_password(body.password)
    audit(db, user.email, "team_update", f"{u.email}")
    db.commit()
    return serialize.user(u)
