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

class OrdenCompra_model extends CI_Model {

    public function listar() {
        return $this->db
            ->select('
                oc.*,
                p.razon_social,
                p.nro_documento,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                u.usuario as usuario_creador
            ')
            ->from('lt_orden_compra oc')
            ->join('lt_proveedor p', 'p.id = oc.proveedor_id')
            ->join('estado e', 'e.id = oc.estado_id')
            ->join('usuarios u', 'u.id = oc.created_by', 'left')
            ->order_by('oc.id', 'DESC')
            ->get()
            ->result();
    }

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

    public function obtener_detalle($ordc_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                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_venta', 'left')
            ->where('d.ordc_id', $ordc_id)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }

    public function obtener_historial_estados($ordc_id) {
        return $this->db
            ->select('
                h.*,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                u.usuario
            ')
            ->from('lt_orden_compra_estado h')
            ->join('estado e', 'e.id = h.estado_id')
            ->join('usuarios u', 'u.id = h.usuario_id', 'left')
            ->where('h.ordc_id', $ordc_id)
            ->order_by('h.id', 'ASC')
            ->get()
            ->result();
    }

    public function obtener_completo($id) {
        return $this->db
            ->select('
                oc.*,
                p.razon_social,
                p.nro_documento,
                p.contacto,
                p.contacto_cargo,
                fp.nombre as forma_pago_nombre,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                u.usuario as usuario_creador
            ')
            ->from('lt_orden_compra oc')
            ->join('lt_proveedor p', 'p.id = oc.proveedor_id')
            ->join('mt_forma_pago fp', 'fp.id = oc.fp_id', 'left')
            ->join('estado e', 'e.id = oc.estado_id')
            ->join('usuarios u', 'u.id = oc.created_by', 'left')
            ->where('oc.id', $id)
            ->get()
            ->row();
    }

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

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

    public function insertar_estado($data) {
        return $this->db->insert('lt_orden_compra_estado', $data);
    }

    public function actualizar($id, $data) {
        return $this->db->where('id', $id)->update('lt_orden_compra', $data);
    }

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

    // ---------------------------------------------------------------
    // PROVEEDOR
    // ---------------------------------------------------------------
    public function buscar_proveedor($term) {
        $this->db->select('id, razon_social, nro_documento, fp_id, fp_descripcion, moneda_id, contacto, contacto_cargo');
        $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 obtener_proveedor($proveedor_id) {
        return $this->db
            ->select('p.*, fp.nombre as forma_pago_nombre, m.nombre as moneda_nombre, m.abreviado as moneda_abreviado')
            ->from('lt_proveedor p')
            ->join('mt_forma_pago fp', 'fp.id = p.fp_id', 'left')
            ->join('mt_moneda m', 'm.id = p.moneda_id', 'left')
            ->where('p.id', $proveedor_id)
            ->get()
            ->row();
    }

    // ---------------------------------------------------------------
    // PRODUCTO
    // ---------------------------------------------------------------
    public function buscar_producto($term) {
        $this->db->select('
            p.id, p.codigo, p.nombre, p.descripcion,
            um.nombre as unidad_nombre, um.abreviado as unidad_abreviado
        ');
        $this->db->from('vt_producto p');
        $this->db->join('mt_unidad_medida um', 'um.id = p.um_id_venta', 'left');
        $this->db->where('p.estado', 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();
    }

    public function obtener_producto($producto_id) {
        return $this->db
            ->select('p.*, um.nombre as unidad_nombre, um.abreviado as unidad_abreviado')
            ->from('vt_producto p')
            ->join('mt_unidad_medida um', 'um.id = p.um_id_venta', 'left')
            ->where('p.id', $producto_id)
            ->get()
            ->row();
    }

    // ---------------------------------------------------------------
    // REQUERIMIENTOS
    // ---------------------------------------------------------------
    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_in('r.estado_id', array(12, 13))
            ->order_by('r.id', 'DESC')
            ->get()
            ->result();
    }

    public function obtener_detalle_requerimiento($req_id) {
        return $this->db
            ->select('
                d.*,
                p.codigo as producto_codigo,
                p.nombre as producto_nombre,
                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_venta', 'left')
            ->where('d.req_id', $req_id)
            ->where('d.saldo >', 0)
            ->order_by('d.id', 'ASC')
            ->get()
            ->result();
    }

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

    public function obtener_tributo_igv() {
        return $this->db->where('estado', 1)->where('codigo', '1000')->get('mt_tributo')->row();
    }

    public function obtener_estado_por_tipo_codigo($tipo, $codigo) {
        return $this->db
            ->where('tipo', $tipo)
            ->where('codigo', $codigo)
            ->where('estado', 1)
            ->get('estado')
            ->row();
    }

    public function obtener_tipo_comprobante_oc() {
        return $this->db->where('id', 12)->get('mt_tipo_comprobante')->row();
    }

    public function incrementar_correlativo($id) {
        return $this->db->query(
            'UPDATE mt_tipo_comprobante SET correlativo_actual = correlativo_actual + 1 WHERE id = ?',
            array($id)
        );
    }

    public function listar_pendientes_autorizacion() {
        return $this->db
            ->select('
                oc.*,
                p.razon_social, p.nro_documento,
                e.nombre as estado_nombre, e.codigo as estado_codigo,
                u.usuario as usuario_creador
            ')
            ->from('lt_orden_compra oc')
            ->join('lt_proveedor p', 'p.id = oc.proveedor_id')
            ->join('estado e',       'e.id = oc.estado_id')
            ->join('usuarios u',     'u.id = oc.created_by', 'left')
            ->where('oc.estado_id', 17)
            ->order_by('oc.id', 'ASC')
            ->get()
            ->result();
    }

    // ---------------------------------------------------------------
    // MANEJO DE SALDO EN REQUERIMIENTO
    // ---------------------------------------------------------------
 
    // Descontar saldo al autorizar la OC
    public function descontar_saldo_requerimiento($ordc_id) {
        $detalle = $this->obtener_detalle($ordc_id);
 
        $requerimientos_afectados = array();
 
        foreach ($detalle as $item) {
            if (empty($item->req_id)) continue;
 
            // Buscar el item en lg_requerimiento_detalle que corresponde
            $req_det = $this->db
                ->where('req_id', $item->req_id)
                ->where('producto_id', $item->producto_id)
                ->where('saldo >', 0)
                ->get('lg_requerimiento_detalle')
                ->row();
 
            if (!$req_det) continue;
 
            $nuevo_saldo = max(0, (float)$req_det->saldo - (float)$item->cantidad);
 
            $this->db->where('id', $req_det->id)
                     ->update('lg_requerimiento_detalle', array(
                         'saldo'      => $nuevo_saldo,
                         'updated_at' => date('Y-m-d H:i:s'),
                         'updated_by' => $this->session->userdata('id')
                     ));
 
            if (!in_array($item->req_id, $requerimientos_afectados)) {
                $requerimientos_afectados[] = $item->req_id;
            }
        }
 
        // Actualizar estado de cada requerimiento afectado
        foreach ($requerimientos_afectados as $req_id) {
            $this->actualizar_estado_requerimiento($req_id);
        }
    }
 
    // Revertir saldo al anular una OC autorizada
    public function revertir_saldo_requerimiento($ordc_id) {
        $detalle = $this->obtener_detalle($ordc_id);
 
        $requerimientos_afectados = array();
 
        foreach ($detalle as $item) {
            if (empty($item->req_id)) continue;
 
            $req_det = $this->db
                ->where('req_id', $item->req_id)
                ->where('producto_id', $item->producto_id)
                ->get('lg_requerimiento_detalle')
                ->row();
 
            if (!$req_det) continue;
 
            $nuevo_saldo = (float)$req_det->saldo + (float)$item->cantidad;
            // No puede superar la cantidad original
            $nuevo_saldo = min($nuevo_saldo, (float)$req_det->cantidad);
 
            $this->db->where('id', $req_det->id)
                     ->update('lg_requerimiento_detalle', array(
                         'saldo'      => $nuevo_saldo,
                         'updated_at' => date('Y-m-d H:i:s'),
                         'updated_by' => $this->session->userdata('id')
                     ));
 
            if (!in_array($item->req_id, $requerimientos_afectados)) {
                $requerimientos_afectados[] = $item->req_id;
            }
        }
 
        foreach ($requerimientos_afectados as $req_id) {
            $this->actualizar_estado_requerimiento($req_id);
        }
    }
 
    // Calcular y actualizar estado del requerimiento
    public function actualizar_estado_requerimiento($req_id) {
        $items = $this->db
            ->where('req_id', $req_id)
            ->get('lg_requerimiento_detalle')
            ->result();
 
        if (empty($items)) return;
 
        $total_items  = count($items);
        $items_saldo0 = 0;
 
        foreach ($items as $item) {
            if ((float)$item->saldo == 0) {
                $items_saldo0++;
            }
        }
 
        if ($items_saldo0 == $total_items) {
            $nuevo_estado = 14; // ATENDIDO
        } elseif ($items_saldo0 > 0) {
            $nuevo_estado = 13; // PARCIAL
        } else {
            $nuevo_estado = 12; // POR ATENDER (sin cambios)
        }
 
        $this->db->where('id', $req_id)
                 ->update('lg_requerimiento', array(
                     'estado_id'  => $nuevo_estado,
                     'updated_at' => date('Y-m-d H:i:s'),
                     'updated_by' => $this->session->userdata('id')
                 ));
    }

    public function es_visador_oc($usuario_id) {
        $proceso_oc_id = 5;
        return $this->db
            ->where('proceso_id', $proceso_oc_id)
            ->where('usuario_id', $usuario_id)
            ->where('estado', 1)
            ->get('visadores')
            ->num_rows() > 0;
    }
}
