<?php
namespace App\Models;

use CodeIgniter\Model;

class CajaModel extends Model
{
    protected $table      = 'caja';
    protected $primaryKey = 'id_caja';
    protected $allowedFields = ['id_usuario', 'id_usuario_cierre', 'fecha_apertura', 'fecha_cierre', 'monto_inicial', 'fondo_chica', 'saldo_chica_actual', 'monto_esperado', 'monto_real_cierre', 'diferencia', 'estado'];
    protected $returnType    = 'array';
    protected $useTimestamps = false;

    public function getOpenCaja()
    {
        return $this->where('estado', 'abierto')->first();
    }

    public function getCajaWithMovements($cajaId)
    {
        $db = \Config\Database::connect();
        $caja = $db->table('caja c')
            ->select('c.*, u1.username, u2.username as username_cierre')
            ->join('usuarios u1', 'u1.id_usuario = c.id_usuario', 'left')
            ->join('usuarios u2', 'u2.id_usuario = c.id_usuario_cierre', 'left')
            ->where('c.id_caja', $cajaId)
            ->get()
            ->getRowArray();
        if (!$caja) return null;

        // General movements
        $caja['movements'] = $db->table('caja_movimientos cm')
            ->select('cm.*, COALESCE(v.total, 0) as venta_total')
            ->join('ventas v', 'v.id_venta = cm.id_venta', 'left')
            ->where('cm.id_caja', $cajaId)
            ->orderBy('cm.fecha', 'ASC')
            ->get()
            ->getResultArray();

        // Chica movements
        $caja['chica_movements'] = $db->table('caja_chica_movimientos ccm')
            ->where('ccm.id_caja', $cajaId)
            ->orderBy('ccm.fecha', 'ASC')
            ->get()
            ->getResultArray();

        // General totals
        $totalIngresos = 0;
        $totalEgresos = 0;
        foreach ($caja['movements'] as $m) {
            if ($m['tipo'] == 'ingreso') $totalIngresos += $m['monto'];
            else $totalEgresos += $m['monto'];
        }
        $caja['total_ingresos'] = $totalIngresos;
        $caja['total_egresos'] = $totalEgresos;

        // General expected balance (not counting the chica float)
        $caja['monto_esperado'] = $caja['monto_inicial'] + $totalIngresos - $totalEgresos;

        // Chica totals
        $totalChicaGastos = 0;
        $totalChicaRepos = 0;
        $totalChicaIngresos = 0;
        foreach ($caja['chica_movements'] as $m) {
            if ($m['tipo'] == 'gasto') $totalChicaGastos += $m['monto'];
            elseif ($m['tipo'] == 'ingreso') $totalChicaIngresos += $m['monto'];
            else $totalChicaRepos += $m['monto'];
        }
        $caja['total_chica_gastos'] = $totalChicaGastos;
        $caja['total_chica_reposiciones'] = $totalChicaRepos;
        $caja['total_chica_ingresos'] = $totalChicaIngresos;
        $caja['saldo_chica_actual'] = ($caja['fondo_chica'] ?? 0) + $totalChicaRepos + $totalChicaIngresos - $totalChicaGastos;

        // Total cash in drawer = General expected + Chica current balance
        $caja['total_efectivo'] = $caja['monto_esperado'] + $caja['saldo_chica_actual'];

        return $caja;
    }

    public function getHistory($limit = 200, $desde = null, $hasta = null)
    {
        $db = \Config\Database::connect();
        $builder = $db->table('caja c')
            ->select('c.*, u1.username as username_apertura, u2.username as username_cierre')
            ->join('usuarios u1', 'u1.id_usuario = c.id_usuario', 'left')
            ->join('usuarios u2', 'u2.id_usuario = c.id_usuario_cierre', 'left');

        if ($desde) {
            $builder->where('c.fecha_apertura >=', $desde . ' 00:00:00');
        }
        if ($hasta) {
            $builder->where('c.fecha_apertura <=', $hasta . ' 23:59:59');
        }

        return $builder->orderBy('c.fecha_apertura', 'DESC')
            ->limit($limit)
            ->get()
            ->getResultArray();
    }

    public function getLastClosedCaja()
    {
        $db = \Config\Database::connect();
        return $db->table('caja')
            ->where('estado', 'cerrado')
            ->orderBy('fecha_cierre', 'DESC')
            ->limit(1)
            ->get()
            ->getRowArray();
    }

    public function getTodayCajas()
    {
        $db = \Config\Database::connect();
        return $db->table('caja c')
            ->select('c.*, u1.username as username_apertura, u2.username as username_cierre,
                     COALESCE((SELECT SUM(monto) FROM caja_chica_movimientos WHERE id_caja = c.id_caja AND tipo = "ingreso"), 0) as total_ventas')
            ->join('usuarios u1', 'u1.id_usuario = c.id_usuario', 'left')
            ->join('usuarios u2', 'u2.id_usuario = c.id_usuario_cierre', 'left')
            ->where('DATE(c.fecha_apertura) = CURDATE()')
            ->orderBy('c.fecha_apertura', 'DESC')
            ->get()
            ->getResultArray();
    }

    public function addMovement($data)
    {
        $db = \Config\Database::connect();
        return $db->table('caja_movimientos')->insert($data);
    }

    public function getMovementsByCaja($cajaId)
    {
        $db = \Config\Database::connect();
        return $db->table('caja_movimientos')
            ->where('id_caja', $cajaId)
            ->orderBy('fecha', 'ASC')
            ->get()
            ->getResultArray();
    }

    public function addChicaMovement($data)
    {
        $db = \Config\Database::connect();
        $db->table('caja_chica_movimientos')->insert($data);

        $mov = $data['tipo'] == 'gasto' ? -$data['monto'] : $data['monto'];
        $db->table('caja')
            ->set('saldo_chica_actual', "saldo_chica_actual + ($mov)", false)
            ->where('id_caja', $data['id_caja'])
            ->update();
    }
    public function closeCaja($cajaId)
    {
        $db = \Config\Database::connect();
        $caja = $this->find($cajaId);
        if (!$caja) return false;

        // Get chica movements for this session
        $chicaMovs = $db->table('caja_chica_movimientos')
            ->where('id_caja', $cajaId)
            ->get()
            ->getResultArray();

        $totalChicaIngresos = 0;
        $totalChicaGastos = 0;
        foreach ($chicaMovs as $m) {
            if ($m['tipo'] == 'ingreso') $totalChicaIngresos += $m['monto'];
            elseif ($m['tipo'] == 'gasto') $totalChicaGastos += $m['monto'];
        }

        // General final = inherited initial + chica income - chica expenses
        $generalFinal = $caja['monto_inicial'] + $totalChicaIngresos - $totalChicaGastos;

        // Reset chica to fixed float
        $saldoChicaFinal = $caja['fondo_chica'];

        return $this->update($cajaId, [
            'fecha_cierre'      => date('Y-m-d H:i:s'),
            'monto_esperado'    => $generalFinal,
            'monto_real_cierre' => $generalFinal,
            'saldo_chica_actual'=> $saldoChicaFinal,
            'diferencia'        => 0,
            'estado'            => 'cerrado',
            'id_usuario_cierre' => session()->get('user_id')
        ]);
    }
}
