from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List, Optional

from database import get_db
from models.customers import Customer
from models.order import Order, OrderItem
from models.user import User
from schemas.customers import CustomerCreate, CustomerUpdate, CustomerOut, AssignCustomerRequest
from routers.deps import require_manager, get_current_user

router = APIRouter()


def _customer_out(c: Customer, db: Session) -> dict:
    orders = db.query(Order).filter(
        Order.customer_id == c.id,
        Order.status.in_(["closed", "paid"]),
    ).all()
    total_spent = sum(
        sum(i.unit_price * i.quantity for i in o.items if i.status in ("active", "paid"))
        for o in orders
    )
    return {
        "id": c.id,
        "name": c.name,
        "nickname": c.nickname,
        "phone": c.phone,
        "email": c.email,
        "notes": c.notes,
        "is_active": c.is_active,
        "created_at": c.created_at,
        "created_by_id": c.created_by_id,
        "visit_count": len(orders),
        "total_spent": round(total_spent, 2),
    }


@router.get("/", response_model=List[CustomerOut])
def list_customers(
    search: Optional[str] = None,
    include_inactive: bool = False,
    db: Session = Depends(get_db),
    user: User = Depends(require_manager),
):
    q = db.query(Customer)
    if not include_inactive:
        q = q.filter(Customer.is_active == True)
    if search:
        term = f"%{search}%"
        q = q.filter(
            Customer.name.ilike(term) |
            Customer.nickname.ilike(term) |
            Customer.phone.ilike(term)
        )
    customers = q.order_by(Customer.name).all()
    return [_customer_out(c, db) for c in customers]


@router.post("/", response_model=CustomerOut, status_code=status.HTTP_201_CREATED)
def create_customer(body: CustomerCreate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
    customer = Customer(**body.model_dump(), created_by_id=user.id)
    db.add(customer)
    db.commit()
    db.refresh(customer)
    return _customer_out(customer, db)


@router.get("/{customer_id}", response_model=CustomerOut)
def get_customer(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)):
    c = db.query(Customer).filter(Customer.id == customer_id).first()
    if not c:
        raise HTTPException(status_code=404, detail="Customer not found")
    return _customer_out(c, db)


@router.put("/{customer_id}", response_model=CustomerOut)
def update_customer(customer_id: int, body: CustomerUpdate, db: Session = Depends(get_db), user: User = Depends(require_manager)):
    c = db.query(Customer).filter(Customer.id == customer_id).first()
    if not c:
        raise HTTPException(status_code=404, detail="Customer not found")
    for field, value in body.model_dump(exclude_none=True).items():
        setattr(c, field, value)
    db.commit()
    db.refresh(c)
    return _customer_out(c, db)


@router.delete("/{customer_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_customer(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)):
    c = db.query(Customer).filter(Customer.id == customer_id).first()
    if not c:
        raise HTTPException(status_code=404, detail="Customer not found")
    c.is_active = False
    db.commit()


@router.get("/{customer_id}/orders")
def customer_orders(customer_id: int, db: Session = Depends(get_db), user: User = Depends(require_manager)):
    c = db.query(Customer).filter(Customer.id == customer_id).first()
    if not c:
        raise HTTPException(status_code=404, detail="Customer not found")
    from models.table import Table
    orders = db.query(Order).filter(Order.customer_id == customer_id).order_by(Order.opened_at.desc()).all()
    tables_map = {t.id: (t.label or f"T{t.number}") for t in db.query(Table).all()}
    result = []
    for o in orders:
        total = sum(i.unit_price * i.quantity for i in o.items if i.status in ("active", "paid"))
        result.append({
            "id": o.id,
            "table_name": tables_map.get(o.table_id) if o.table_id else None,
            "opened_at": o.opened_at,
            "status": o.status,
            "total": round(total, 2),
            "item_count": sum(i.quantity for i in o.items if i.status in ("active", "paid")),
        })
    return {"orders": result}
