<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Caja_model extends CI_Model {
    
    public function __construct() {
        parent::__construct();
        $this->load->database();
        $this->table_caja = 'caja';
        $this->table_movimientos = 'caja_movimientos';
        $this->table_retiros = 'caja_retiros';
        $this->table_arqueos = 'caja_arqueos';
        $this->table_cierres = 'caja_cierres';
    }

    /**
     * Obtiene la caja actualmente abierta
     */
    public function get_caja_actual() {
        $this->db->select('*');
        $this->db->from($this->table_caja);
        $this->db->where('fecha_cierre IS NULL');
        $this->db->where('status', 1);
        $this->db->order_by('id', 'DESC');
        $this->db->limit(1);
        
        $query = $this->db->get();
        
        if ($query->num_rows() > 0) {
            return $query->row_array();
        }
        
        return NULL;
    }
    
    /**
     * Abre una nueva caja
     */
    public function abrir_caja($data) {
        if ($this->db->insert($this->table_caja, $data)) {
            $id = $this->db->insert_id();
            if (create_log($this->table_caja, $id, $data)) {
                return $id;
            }
        }
        return FALSE;
    }
    
    /**
     * Actualiza una caja existente
     */
    public function actualizar_caja($caja_id, $data) {
        $data['updated_at'] = date('Y-m-d H:i:s');
        
        $this->db->where('id', $caja_id);
        if ($this->db->update($this->table_caja, $data)) {
            if (create_log($this->table_caja, $caja_id, $data)) {
                return TRUE;
            }
        }
        return FALSE;
    }
    
    /**
     * Registra un movimiento en caja
     */
    public function registrar_movimiento($data) {
        $this->db->trans_begin();
        
        // Insertar movimiento
        $this->db->insert($this->table_movimientos, $data);
        $movimiento_id = $this->db->insert_id();
        
        // Actualizar saldo de caja
        $update_data = array(
            'saldo' => $data['saldo_nuevo'],
            'updated_at' => date('Y-m-d H:i:s')
        );
        
        $this->db->where('id', $data['caja_id']);
        $this->db->update($this->table_caja, $update_data);
        
        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            return FALSE;
        } else {
            $this->db->trans_commit();
            return $movimiento_id;
        }
    }
    
    /**
     * Registra un retiro de caja
     */
    public function registrar_retiro($data) {
        $this->db->trans_begin();
        
        // Insertar retiro
        $this->db->insert($this->table_retiros, $data);
        $retiro_id = $this->db->insert_id();
        
        // Registrar movimiento de caja
        $movimiento_data = array(
            'caja_id' => $data['caja_id'],
            'tipo_movimiento' => 'RETIRO',
            'monto' => $data['monto'],
            'saldo_anterior' => $data['saldo_anterior'],
            'saldo_nuevo' => $data['saldo_nuevo'],
            'referencia' => $data['referencia'],
            'detalle_id' => $retiro_id,
            'usuario_id' => $data['usuario_id'],
            'fecha_movimiento' => $data['fecha_retiro'],
            'created_at' => date('Y-m-d H:i:s')
        );
        
        $this->db->insert($this->table_movimientos, $movimiento_data);
        
        // Actualizar saldo de caja
        $update_data = array(
            'saldo' => $data['saldo_nuevo'],
            'updated_at' => date('Y-m-d H:i:s')
        );
        
        $this->db->where('id', $data['caja_id']);
        $this->db->update($this->table_caja, $update_data);
        
        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            return FALSE;
        } else {
            $this->db->trans_commit();
            return $retiro_id;
        }
    }
    
    /**
     * Registra un arqueo de caja
     */
    public function registrar_arqueo($data) {
        if ($this->db->insert($this->table_arqueos, $data)) {
            $id = $this->db->insert_id();
            if (create_log($this->table_arqueos, $id, $data)) {
                return $id;
            }
        }
        return FALSE;
    }
    
    /**
     * Registra un cierre de caja
     */
    public function registrar_cierre($data) {
        if ($this->db->insert($this->table_cierres, $data)) {
            $id = $this->db->insert_id();
            if (create_log($this->table_cierres, $id, $data)) {
                return $id;
            }
        }
        return FALSE;
    }
    
    /**
     * Obtiene los movimientos de caja con filtros
     */
    public function get_movimientos_caja($filtros = array()) {
        // Primero realizamos una consulta para ver la estructura de la tabla usuarios
        $usuario_fields = $this->db->list_fields('usuarios');
        
        // Seleccionamos las columnas básicas
        $this->db->select('cm.*');
        
        // Determinamos el nombre de la columna correcta para el nombre de usuario
        if (in_array('nombre_completo', $usuario_fields)) {
            $this->db->select('u.nombre_completo as nombre_usuario');
        } elseif (in_array('nombre_usuario', $usuario_fields)) {
            $this->db->select('u.nombre_usuario as nombre_usuario');
        } elseif (in_array('nombre', $usuario_fields) && in_array('apellido', $usuario_fields)) {
            $this->db->select("CONCAT(u.nombre, ' ', u.apellido) as nombre_usuario");
        } else {
            // Si no encontramos ningún campo adecuado, usamos el ID como nombre de usuario
            $this->db->select('u.id as nombre_usuario');
        }
        
        $this->db->from($this->table_movimientos . ' cm');
        $this->db->join('usuarios u', 'u.id = cm.usuario_id', 'left');
        
        // Aplicar filtros
        if (!empty($filtros['caja_id'])) {
            $this->db->where('cm.caja_id', $filtros['caja_id']);
        }
        
        if (!empty($filtros['fecha_inicio'])) {
            $this->db->where('DATE(cm.fecha_movimiento) >=', $filtros['fecha_inicio']);
        }
        
        if (!empty($filtros['fecha_fin'])) {
            $this->db->where('DATE(cm.fecha_movimiento) <=', $filtros['fecha_fin']);
        }
        
        $this->db->order_by('cm.fecha_movimiento', 'DESC');
        
        $query = $this->db->get();
        return $query->result_array();
    }
    
    /**
     * Cuenta total de movimientos para paginación
     */
    public function count_movimientos_caja($filtros = array()) {
        $this->db->select('COUNT(*) as total');
        $this->db->from($this->table_movimientos . ' cm');
        
        // Aplicar filtros
        if (!empty($filtros['caja_id'])) {
            $this->db->where('cm.caja_id', $filtros['caja_id']);
        }
        
        if (!empty($filtros['fecha_inicio'])) {
            $this->db->where('DATE(cm.fecha_movimiento) >=', $filtros['fecha_inicio']);
        }
        
        if (!empty($filtros['fecha_fin'])) {
            $this->db->where('DATE(cm.fecha_movimiento) <=', $filtros['fecha_fin']);
        }
        
        $query = $this->db->get();
        $result = $query->row_array();
        return $result['total'];
    }
    
    /**
     * Obtiene los retiros de caja con filtros
     */
    public function get_retiros_caja($filtros = array()) {
        // Primero realizamos una consulta para ver la estructura de la tabla usuarios
        $usuario_fields = $this->db->list_fields('usuarios');
        
        // Seleccionamos las columnas básicas
        $this->db->select('cr.*');
        
        // Determinamos el nombre de la columna correcta para el nombre de usuario
        if (in_array('nombre_completo', $usuario_fields)) {
            $this->db->select('u.nombre_completo as nombre_usuario');
        } elseif (in_array('nombre_usuario', $usuario_fields)) {
            $this->db->select('u.nombre_usuario as nombre_usuario');
        } elseif (in_array('nombre', $usuario_fields) && in_array('apellido', $usuario_fields)) {
            $this->db->select("CONCAT(u.nombre, ' ', u.apellido) as nombre_usuario");
        } else {
            // Si no encontramos ningún campo adecuado, usamos el ID como nombre de usuario
            $this->db->select('u.id as nombre_usuario');
        }
        
        $this->db->from($this->table_retiros . ' cr');
        $this->db->join('usuarios u', 'u.id = cr.usuario_id', 'left');
        
        // Aplicar filtros
        if (!empty($filtros['caja_id'])) {
            $this->db->where('cr.caja_id', $filtros['caja_id']);
        }
        
        if (!empty($filtros['fecha_inicio'])) {
            $this->db->where('DATE(cr.fecha_retiro) >=', $filtros['fecha_inicio']);
        }
        
        if (!empty($filtros['fecha_fin'])) {
            $this->db->where('DATE(cr.fecha_retiro) <=', $filtros['fecha_fin']);
        }
        
        $this->db->where('cr.status', 1);
        $this->db->order_by('cr.fecha_retiro', 'DESC');
        
        $query = $this->db->get();
        return $query->result_array();
    }
    
    /**
     * Cuenta total de retiros para paginación
     */
    public function count_retiros_caja($filtros = array()) {
        $this->db->select('COUNT(*) as total');
        $this->db->from($this->table_retiros . ' cr');
        
        // Aplicar filtros
        if (!empty($filtros['caja_id'])) {
            $this->db->where('cr.caja_id', $filtros['caja_id']);
        }
        
        if (!empty($filtros['fecha_inicio'])) {
            $this->db->where('DATE(cr.fecha_retiro) >=', $filtros['fecha_inicio']);
        }
        
        if (!empty($filtros['fecha_fin'])) {
            $this->db->where('DATE(cr.fecha_retiro) <=', $filtros['fecha_fin']);
        }
        
        $this->db->where('cr.status', 1);
        
        $query = $this->db->get();
        $result = $query->row_array();
        return $result['total'];
    }
    
    /**
     * Obtiene un retiro específico por ID
     */
    public function get_retiro_by_id($retiro_id) {
        // Primero realizamos una consulta para ver la estructura de la tabla usuarios
        $usuario_fields = $this->db->list_fields('usuarios');
        
        // Seleccionamos las columnas básicas
        $this->db->select('cr.*, c.saldo as saldo_actual');
        
        // Determinamos el nombre de la columna correcta para el nombre de usuario
        if (in_array('nombre_completo', $usuario_fields)) {
            $this->db->select('u.nombre_completo as nombre_usuario');
        } elseif (in_array('nombre_usuario', $usuario_fields)) {
            $this->db->select('u.nombre_usuario as nombre_usuario');
        } elseif (in_array('nombre', $usuario_fields) && in_array('apellido', $usuario_fields)) {
            $this->db->select("CONCAT(u.nombre, ' ', u.apellido) as nombre_usuario");
        } else {
            // Si no encontramos ningún campo adecuado, usamos el ID como nombre de usuario
            $this->db->select('u.id as nombre_usuario');
        }
        
        $this->db->from($this->table_retiros . ' cr');
        $this->db->join('usuarios u', 'u.id = cr.usuario_id', 'left');
        $this->db->join($this->table_caja . ' c', 'c.id = cr.caja_id');
        $this->db->where('cr.id', $retiro_id);
        
        $query = $this->db->get();
        
        if ($query->num_rows() > 0) {
            return $query->row_array();
        }
        
        return NULL;
    }
}