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

class NotaCredito extends MY_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->model('ventas/NotaCredito_model');
        $this->load->model('almacen/ParteIngreso_model');
        $this->load->helper('numero');
    }

    protected function validar_permiso_ajax($slug) {
        if (!tiene_permiso($slug)) {
            echo json_encode(array('status' => false, 'message' => 'No tienes permisos'));
            exit;
        }
    }

    // ---------------------------------------------------------------
    // LISTADO
    // ---------------------------------------------------------------
    public function index() {
        $this->validar_permiso('nota_credito_ver');

        $data['titulo'] = 'Notas de Crédito';
        $data['notas']  = $this->NotaCredito_model->listar();
        $this->layout('ventas/nota_credito/index', $data);
    }

    // ---------------------------------------------------------------
    // PANTALLA 1 — Selección tipo + comprobante
    // ---------------------------------------------------------------
    public function create() {
        $this->validar_permiso('nota_credito_crear');

        $data['titulo']   = 'Nueva Nota de Crédito';
        $data['tipos_nc'] = $this->NotaCredito_model->listar_tipos_nc();
        $this->layout('ventas/nota_credito/create_paso1', $data);
    }

    // ---------------------------------------------------------------
    // PANTALLA 2 — Formulario según grupo del tipo
    // ---------------------------------------------------------------
    public function create_paso2() {
        $this->validar_permiso('nota_credito_crear');

        $tipo_nc_id = $this->input->post('tipo_nc_id', TRUE);
        $comprob_id = $this->input->post('comprob_id', TRUE);
        $fecha      = $this->input->post('fecha', TRUE);

        if (!$tipo_nc_id || !$comprob_id || !$fecha) {
            $this->session->set_flashdata('error', 'Debe seleccionar tipo, comprobante y fecha');
            redirect('ventas/nota_credito/create');
        }

        $tipo_nc     = $this->db->where('id', $tipo_nc_id)->get('mt_tipo_nota_credito')->row();
        $comprobante = $this->NotaCredito_model->obtener_completo_comprobante($comprob_id);
        $items       = $this->NotaCredito_model->obtener_items_comprobante($comprob_id);
        $serie       = $this->NotaCredito_model->obtener_serie_nc($comprob_id);
        $numero      = $this->NotaCredito_model->siguiente_numero(3, $serie);

        // Determinar grupo
        $grupo = 'D';
        if (in_array($tipo_nc->codigo, $this->NotaCredito_model->grupo_a))     $grupo = 'A';
        elseif (in_array($tipo_nc->codigo, $this->NotaCredito_model->grupo_b)) $grupo = 'B';
        elseif (in_array($tipo_nc->codigo, $this->NotaCredito_model->grupo_c)) $grupo = 'C';

        $data['titulo']      = 'Nueva Nota de Crédito — ' . $tipo_nc->descripcion;
        $data['tipo_nc']     = $tipo_nc;
        $data['comprobante'] = $comprobante;
        $data['items']       = $items;
        $data['fecha']       = $fecha;
        $data['serie']       = $serie;
        $data['numero']      = $numero;
        $data['grupo']       = $grupo;
        $data['monedas']     = $this->NotaCredito_model->listar_monedas();

        $this->layout('ventas/nota_credito/create_paso2', $data);
    }

    // ---------------------------------------------------------------
    // GUARDAR
    // ---------------------------------------------------------------
    public function store() {
        $this->validar_permiso('nota_credito_crear');

        $tipo_nc_id = $this->input->post('tipo_nc_id', TRUE);
        $comprob_id = $this->input->post('comprob_id', TRUE);
        $fecha      = $this->input->post('fecha', TRUE);
        $serie      = $this->input->post('serie', TRUE);
        $numero     = $this->input->post('numero', TRUE);
        $moneda_id  = $this->input->post('moneda_id', TRUE);
        $tipocambio = (float)$this->input->post('tipocambio', TRUE);
        $subtotal   = (float)$this->input->post('subtotal', TRUE);
        $igv_porc   = (float)$this->input->post('igv_porcentaje', TRUE);
        $igv        = (float)$this->input->post('igv', TRUE);
        $total      = (float)$this->input->post('total', TRUE);
        $sustento   = trim($this->input->post('sustento', TRUE));
        $cliente_id = $this->input->post('cliente_id', TRUE);
        $detalle    = $this->input->post('detalle');

        if (!$tipo_nc_id || !$comprob_id || !$fecha || !$cliente_id) {
            $this->session->set_flashdata('error', 'Faltan datos obligatorios');
            redirect('ventas/nota_credito/create');
        }

        // Determinar grupo del tipo NC
        $tipo_nc_obj  = $this->db->where('id', $tipo_nc_id)->get('mt_tipo_nota_credito')->row();
        $codigo_tipo  = $tipo_nc_obj ? $tipo_nc_obj->codigo : '';
        $grupo_a      = array('01','02','06');
        $grupo_b      = array('05','07','09');
        $afecta_stock = in_array($codigo_tipo, array_merge($grupo_a, $grupo_b));
        $anula_total  = in_array($codigo_tipo, $grupo_a);

        // Obtener almacen_id del comprobante
        $comprob_data = $this->db->select('almacen_id')->where('id', $comprob_id)->get('vt_comprobante')->row();
        $almacen_id   = $comprob_data ? $comprob_data->almacen_id : 1;

        $cabecera = array(
            'tipo_nc_id'     => $tipo_nc_id,
            'serie'          => $serie,
            'numero'         => $numero,
            'comprob_id'     => $comprob_id,
            'cliente_id'     => $cliente_id,
            'fecha'          => $fecha,
            'moneda_id'      => $moneda_id,
            'tipocambio'     => $tipocambio,
            'subtotal'       => $subtotal,
            'igv_porcentaje' => $igv_porc,
            'igv'            => $igv,
            'total'          => $total,
            'sustento'       => $sustento !== '' ? $sustento : null,
            'envio_sunat'    => 0,
            'estado'         => 1,
            'created_by'     => $this->session->userdata('id')
        );

        $this->db->trans_begin();

        $nc_id = $this->NotaCredito_model->insertar($cabecera);

        if (!$nc_id) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo registrar la nota de crédito');
            redirect('ventas/nota_credito/create');
        }

        // Construir e insertar detalle
        $detalleInsert = array();
        if (!empty($detalle) && is_array($detalle)) {
            foreach ($detalle as $item) {
                $cantidad = (float)($item['cantidad'] ?? 0);
                $precio   = (float)($item['precio_unitario'] ?? 0);
                if ($cantidad <= 0 || !isset($item['producto_id'])) continue;

                $subtotal_item = round($cantidad * $precio, 2);
                $igv_item      = round($subtotal_item * ($igv_porc / 100), 2);
                $total_item    = round($subtotal_item + $igv_item, 2);

                $detalleInsert[] = array(
                    'nc_id'               => $nc_id,
                    'producto_id'         => $item['producto_id'],
                    'descripcion'         => $item['descripcion'] ?? null,
                    'cantidad'            => $cantidad,
                    'precio_unitario'     => $precio,
                    'tipo_afectacion_igv' => $item['tipo_afectacion_igv'] ?? '10',
                    'igv'                 => $igv_item,
                    'subtotal'            => $subtotal_item,
                    'total'               => $total_item
                );
            }
            if (!empty($detalleInsert)) {
                $this->NotaCredito_model->insertar_detalle_batch($detalleInsert);
            }
        }

        // ---------------------------------------------------------------
        // GENERAR PARTE DE INGRESO TIPO R (REINGRESO) Y ACTUALIZAR STOCK
        // Solo para Grupo A y B que afectan cantidades
        // ---------------------------------------------------------------
        if ($afecta_stock && !empty($detalleInsert)) {

            // Cabecera del Parte de Ingreso
            $observacion_pi = 'Reingreso por NC ' . $serie . '-' . $numero . ' — ' . $tipo_nc_obj->descripcion;

            $this->db->insert('lt_parte_ingreso', array(
                'tipoingreso'   => 'R',
                'almacen_id'    => $almacen_id,
                'fecha'         => $fecha,
                'proveedor_id'  => null,
                'ordc_id'       => null,
                'observaciones' => $observacion_pi,
                'facturado'     => 0,
                'estado'        => 1,
                'created_by'    => $this->session->userdata('id')
            ));
            $pi_id = $this->db->insert_id();

            foreach ($detalleInsert as $d) {
                // Obtener precio promedio y stock actual
                $reg = $this->db
                    ->where('producto_id', $d['producto_id'])
                    ->where('almacen_id', $almacen_id)
                    ->get('vt_producto_almacen')->row();

                $precio_promedio = $reg ? (float)$reg->precio_promedio : (float)$d['precio_unitario'];
                $stock_actual    = $reg ? (float)$reg->cantidad_stock   : 0;
                $cantidad        = (float)$d['cantidad'];

                // Insertar detalle del parte de ingreso
                $this->db->insert('lt_parte_ingreso_det', array(
                    'pi_id'           => $pi_id,
                    'producto_id'     => $d['producto_id'],
                    'cantidad'        => $cantidad,
                    'precio_unitario' => $precio_promedio,
                    'subtotal'        => round($cantidad * $precio_promedio, 2)
                ));

                // Calcular nuevo stock y precio promedio ponderado
                $nuevo_stock = $stock_actual + $cantidad;
                $nuevo_precio = $nuevo_stock > 0
                    ? round((($stock_actual * $precio_promedio) + ($cantidad * $precio_promedio)) / $nuevo_stock, 4)
                    : $precio_promedio;

                if ($reg) {
                    $this->db->where('producto_id', $d['producto_id'])
                             ->where('almacen_id', $almacen_id)
                             ->update('vt_producto_almacen', array(
                                 'cantidad_stock'  => $nuevo_stock,
                                 'precio_promedio' => $nuevo_precio,
                                 'updated_at'      => date('Y-m-d H:i:s'),
                                 'updated_by'      => $this->session->userdata('id')
                             ));
                } else {
                    $this->db->insert('vt_producto_almacen', array(
                        'producto_id'           => $d['producto_id'],
                        'almacen_id'            => $almacen_id,
                        'cantidad_stock'        => $cantidad,
                        'precio_promedio'       => $precio_promedio,
                        'cantidad_reposicion'   => 0,
                        'cantidad_comprometida' => 0,
                        'cantidad_minima'       => 0,
                        'cantidad_maxima'       => 0,
                        'created_by'            => $this->session->userdata('id')
                    ));
                }
            }
        }

        // ---------------------------------------------------------------
        // Si es anulación total (Grupo A) cambiar estado comprobante a ANULADO (24)
        // ---------------------------------------------------------------
        if ($anula_total) {
            $this->db->where('id', $comprob_id)->update('vt_comprobante', array(
                'estado_id'  => 24,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));

            $this->db->insert('vt_comprobante_estado', array(
                'comprob_id'          => $comprob_id,
                'estado_id'           => 24,
                'comprob_fechaestado' => date('Y-m-d H:i:s'),
                'usuario_id'          => $this->session->userdata('id')
            ));
        }

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'Error al guardar la nota de crédito');
            redirect('ventas/nota_credito/create');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Nota de Crédito ' . $serie . '-' . $numero . ' registrada correctamente');
        redirect('ventas/nota_credito/ver/' . $nc_id);
    }

    // ---------------------------------------------------------------
    // VER
    // ---------------------------------------------------------------
    public function ver($id) {
        $this->validar_permiso('nota_credito_ver');

        $nc = $this->NotaCredito_model->obtener_completo($id);
        if (!$nc) show_404();

        $data['titulo']  = 'Nota de Crédito ' . $nc->serie . '-' . $nc->numero;
        $data['nc']      = $nc;
        $data['detalle'] = $this->NotaCredito_model->obtener_detalle($id);
        $this->layout('ventas/nota_credito/ver', $data);
    }

    // ---------------------------------------------------------------
    // IMPRIMIR
    // ---------------------------------------------------------------
    public function print_nc($id) {
        $this->validar_permiso('nota_credito_ver');

        $nc = $this->NotaCredito_model->obtener_completo($id);
        if (!$nc) show_404();

        $empresa       = $this->db->get('empresa')->row();
        $montoEnLetras = numero_a_letras((float)$nc->total, !empty($nc->moneda) ? $nc->moneda : 'SOLES');

        $data['nc']            = $nc;
        $data['detalle']       = $this->NotaCredito_model->obtener_detalle($id);
        $data['empresa']       = $empresa;
        $data['montoEnLetras'] = $montoEnLetras;

        $this->load->view('ventas/nota_credito/print', $data);
    }

    // ---------------------------------------------------------------
    // ANULAR
    // ---------------------------------------------------------------
    public function anular($id) {
        $this->validar_permiso('nota_credito_anular');

        $nc = $this->NotaCredito_model->obtener($id);
        if (!$nc) show_404();

        if ($nc->estado == 0) {
            $this->session->set_flashdata('error', 'La nota de crédito ya está anulada');
            redirect('ventas/nota_credito');
        }

        if ($nc->envio_sunat == 1) {
            $this->session->set_flashdata('error', 'No se puede anular una nota de crédito ya enviada a SUNAT');
            redirect('ventas/nota_credito');
        }

        $tipo_nc_obj  = $this->db->where('id', $nc->tipo_nc_id)->get('mt_tipo_nota_credito')->row();
        $codigo_tipo  = $tipo_nc_obj ? $tipo_nc_obj->codigo : '';
        $grupo_a      = array('01','02','06');
        $grupo_b      = array('05','07','09');
        $afecta_stock = in_array($codigo_tipo, array_merge($grupo_a, $grupo_b));
        $anula_total  = in_array($codigo_tipo, $grupo_a);

        $this->db->trans_begin();

        // Revertir parte de ingreso si la NC afectó stock
        if ($afecta_stock) {
            $observacion_pi = 'Reingreso por NC ' . $nc->serie . '-' . $nc->numero . ' — ' . $tipo_nc_obj->descripcion;

            $pi = $this->db
                ->where('observaciones', $observacion_pi)
                ->where('estado', 1)
                ->get('lt_parte_ingreso')->row();

            if ($pi) {
                $comprob_data = $this->db->select('almacen_id')->where('id', $nc->comprob_id)->get('vt_comprobante')->row();
                $almacen_id   = $comprob_data ? $comprob_data->almacen_id : 1;

                $det_pi = $this->db->where('pi_id', $pi->id)->get('lt_parte_ingreso_det')->result();

                foreach ($det_pi as $d) {
                    $reg = $this->db
                        ->where('producto_id', $d->producto_id)
                        ->where('almacen_id', $almacen_id)
                        ->get('vt_producto_almacen')->row();

                    if ($reg) {
                        $nuevo_stock = max(0, round((float)$reg->cantidad_stock - (float)$d->cantidad, 2));
                        $this->db->where('producto_id', $d->producto_id)
                                 ->where('almacen_id', $almacen_id)
                                 ->update('vt_producto_almacen', array(
                                     'cantidad_stock' => $nuevo_stock,
                                     'updated_at'     => date('Y-m-d H:i:s'),
                                     'updated_by'     => $this->session->userdata('id')
                                 ));
                    }
                }

                // Anular el parte de ingreso
                $this->db->where('id', $pi->id)->update('lt_parte_ingreso', array(
                    'estado'     => 0,
                    'updated_at' => date('Y-m-d H:i:s'),
                    'updated_by' => $this->session->userdata('id')
                ));
            }
        }

        // Si era anulación total, revertir estado del comprobante a EMITIDO (23)
        if ($anula_total) {
            $this->db->where('id', $nc->comprob_id)->update('vt_comprobante', array(
                'estado_id'  => 23,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));
        }

        // Anular la NC
        $this->NotaCredito_model->actualizar($id, array(
            'estado'     => 0,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        ));

        if ($this->db->trans_status() === FALSE) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo anular la nota de crédito');
            redirect('ventas/nota_credito');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Nota de crédito anulada correctamente');
        redirect('ventas/nota_credito');
    }

    // ---------------------------------------------------------------
    // AJAX — buscar comprobante
    // ---------------------------------------------------------------
    public function buscar_comprobante() {
        $this->validar_permiso_ajax('nota_credito_crear');
        $term = trim($this->input->get('term', TRUE));
        if (strlen($term) < 2) { echo json_encode(array()); return; }

        $comprobantes = $this->NotaCredito_model->buscar_comprobante($term);
        $resultado    = array();
        foreach ($comprobantes as $item) {
            $resultado[] = array(
                'id'               => $item->id,
                'label'            => $item->serie . '-' . $item->numero . ' | ' . $item->cliente . ' | S/ ' . number_format((float)$item->total, 2),
                'value'            => $item->serie . '-' . $item->numero,
                'serie'            => $item->serie,
                'numero'           => $item->numero,
                'cliente'          => $item->cliente,
                'cliente_ruc'      => $item->cliente_ruc,
                'cliente_id'       => $item->cliente_id,
                'fecha'            => $item->fecha,
                'total'            => number_format((float)$item->total, 2),
                'moneda_id'        => $item->moneda_id,
                'moneda'           => $item->moneda,
                'tipo_comprobante' => $item->tipo_comprobante
            );
        }
        echo json_encode($resultado);
    }
}
