from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from sqlalchemy import and_
from typing import List, Optional
from datetime import date

from ..database import get_db
from ..dependencies import get_current_user, require_owner
from ..models import PumpShiftConfig, Pump, ShiftTemplate, DailyShift, PumpReading, Staff
from ..schemas import PumpShiftConfigOut, PumpShiftConfigToggle, PumpStatusOut, PumpShiftStatus

router = APIRouter()


# ── Pump-Shift Config CRUD ──────────────────────────────────────────────────

@router.get("/pump-shift-configs", response_model=List[PumpShiftConfigOut])
def list_pump_shift_configs(
    pump_id:   Optional[int] = None,
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    q = (
        db.query(PumpShiftConfig)
        .join(Pump, PumpShiftConfig.pump_id == Pump.id)
        .join(ShiftTemplate, PumpShiftConfig.shift_template_id == ShiftTemplate.id)
    )
    if pump_id:
        q = q.filter(PumpShiftConfig.pump_id == pump_id)
    configs = q.order_by(
        Pump.pump_number, Pump.sort_order, Pump.pump_code, ShiftTemplate.sort_order
    ).all()
    result = []
    for c in configs:
        result.append(PumpShiftConfigOut(
            id=c.id,
            pump_id=c.pump_id,
            pump_number=c.pump.pump_number if c.pump else None,
            pump_code=c.pump.pump_code if c.pump else None,
            fuel_type=c.pump.fuel_type if c.pump else None,
            shift_template_id=c.shift_template_id,
            shift_code=c.shift_template.code if c.shift_template else None,
            shift_name=c.shift_template.name if c.shift_template else None,
            shift_color=c.shift_template.color if c.shift_template else None,
            is_active=c.is_active,
            sort_order=c.sort_order,
        ))
    return result


@router.put("/pump-shift-configs/{config_id}", response_model=PumpShiftConfigOut)
def toggle_pump_shift_config(
    config_id: int,
    body: PumpShiftConfigToggle,
    db: Session = Depends(get_db),
    user=Depends(require_owner),
):
    cfg = db.query(PumpShiftConfig).filter(PumpShiftConfig.id == config_id).first()
    if not cfg:
        raise HTTPException(404, "Config not found")
    cfg.is_active = body.is_active
    from .audit import log_audit
    log_audit(db, user.id, 'UPDATE', 'pump_shift_configs', config_id,
              f"{'Enabled' if body.is_active else 'Disabled'} pump {cfg.pump_id} for shift template {cfg.shift_template_id}")
    db.commit()
    db.refresh(cfg)
    return PumpShiftConfigOut(
        id=cfg.id, pump_id=cfg.pump_id,
        pump_number=cfg.pump.pump_number if cfg.pump else None,
        pump_code=cfg.pump.pump_code if cfg.pump else None,
        fuel_type=cfg.pump.fuel_type if cfg.pump else None,
        shift_template_id=cfg.shift_template_id,
        shift_code=cfg.shift_template.code if cfg.shift_template else None,
        shift_name=cfg.shift_template.name if cfg.shift_template else None,
        shift_color=cfg.shift_template.color if cfg.shift_template else None,
        is_active=cfg.is_active, sort_order=cfg.sort_order,
    )


# ── Live Pump Status ────────────────────────────────────────────────────────

@router.get("/pumps/status", response_model=List[PumpStatusOut])
def get_pump_status(
    on_date: Optional[date] = Query(None, alias="date"),
    db: Session = Depends(get_db),
    _=Depends(get_current_user),
):
    """
    Return all active pumps with their shift assignments and live status for a given date.
    Status: NOT_STARTED (no reading yet) | OPEN (reading exists, no ending meter) | CLOSED (ending meter entered)
    """
    target = on_date or date.today()

    # Active pumps ordered by pump_number
    pumps = db.query(Pump).filter(Pump.is_active == True).order_by(Pump.pump_number, Pump.pump_code).all()

    # Active shift templates for each pump via pump_shift_configs
    configs = (
        db.query(PumpShiftConfig)
        .filter(PumpShiftConfig.is_active == True)
        .order_by(PumpShiftConfig.pump_id, PumpShiftConfig.sort_order)
        .all()
    )
    # Group configs by pump_id
    configs_by_pump: dict[int, list[PumpShiftConfig]] = {}
    for c in configs:
        configs_by_pump.setdefault(c.pump_id, []).append(c)

    # Fetch all daily_shifts for the target date
    day_shifts = (
        db.query(DailyShift)
        .filter(DailyShift.record_date == target)
        .all()
    )
    # Index shifts by shift_type for fast lookup
    shifts_by_type: dict[str, DailyShift] = {s.shift_type: s for s in day_shifts}

    # Fetch all pump readings for these shifts
    shift_ids = [s.id for s in day_shifts]
    readings: list[PumpReading] = []
    if shift_ids:
        readings = (
            db.query(PumpReading)
            .filter(PumpReading.shift_id.in_(shift_ids))
            .all()
        )
    # Index readings by (shift_id, pump_id)
    reading_map: dict[tuple, PumpReading] = {(r.shift_id, r.pump_id): r for r in readings}

    # Fetch operator names for all staff ids referenced in readings
    staff_ids = {r.staff_id for r in readings if r.staff_id}
    staff_map: dict[int, str] = {}
    if staff_ids:
        staff_rows = db.query(Staff).filter(Staff.id.in_(staff_ids)).all()
        staff_map = {s.id: s.full_name for s in staff_rows}

    result = []
    for pump in pumps:
        pump_configs = configs_by_pump.get(pump.id, [])
        shift_statuses = []

        for cfg in pump_configs:
            tmpl = cfg.shift_template
            if not tmpl:
                continue
            shift = shifts_by_type.get(tmpl.code)
            reading = reading_map.get((shift.id, pump.id)) if shift else None

            if reading and float(reading.ending_meter) > 0:
                pump_status = 'CLOSED'
            elif reading:
                pump_status = 'OPEN'
            else:
                pump_status = 'NOT_STARTED'

            operator_id = reading.staff_id if reading else None
            # For EM shift, fall back to the shift's manager staff_id
            if not operator_id and shift and tmpl.code == 'EM':
                operator_id = shift.staff_id

            shift_statuses.append(PumpShiftStatus(
                shift_id=shift.id if shift else None,
                shift_type=tmpl.code,
                shift_name=tmpl.name,
                shift_color=tmpl.color,
                shift_start=tmpl.start_time,
                shift_end=tmpl.end_time,
                operator_id=operator_id,
                operator_name=staff_map.get(operator_id) if operator_id else None,
                pump_status=pump_status,
                ending_meter=float(reading.ending_meter) if reading and float(reading.ending_meter) > 0 else None,
                sale_amount=float(reading.sale_amount) if reading else None,
            ))

        result.append(PumpStatusOut(
            pump_id=pump.id,
            pump_code=pump.pump_code,
            pump_number=pump.pump_number,
            fuel_type=pump.fuel_type,
            description=pump.description,
            shifts=shift_statuses,
        ))

    return result
