from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from datetime import date
from decimal import Decimal
from ..database import get_db
from ..models import CashHandover, DailyShift
from ..dependencies import get_current_user
from ..shift_utils import recalc_shift_totals

router = APIRouter()


def _denom_total(d: dict) -> Decimal:
    return Decimal(
        d.get('note_5000', 0) * 5000 + d.get('note_2000', 0) * 2000 +
        d.get('note_1000', 0) * 1000 + d.get('note_500',  0) * 500  +
        d.get('note_100',  0) * 100  + d.get('note_50',   0) * 50   +
        d.get('note_20',   0) * 20   + d.get('note_10',   0) * 10
    )


def _serialize(h: CashHandover) -> dict:
    return {
        'id':               h.id,
        'shift_id':         h.shift_id,
        'cycle_id':         h.cycle_id,
        'collection_date':  str(h.collection_date),
        'shift_type':       h.shift_type,
        'pumper_id':        h.pumper_id,
        'pumper_name':      h.pumper.full_name if h.pumper else None,
        'note_5000':        h.note_5000,
        'note_2000':        h.note_2000,
        'note_1000':        h.note_1000,
        'note_500':         h.note_500,
        'note_100':         h.note_100,
        'note_50':          h.note_50,
        'note_20':          h.note_20,
        'note_10':          h.note_10,
        'calculated_total': float(h.calculated_total),
        'card_visa':        float(h.card_visa),
        'card_amex':        float(h.card_amex),
        'card_touch':       float(h.card_touch),
        'card_total':       float(h.card_total),
        'credit_total':     float(h.credit_total),
        'collected_at':     h.collected_at.isoformat() if h.collected_at else None,
        'notes':            h.notes,
    }


@router.get("/cash-handovers")
def list_handovers(
    collection_date: date = None,
    shift_type: str = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = db.query(CashHandover)
    if collection_date:
        q = q.filter(CashHandover.collection_date == collection_date)
    if shift_type:
        q = q.filter(CashHandover.shift_type == shift_type)
    return [_serialize(h) for h in q.order_by(CashHandover.collected_at).all()]


@router.post("/cash-handovers")
def create_handover(
    data: dict,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user),
):
    shift_id = data.get('shift_id') or None
    if not shift_id:
        raise HTTPException(status_code=400, detail="shift_id is required — select a shift before recording cash")
    shift = db.query(DailyShift).filter(DailyShift.id == shift_id).first()
    if not shift:
        raise HTTPException(status_code=404, detail="Shift not found")

    h = CashHandover(
        collection_date  = data.get('collection_date', date.today()),
        shift_type       = data['shift_type'],
        pumper_id        = data.get('pumper_id') or None,
        note_5000        = int(data.get('note_5000', 0)),
        note_2000        = int(data.get('note_2000', 0)),
        note_1000        = int(data.get('note_1000', 0)),
        note_500         = int(data.get('note_500',  0)),
        note_100         = int(data.get('note_100',  0)),
        note_50          = int(data.get('note_50',   0)),
        note_20          = int(data.get('note_20',   0)),
        note_10          = int(data.get('note_10',   0)),
        calculated_total = _denom_total(data),
        card_visa        = Decimal(str(data.get('card_visa',  0) or 0)),
        card_amex        = Decimal(str(data.get('card_amex',  0) or 0)),
        card_touch       = Decimal(str(data.get('card_touch', 0) or 0)),
        card_total       = (Decimal(str(data.get('card_visa',  0) or 0)) +
                            Decimal(str(data.get('card_amex',  0) or 0)) +
                            Decimal(str(data.get('card_touch', 0) or 0))),
        credit_total     = Decimal(str(data.get('credit_total', 0) or 0)),
        notes            = data.get('notes') or None,
        collected_by     = current_user.id,
        shift_id         = shift_id,
        cycle_id         = data.get('cycle_id') or None,
    )
    db.add(h)
    db.flush()
    if h.shift_id:
        recalc_shift_totals(h.shift_id, db)
    from .audit import log_audit
    log_audit(db, current_user.id, 'CREATE', 'cash_handovers', h.id,
              f"Cash bag recorded for shift #{shift_id}: Rs {float(h.calculated_total):.0f}")
    db.commit()
    db.refresh(h)
    return _serialize(h)


@router.put("/cash-handovers/{handover_id}")
def update_handover(
    handover_id: int,
    data: dict,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user),
):
    h = db.query(CashHandover).filter(CashHandover.id == handover_id).first()
    if not h:
        raise HTTPException(status_code=404, detail='Handover not found')
    for field in ['note_5000', 'note_2000', 'note_1000', 'note_500',
                  'note_100', 'note_50', 'note_20', 'note_10']:
        if field in data:
            setattr(h, field, int(data[field]))
    if 'card_visa' in data:
        h.card_visa  = Decimal(str(data['card_visa']  or 0))
    if 'card_amex' in data:
        h.card_amex  = Decimal(str(data['card_amex']  or 0))
    if 'card_touch' in data:
        h.card_touch = Decimal(str(data['card_touch'] or 0))
    h.card_total = h.card_visa + h.card_amex + h.card_touch
    if 'credit_total' in data:
        h.credit_total = Decimal(str(data['credit_total'] or 0))
    if 'pumper_id' in data:
        h.pumper_id = data['pumper_id'] or None
    if 'notes' in data:
        h.notes = data['notes'] or None
    h.calculated_total = _denom_total({
        'note_5000': h.note_5000, 'note_2000': h.note_2000,
        'note_1000': h.note_1000, 'note_500':  h.note_500,
        'note_100':  h.note_100,  'note_50':   h.note_50,
        'note_20':   h.note_20,   'note_10':   h.note_10,
    })
    if h.shift_id:
        recalc_shift_totals(h.shift_id, db)
    from .audit import log_audit
    log_audit(db, current_user.id, 'UPDATE', 'cash_handovers', handover_id,
              f"Updated cash bag for shift #{h.shift_id}: Rs {float(h.calculated_total):.0f}")
    db.commit()
    db.refresh(h)
    return _serialize(h)


@router.delete("/cash-handovers/{handover_id}", status_code=204)
def delete_handover(
    handover_id: int,
    db: Session = Depends(get_db),
    current_user=Depends(get_current_user),
):
    h = db.query(CashHandover).filter(CashHandover.id == handover_id).first()
    if not h:
        raise HTTPException(status_code=404, detail='Handover not found')
    shift_id = h.shift_id
    from .audit import log_audit
    log_audit(db, current_user.id, 'DELETE', 'cash_handovers', handover_id,
              f"Deleted cash bag for shift #{shift_id}")
    db.delete(h)
    db.flush()
    if shift_id:
        recalc_shift_totals(shift_id, db)
    db.commit()
