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

require APPPATH . 'libraries/RestController.php';
require APPPATH . 'libraries/Format.php';

use chriskacerguis\RestServer\RestController;

class Caja extends RestController
{

    function __construct()
    {
        parent::__construct();
        $this->load->helper('session');
        $this->load->model('caja_model');
        $this->load->model('tags_model');
        $this->load->model('tags_movimientos_model');
    }

    /**
     * Obtiene el estado actual de la caja
     */
    public function get_estado_actual_get()
    {
        $caja_actual = $this->caja_model->get_caja_actual();

        if ($caja_actual) {
            $this->response([
                'caja' => $caja_actual,
                'error' => false
            ], RestController::HTTP_OK);
        } else {
            $this->response([
                'message' => 'No hay caja abierta actualmente',
                'error' => false
            ], RestController::HTTP_OK);
        }
    }

    /**
     * Abre una nueva caja
     */
    public function abrir_caja_post()
    {
        // Verificar que no haya una caja abierta
        $caja_actual = $this->caja_model->get_caja_actual();
        if ($caja_actual) {
            $this->response([
                'message' => 'Ya existe una caja abierta',
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
            return;
        }

        $data = array(
            'saldo' => 0.00,
            'fecha_apertura' => date('Y-m-d H:i:s'),
            'usuario_id' => get_current_user_id(),
            'created_at' => date('Y-m-d H:i:s'),
            'status' => 1
        );

        $caja_id = $this->caja_model->abrir_caja($data);

        if ($caja_id) {
            $this->response([
                'message' => 'Caja abierta correctamente',
                'caja_id' => $caja_id,
                'error' => false
            ], RestController::HTTP_OK);
        } else {
            $this->response([
                'message' => 'Error al abrir la caja',
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
     * Realiza un retiro de caja
     */
    public function retiro_caja_post()
    {
        $this->_validate_retiro_data();

        // Verificar que hay una caja abierta
        $caja_actual = $this->caja_model->get_caja_actual();
        if (!$caja_actual) {
            $this->response([
                'message' => 'No hay caja abierta actualmente',
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
            return;
        }

        // Verificar que el monto no sea mayor al saldo
        $monto = $this->post('monto');
        if ($monto > $caja_actual['saldo']) {
            $this->response([
                'message' => 'El monto a retirar es mayor al saldo disponible',
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
            return;
        }

        $data = array(
            'caja_id' => $caja_actual['id'],
            'monto' => $monto,
            'saldo_anterior' => $caja_actual['saldo'],
            'saldo_nuevo' => $caja_actual['saldo'] - $monto,
            'concepto' => $this->post('concepto'),
            'observaciones' => $this->post('observaciones'),
            'referencia' => 'RT-' . date('YmdHis'),
            'usuario_id' => get_current_user_id(),
            'fecha_retiro' => date('Y-m-d H:i:s'),
            'created_at' => date('Y-m-d H:i:s'),
            'status' => 1
        );

        $retiro_id = $this->caja_model->registrar_retiro($data);

        if ($retiro_id) {
            $this->response([
                'message' => 'Retiro realizado correctamente',
                'retiro_id' => $retiro_id,
                'error' => false
            ], RestController::HTTP_OK);
        } else {
            $this->response([
                'message' => 'Error al realizar el retiro',
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
     * Realiza un arqueo de caja
     */
    public function arqueo_caja_post()
    {
        $this->_validate_arqueo_data();

        // Verificar que hay una caja abierta
        $caja_actual = $this->caja_model->get_caja_actual();
        if (!$caja_actual) {
            $this->response([
                'message' => 'No hay caja abierta actualmente',
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
            return;
        }

        $monto_fisico = $this->post('monto_fisico');
        $diferencia = $monto_fisico - $caja_actual['saldo'];

        $data = array(
            'caja_id' => $caja_actual['id'],
            'saldo_sistema' => $caja_actual['saldo'],
            'monto_fisico' => $monto_fisico,
            'diferencia' => $diferencia,
            'observaciones' => $this->post('observaciones'),
            'referencia' => 'AQ-' . date('YmdHis'),
            'usuario_id' => get_current_user_id(),
            'fecha_arqueo' => date('Y-m-d H:i:s'),
            'created_at' => date('Y-m-d H:i:s'),
            'status' => 1
        );

        $arqueo_id = $this->caja_model->registrar_arqueo($data);

        if ($arqueo_id) {
            $this->response([
                'message' => 'Arqueo realizado correctamente',
                'arqueo_id' => $arqueo_id,
                'error' => false
            ], RestController::HTTP_OK);
        } else {
            $this->response([
                'message' => 'Error al realizar el arqueo',
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
     * Cierra la caja actual
     */
    public function cerrar_caja_post()
    {
        // Verificar que hay una caja abierta
        $caja_actual = $this->caja_model->get_caja_actual();
        if (!$caja_actual) {
            $this->response([
                'message' => 'No hay caja abierta actualmente',
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
            return;
        }

        $data = array(
            'caja_id' => $caja_actual['id'],
            'saldo_final' => $caja_actual['saldo'],
            'observaciones' => $this->post('observaciones'),
            'referencia' => 'CC-' . date('YmdHis'),
            'usuario_id' => get_current_user_id(),
            'fecha_cierre' => date('Y-m-d H:i:s'),
            'created_at' => date('Y-m-d H:i:s'),
            'status' => 1
        );

        $cierre_id = $this->caja_model->registrar_cierre($data);

        if ($cierre_id) {
            // Actualizar caja con fecha de cierre
            $update_data = array(
                'fecha_cierre' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
                'status' => 0 // Inactiva
            );

            $this->caja_model->actualizar_caja($caja_actual['id'], $update_data);

            $this->response([
                'message' => 'Caja cerrada correctamente',
                'cierre_id' => $cierre_id,
                'error' => false
            ], RestController::HTTP_OK);
        } else {
            $this->response([
                'message' => 'Error al cerrar la caja',
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
     * Obtiene los movimientos de caja
     */
    public function get_movimientos_get()
    {
        $caja_id = $this->get('caja_id');
        $fecha_inicio = $this->get('fecha_inicio');
        $fecha_fin = $this->get('fecha_fin');

        $filtros = array();

        if ($caja_id) {
            $filtros['caja_id'] = $caja_id;
        }

        if ($fecha_inicio) {
            $filtros['fecha_inicio'] = $fecha_inicio;
        }

        if ($fecha_fin) {
            $filtros['fecha_fin'] = $fecha_fin;
        }

        $movimientos = $this->caja_model->get_movimientos_caja($filtros);
        $total = $this->caja_model->count_movimientos_caja($filtros);

        $this->response([
            'movimientos' => $movimientos,
            'total' => $total,
            'error' => false
        ], RestController::HTTP_OK);
    }

    /**
     * Obtiene los retiros de caja
     */
    public function get_retiros_get()
    {
        $caja_id = $this->get('caja_id');
        $fecha_inicio = $this->get('fecha_inicio');
        $fecha_fin = $this->get('fecha_fin');

        $filtros = array();

        if ($caja_id) {
            $filtros['caja_id'] = $caja_id;
        }

        if ($fecha_inicio) {
            $filtros['fecha_inicio'] = $fecha_inicio;
        }

        if ($fecha_fin) {
            $filtros['fecha_fin'] = $fecha_fin;
        }

        $retiros = $this->caja_model->get_retiros_caja($filtros);
        $total = $this->caja_model->count_retiros_caja($filtros);

        $this->response([
            'retiros' => $retiros,
            'total' => $total,
            'error' => false
        ], RestController::HTTP_OK);
    }

    /**
     * Exportar movimientos a Excel
     */
    public function export_movimientos_excel_get()
    {
        // Cargar helper URL si no lo está ya
        $this->load->helper('url');

        $caja_id = $this->get('caja_id');
        $fecha_inicio = $this->get('fecha_inicio');
        $fecha_fin = $this->get('fecha_fin');

        $filtros = array();

        if ($caja_id) {
            $filtros['caja_id'] = $caja_id;
        }

        if ($fecha_inicio) {
            $filtros['fecha_inicio'] = $fecha_inicio;
        }

        if ($fecha_fin) {
            $filtros['fecha_fin'] = $fecha_fin;
        }

        $movimientos = $this->caja_model->get_movimientos_caja($filtros);

        if (empty($movimientos)) {
            $this->response([
                'message' => 'No hay datos para exportar',
                'error' => true
            ], RestController::HTTP_OK);
            return;
        }

        try {
            require_once APPPATH . '../vendor/autoload.php';

            $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            $sheet = $spreadsheet->getActiveSheet();

            // Encabezados
            $sheet->setCellValue('A1', 'Referencia');
            $sheet->setCellValue('B1', 'Tipo');
            $sheet->setCellValue('C1', 'Monto');
            $sheet->setCellValue('D1', 'Saldo Anterior');
            $sheet->setCellValue('E1', 'Saldo Nuevo');
            $sheet->setCellValue('F1', 'Fecha');
            $sheet->setCellValue('G1', 'Usuario');

            // Estilo para encabezados
            $styleHeader = [
                'font' => [
                    'bold' => true,
                    'color' => ['rgb' => 'FFFFFF'],
                ],
                'fill' => [
                    'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
                    'color' => ['rgb' => '4F81BD'],
                ],
                'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                ],
            ];
            $sheet->getStyle('A1:G1')->applyFromArray($styleHeader);

            // Datos
            $row = 2;
            foreach ($movimientos as $mov) {
                $sheet->setCellValue('A' . $row, $mov['referencia']);
                $sheet->setCellValue('B' . $row, $mov['tipo_movimiento']);
                $sheet->setCellValue('C' . $row, $mov['monto']);
                $sheet->setCellValue('D' . $row, $mov['saldo_anterior']);
                $sheet->setCellValue('E' . $row, $mov['saldo_nuevo']);
                $sheet->setCellValue('F' . $row, date('d/m/Y H:i:s', strtotime($mov['fecha_movimiento'])));
                $sheet->setCellValue('G' . $row, isset($mov['nombre_usuario']) ? $mov['nombre_usuario'] : 'Usuario');
                $row++;
            }

            // Aplicar formato de moneda a columnas de montos
            $sheet->getStyle('C2:E' . ($row - 1))->getNumberFormat()->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_CURRENCY_USD_SIMPLE);

            // Autoajustar columnas
            foreach (range('A', 'G') as $col) {
                $sheet->getColumnDimension($col)->setAutoSize(true);
            }

            // Configurar el archivo para descarga directa
            $filename = 'movimientos_caja_' . date('YmdHis') . '.xlsx';

            // Configurar las cabeceras para descarga directa
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
            header('Content-Disposition: attachment;filename="' . $filename . '"');
            header('Cache-Control: max-age=0');

            // Crear el escritor y enviar la salida directamente al navegador
            $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
            $writer->save('php://output');
            exit;
        } catch (\Exception $e) {
            log_message('error', 'Error al generar Excel: ' . $e->getMessage());
            $this->response([
                'message' => 'Error al generar el Excel: ' . $e->getMessage(),
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
     * Exportar movimientos a PDF
     */
    public function export_movimientos_pdf_get()
    {
        // Cargar helper URL si no lo está ya
        $this->load->helper('url');

        $caja_id = $this->get('caja_id');
        $fecha_inicio = $this->get('fecha_inicio');
        $fecha_fin = $this->get('fecha_fin');

        $filtros = array();

        if ($caja_id) {
            $filtros['caja_id'] = $caja_id;
        }

        if ($fecha_inicio) {
            $filtros['fecha_inicio'] = $fecha_inicio;
        }

        if ($fecha_fin) {
            $filtros['fecha_fin'] = $fecha_fin;
        }

        $movimientos = $this->caja_model->get_movimientos_caja($filtros);

        if (empty($movimientos)) {
            $this->response([
                'message' => 'No hay datos para exportar',
                'error' => true
            ], RestController::HTTP_OK);
            return;
        }

        try {
            require_once APPPATH . '../vendor/autoload.php';

            // Configurar mPDF
            $mpdf = new \Mpdf\Mpdf([
                'format' => 'A4-L', // Formato apaisado
                'margin_left' => 15,
                'margin_right' => 15,
                'margin_top' => 15,
                'margin_bottom' => 15
            ]);

            // Título del documento
            $mpdf->SetTitle('Reporte de Movimientos de Caja');

            // Preparar datos para la vista
            $data = [
                'movimientos' => $movimientos,
                'filtros' => $filtros,
                'fecha_generacion' => date('Y-m-d H:i:s')
            ];

            // Cargar vista
            $html = $this->load->view('caja/reporte_movimientos_caja_pdf', $data, TRUE);

            // Escribir HTML al PDF
            $mpdf->WriteHTML($html);

            // Salida del PDF
            $filename = 'movimientos_caja_' . date('YmdHis') . '.pdf';
            $mpdf->Output($filename, \Mpdf\Output\Destination::DOWNLOAD);
            exit;
        } catch (\Exception $e) {
            log_message('error', 'Error al generar PDF: ' . $e->getMessage());
            $this->response([
                'message' => 'Error al generar el PDF: ' . $e->getMessage(),
                'error' => true
            ], RestController::HTTP_INTERNAL_ERROR);
        }
    }

    /**
 * Imprime comprobante de retiro
 */
public function print_retiro_get($retiro_id) {
    // Cargar helper URL si no lo está ya
    $this->load->helper('url');
    
    if (!$retiro_id) {
        $this->response([
            'message' => 'ID de retiro no proporcionado',
            'error' => true
        ], RestController::HTTP_BAD_REQUEST);
        return;
    }

    $retiro = $this->caja_model->get_retiro_by_id($retiro_id);
    
    if (!$retiro) {
        $this->response([
            'message' => 'Retiro no encontrado',
            'error' => true
        ], RestController::HTTP_NOT_FOUND);
        return;
    }

    try {
        require_once APPPATH . '../vendor/autoload.php';
        
        // Configuración para tickets térmicos
        $mpdf = new \Mpdf\Mpdf([
            'format' => [80, 150],
            'margin_left' => 5,
            'margin_right' => 5,
            'margin_top' => 5,
            'margin_bottom' => 5
        ]);
        
        // Preparar datos para la vista
        $data = [
            'retiro' => $retiro,
            'fecha_generacion' => date('Y-m-d H:i:s'),
            'base_url' => site_url() // Usar site_url() en lugar de base_url()
        ];
        
        // Cargar vista
        $html = $this->load->view('caja/ticket_retiro', $data, TRUE);
        
        $mpdf->WriteHTML($html);
        
        // Generar y mostrar PDF
        $filename = 'retiro_' . $retiro_id . '_' . date('YmdHis') . '.pdf';
        $mpdf->Output($filename, \Mpdf\Output\Destination::INLINE);
        exit;
        
    } catch (\Exception $e) {
        log_message('error', 'Error al generar ticket: ' . $e->getMessage());
        $this->response([
            'message' => 'Error al generar el ticket: ' . $e->getMessage(),
            'error' => true
        ], RestController::HTTP_INTERNAL_ERROR);
    }
}

    /**
     * Validaciones
     */
    private function _validate_retiro_data()
    {
        $this->load->library('form_validation');

        $this->form_validation->set_rules('monto', 'Monto', 'required|numeric|greater_than[0]');
        $this->form_validation->set_rules('concepto', 'Concepto', 'required|max_length[200]');

        if (!$this->form_validation->run()) {
            $this->response([
                'message' => validation_errors(),
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
        }
    }

    private function _validate_arqueo_data()
    {
        $this->load->library('form_validation');

        $this->form_validation->set_rules('monto_fisico', 'Monto físico', 'required|numeric|greater_than_equal[0]');

        if (!$this->form_validation->run()) {
            $this->response([
                'message' => validation_errors(),
                'error' => true
            ], RestController::HTTP_BAD_REQUEST);
        }
    }
}
