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

class ParteIngreso_model extends CI_Model {

    public function listar() {
        return $this->db
            ->select('
                pi.*,
                p.razon_social as proveedor,
                m.nombre as moneda,
                m.abreviado as moneda_abreviado,
                a.nombre as almacen,
                u.usuario as usuario_creador
            ')
            ->from('lt_parte_ingreso pi')
            ->join('lt_proveedor p',   'p.id = pi.proveedor_id', 'left')
            ->join('mt_moneda m',      'm.id = pi.moneda_id',    'left')
            ->join('mt_almacen a',     'a.id = pi.almacen_id')
            ->join('usuarios u',       'u.id = pi.created_by',   'left')
            ->order_by('pi.id', 'DESC')
            ->get()
            ->result();
    }

    public function obtener($id) {
        return $this->db->where('id', $id)->get('lt_parte_ingreso')->row();
    }

    public function obtener_completo($id) {
        return $this->db
            ->select('
                pi.*,
                p.razon_social as proveedor,
                p.nro_documento as proveedor_documento,
                m.nombre as moneda,
                m.abreviado as moneda_abreviado,
                a.nombre as almacen,
                u.usuario as usuario_creador
            ')
            ->from('lt_parte_ingreso pi')
            ->join('lt_proveedor p',   'p.id = pi.proveedor_id', 'left')
            ->join('mt_moneda m',      'm.id = pi.moneda_id',    'left')
            ->join('mt_almacen a',     'a.id = pi.almacen_id')
            ->join('usuarios u',       'u.id = pi.created_by',   'left')
            ->where('pi.id', $id)
            ->get()
            ->row();
    }

    public function obtener_detalle($pi_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                p.maneja_stock,
                um.abreviado as unidad_abreviado
            ')
            ->from('lt_parte_ingreso_det d')
            ->join('vt_producto p',        'p.id = d.producto_id')
            ->join('mt_unidad_medida um',  'um.id = p.um_id_compra', 'left')
            ->where('d.pi_id', $pi_id)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }

    public function insertar_cabecera($data) {
        $this->db->insert('lt_parte_ingreso', $data);
        return $this->db->insert_id();
    }

    public function insertar_detalle_batch($data) {
        return $this->db->insert_batch('lt_parte_ingreso_det', $data);
    }

    public function anular($id, $usuario_id) {
        return $this->db->where('id', $id)->update('lt_parte_ingreso', array(
            'estado'     => 0,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $usuario_id
        ));
    }

    public function eliminar_detalle($pi_id) {
        return $this->db->where('pi_id', $pi_id)->delete('lt_parte_ingreso_det');
    }

    // ---------------------------------------------------------------
    // STOCK - ACTUALIZAR CON PRECIO PROMEDIO PONDERADO
    // ---------------------------------------------------------------
    public function actualizar_stock($producto_id, $almacen_id, $cantidad, $precio_unitario) {
        $registro = $this->db
            ->where('producto_id', $producto_id)
            ->where('almacen_id', $almacen_id)
            ->get('vt_producto_almacen')
            ->row();

        if ($registro) {
            $stock_actual   = (float)$registro->cantidad_stock;
            $precio_actual  = (float)$registro->precio_promedio;
            $cant_ingreso   = (float)$cantidad;
            $precio_ingreso = (float)$precio_unitario;

            $nuevo_stock = $stock_actual + $cant_ingreso;

            if ($nuevo_stock > 0) {
                $nuevo_precio_promedio = round(
                    ($stock_actual * $precio_actual + $cant_ingreso * $precio_ingreso) / $nuevo_stock,
                    4
                );
            } else {
                $nuevo_precio_promedio = $precio_ingreso;
            }

            $this->db->where('producto_id', $producto_id)
                     ->where('almacen_id', $almacen_id)
                     ->update('vt_producto_almacen', array(
                         'cantidad_stock'  => $nuevo_stock,
                         'precio_promedio' => $nuevo_precio_promedio,
                         'updated_at'      => date('Y-m-d H:i:s'),
                         'updated_by'      => $this->session->userdata('id')
                     ));
        } else {
            // Si no existe el registro lo creamos
            $this->db->insert('vt_producto_almacen', array(
                'producto_id'          => $producto_id,
                'almacen_id'           => $almacen_id,
                'cantidad_stock'       => (float)$cantidad,
                'precio_promedio'      => round((float)$precio_unitario, 4),
                'cantidad_reposicion'  => 0,
                'cantidad_comprometida'=> 0,
                'cantidad_minima'      => 0,
                'cantidad_maxima'      => 0,
                'created_by'           => $this->session->userdata('id')
            ));
        }
    }

    // Revertir stock al anular el parte
    public function revertir_stock($producto_id, $almacen_id, $cantidad) {
        $registro = $this->db
            ->where('producto_id', $producto_id)
            ->where('almacen_id', $almacen_id)
            ->get('vt_producto_almacen')
            ->row();

        if (!$registro) return;

        $nuevo_stock = max(0, (float)$registro->cantidad_stock - (float)$cantidad);

        $this->db->where('producto_id', $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')
                 ));
    }

    // ---------------------------------------------------------------
    // AUXILIARES
    // ---------------------------------------------------------------
    public function listar_almacenes() {
        return $this->db->where('estado', 1)->order_by('nombre', 'ASC')->get('mt_almacen')->result();
    }

    public function listar_monedas() {
        return $this->db->where('estado', 1)->order_by('nombre', 'ASC')->get('mt_moneda')->result();
    }

    public function buscar_proveedor($term) {
        $this->db->select('id, razon_social, nro_documento');
        $this->db->from('lt_proveedor');
        $this->db->where('estado', 1);
        $this->db->group_start();
        $this->db->like('razon_social', $term);
        $this->db->or_like('nro_documento', $term);
        $this->db->group_end();
        $this->db->limit(20);
        return $this->db->get()->result();
    }

    public function buscar_producto($term) {
        $this->db->select('p.id, p.codigo, p.nombre, p.maneja_stock, um.abreviado as unidad_abreviado, p.precio_compra');
        $this->db->from('vt_producto p');
        $this->db->join('mt_unidad_medida um', 'um.id = p.um_id_compra', 'left');
        $this->db->where('p.estado', 1);
        $this->db->where('p.activo_compra', 1);
        $this->db->group_start();
        $this->db->like('p.codigo', $term);
        $this->db->or_like('p.nombre', $term);
        $this->db->group_end();
        $this->db->limit(20);
        return $this->db->get()->result();
    }

    // OC autorizadas disponibles para ingreso
    public function listar_oc_autorizadas() {
        return $this->db
            ->select('oc.id, oc.codigo, oc.fecha, p.razon_social')
            ->from('lt_orden_compra oc')
            ->join('lt_proveedor p', 'p.id = oc.proveedor_id')
            ->where_in('oc.estado_id', array(18, 19)) // AUTORIZADO o PARCIAL
            ->order_by('oc.id', 'DESC')
            ->get()
            ->result();
    }

    // Detalle de OC para cargar en el parte
    public function obtener_detalle_oc($ordc_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                p.maneja_stock,
                um.abreviado as unidad_abreviado
            ')
            ->from('lt_orden_compra_det d')
            ->join('vt_producto p',       'p.id = d.producto_id')
            ->join('mt_unidad_medida um', 'um.id = p.um_id_compra', 'left')
            ->where('d.ordc_id', $ordc_id)
            ->where('d.saldo >', 0)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }

    // Requerimientos con saldo pendiente
    public function listar_requerimientos_pendientes() {
        return $this->db
            ->select('r.id, r.fecha, e.nombre as estado_nombre, u.nombre as solicitante')
            ->from('lg_requerimiento r')
            ->join('estado e',    'e.id = r.estado_id')
            ->join('usuarios u',  'u.id = r.empleado_id', 'left')
            ->where('r.tipo', 'C')
            ->where_in('r.estado_id', array(12, 13))
            ->order_by('r.id', 'DESC')
            ->get()
            ->result();
    }

    // Detalle de requerimiento con saldo pendiente
    public function obtener_detalle_requerimiento($req_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                p.maneja_stock,
                um.abreviado as unidad_abreviado
            ')
            ->from('lg_requerimiento_detalle d')
            ->join('vt_producto p',       'p.id = d.producto_id')
            ->join('mt_unidad_medida um', 'um.id = p.um_id_compra', 'left')
            ->where('d.req_id', $req_id)
            ->where('d.saldo >', 0)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }

    // Actualizar saldo en OC al ingresar
    public function actualizar_saldo_oc($ordc_id, $producto_id, $cantidad_ingresada) {
        $det = $this->db
            ->where('ordc_id', $ordc_id)
            ->where('producto_id', $producto_id)
            ->where('saldo >', 0)
            ->get('lt_orden_compra_det')
            ->row();

        if (!$det) return;

        $nuevo_saldo = max(0, (float)$det->saldo - (float)$cantidad_ingresada);
        $nuevo_estado = ($nuevo_saldo == 0) ? 20 : 19; // INGRESADO o PARCIAL

        $this->db->where('id', $det->id)
                 ->update('lt_orden_compra_det', array('saldo' => $nuevo_saldo, 'estado_id' => $nuevo_estado));

        // Revisar si toda la OC está completamente ingresada
        $pendientes = $this->db
            ->where('ordc_id', $ordc_id)
            ->where('saldo >', 0)
            ->get('lt_orden_compra_det')
            ->num_rows();

        $nuevo_estado_oc = ($pendientes == 0) ? 20 : 19; // EJE o PAR
        $this->db->where('id', $ordc_id)
                 ->update('lt_orden_compra', array(
                     'estado_id'  => $nuevo_estado_oc,
                     'updated_at' => date('Y-m-d H:i:s'),
                     'updated_by' => $this->session->userdata('id')
                 ));
    }
}
