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

class Costos_model extends CI_Model {

    // =========================================================
    // INSUMOS
    // =========================================================

    public function listar_insumos($solo_activos = true) {
        $this->db
            ->select('i.*, um.abreviado as um_abreviado, um.nombre as um_nombre,
                      m.abreviado as moneda_abrev,
                      p.razon_social as proveedor_nombre')
            ->from('cs_insumo i')
            ->join('mt_unidad_medida um', 'um.id = i.um_id')
            ->join('mt_moneda m',         'm.id  = i.moneda_id')
            ->join('lt_proveedor p',      'p.id  = i.proveedor_id', 'left')
            ->order_by('i.nombre');

        if ($solo_activos) $this->db->where('i.estado', 1);

        return $this->db->get()->result();
    }

    public function obtener_insumo($id) {
        return $this->db
            ->select('i.*, um.abreviado as um_abreviado, m.abreviado as moneda_abrev,
                      p.razon_social as proveedor_nombre')
            ->from('cs_insumo i')
            ->join('mt_unidad_medida um', 'um.id = i.um_id')
            ->join('mt_moneda m',         'm.id  = i.moneda_id')
            ->join('lt_proveedor p',      'p.id  = i.proveedor_id', 'left')
            ->where('i.id', $id)
            ->get()
            ->row();
    }

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

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

    // =========================================================
    // PROCESOS
    // =========================================================

    public function listar_procesos($solo_activos = true) {
        if ($solo_activos) $this->db->where('estado', 1);

        return $this->db
            ->order_by('es_tercerizado, nombre')
            ->get('cs_proceso')
            ->result();
    }

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

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

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

    // =========================================================
    // GASTOS FIJOS
    // =========================================================

    public function listar_gastos_fijos($solo_activos = true) {
        if ($solo_activos) $this->db->where('g.estado', 1);

        return $this->db
            ->select('g.*, m.abreviado as moneda_abrev')
            ->from('cs_gasto_fijo g')
            ->join('mt_moneda m', 'm.id = g.moneda_id')
            ->order_by('g.nombre')
            ->get()
            ->result();
    }

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

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

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

    // =========================================================
    // PRODUCTOS (vt_producto — tabla existente)
    // =========================================================

    public function listar_productos_activos() {
        return $this->db
            ->select('id, codigo, nombre')
            ->where('estado', 1)
            ->order_by('nombre')
            ->get('vt_producto')
            ->result();
    }

    public function listar_productos_con_hoja() {
        return $this->db
            ->select('p.id, p.codigo, p.nombre, p.precio_unidad,
                      COUNT(h.id) as total_hojas,
                      MAX(h.id) as hoja_principal_id')
            ->from('vt_producto p')
            ->join('cs_hoja_costo h', 'h.producto_id = p.id AND h.estado = 1', 'left')
            ->where('p.estado', 1)
            ->group_by('p.id')
            ->order_by('p.nombre')
            ->get()
            ->result();
    }

    public function obtener_producto_vt($id) {
        return $this->db
            ->select('p.*, c.nombre as categoria_nombre, um.abreviado as um_venta_abrev')
            ->from('vt_producto p')
            ->join('mt_producto_categoria c',  'c.id  = p.categoria_id',  'left')
            ->join('mt_unidad_medida um',       'um.id = p.um_id_venta',   'left')
            ->where('p.id', $id)
            ->get()
            ->row();
    }

    // =========================================================
    // HOJAS DE COSTOS
    // =========================================================

    public function listar_hojas_por_producto($producto_id) {
        return $this->db
            ->where('producto_id', $producto_id)
            ->where('estado', 1)
            ->get('cs_hoja_costo')
            ->result();
    }

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

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

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

    // =========================================================
    // DETALLE: insumos de la hoja
    // =========================================================

    public function obtener_hoja_insumos($hoja_id) {
        return $this->db
            ->select('hi.*, i.nombre as insumo_nombre, i.precio_unitario,
                      um.abreviado as um_abreviado,
                      (i.precio_unitario * hi.cantidad / hi.rendimiento) as costo_unitario')
            ->from('cs_hoja_insumo hi')
            ->join('cs_insumo i',        'i.id  = hi.insumo_id')
            ->join('mt_unidad_medida um', 'um.id = i.um_id')
            ->where('hi.hoja_id', $hoja_id)
            ->get()
            ->result();
    }

    public function guardar_hoja_insumo($data) {
        $existe = $this->db
            ->where('hoja_id',   $data['hoja_id'])
            ->where('insumo_id', $data['insumo_id'])
            ->get('cs_hoja_insumo')
            ->row();

        if ($existe) {
            return $this->db->where('id', $existe->id)->update('cs_hoja_insumo', $data);
        }

        $this->db->insert('cs_hoja_insumo', $data);
        return $this->db->insert_id();
    }

    public function eliminar_hoja_insumo($id) {
        return $this->db->where('id', $id)->delete('cs_hoja_insumo');
    }

    // =========================================================
    // DETALLE: procesos de la hoja
    // =========================================================

    public function obtener_hoja_procesos($hoja_id) {
        return $this->db
            ->select('hp.*, pr.nombre as proceso_nombre, pr.tipo_costo,
                      pr.costo as costo_base, pr.lote_cantidad, pr.es_tercerizado')
            ->from('cs_hoja_proceso hp')
            ->join('cs_proceso pr', 'pr.id = hp.proceso_id')
            ->where('hp.hoja_id', $hoja_id)
            ->get()
            ->result();
    }

    public function guardar_hoja_proceso($data) {
        $existe = $this->db
            ->where('hoja_id',    $data['hoja_id'])
            ->where('proceso_id', $data['proceso_id'])
            ->get('cs_hoja_proceso')
            ->row();

        if ($existe) {
            return $this->db->where('id', $existe->id)->update('cs_hoja_proceso', $data);
        }

        $this->db->insert('cs_hoja_proceso', $data);
        return $this->db->insert_id();
    }

    public function eliminar_hoja_proceso($id) {
        return $this->db->where('id', $id)->delete('cs_hoja_proceso');
    }

    // =========================================================
    // DETALLE: gastos fijos de la hoja
    // =========================================================

    public function obtener_hoja_gastos($hoja_id) {
        return $this->db
            ->select('hg.*, gf.nombre as gasto_nombre, gf.monto_mensual')
            ->from('cs_hoja_gasto hg')
            ->join('cs_gasto_fijo gf', 'gf.id = hg.gasto_fijo_id')
            ->where('hg.hoja_id', $hoja_id)
            ->get()
            ->result();
    }

    public function guardar_hoja_gasto($data) {
        $existe = $this->db
            ->where('hoja_id',       $data['hoja_id'])
            ->where('gasto_fijo_id', $data['gasto_fijo_id'])
            ->get('cs_hoja_gasto')
            ->row();

        if ($existe) {
            return $this->db->where('id', $existe->id)->update('cs_hoja_gasto', $data);
        }

        $this->db->insert('cs_hoja_gasto', $data);
        return $this->db->insert_id();
    }

    public function eliminar_hoja_gasto($id) {
        return $this->db->where('id', $id)->delete('cs_hoja_gasto');
    }

    // =========================================================
    // CÁLCULO DE COSTO UNITARIO
    //
    // Insumo:    precio_unitario * cantidad / rendimiento
    // Proc HORA: (minutos / 60) * costo_hora
    // Proc LOTE: (override ?? costo_base) / lote_cantidad
    //            + costo_flete / flete_lote_qty  (si aplica)
    // Gasto MONTO:      valor directo por unidad
    // Gasto PORCENTAJE: (sub_insumos + sub_propios + sub_tercerizado) * valor/100
    // =========================================================

    public function calcular_costo($hoja_id) {
        $r           = new stdClass();
        $r->hoja     = $this->obtener_hoja($hoja_id);
        $r->producto = $this->obtener_producto_vt($r->hoja->producto_id);
        $r->insumos  = $this->obtener_hoja_insumos($hoja_id);
        $r->procesos = $this->obtener_hoja_procesos($hoja_id);
        $r->gastos   = $this->obtener_hoja_gastos($hoja_id);

        // Insumos
        $sub_insumos = 0;
        foreach ($r->insumos as $ins) {
            $ins->costo_calc = ($ins->rendimiento > 0)
                ? ($ins->precio_unitario * $ins->cantidad / $ins->rendimiento)
                : 0;
            $sub_insumos += $ins->costo_calc;
        }

        // Procesos
        $sub_propios     = 0;
        $sub_tercerizado = 0;
        foreach ($r->procesos as $proc) {
            $costo_base = ($proc->costo_lote_override !== NULL)
                ? (float)$proc->costo_lote_override
                : (float)$proc->costo_base;

            if ($proc->tipo_costo === 'HORA') {
                $proc->costo_calc = ($proc->minutos > 0)
                    ? ($proc->minutos / 60) * $costo_base
                    : 0;
            } else {
                $proc->costo_calc = $costo_base / max(1, (int)$proc->lote_cantidad);
            }

            $proc->flete_calc = ($proc->incluye_flete && $proc->costo_flete > 0)
                ? $proc->costo_flete / max(1, (int)$proc->flete_lote_qty)
                : 0;

            $proc->costo_total_calc = $proc->costo_calc + $proc->flete_calc;

            if ($proc->es_tercerizado) {
                $sub_tercerizado += $proc->costo_total_calc;
            } else {
                $sub_propios += $proc->costo_total_calc;
            }
        }

        $sub_variable = $sub_insumos + $sub_propios + $sub_tercerizado;

        // Gastos fijos
        $sub_gastos = 0;
        foreach ($r->gastos as $g) {
            $g->costo_calc = ($g->tipo_asignacion === 'MONTO')
                ? (float)$g->valor
                : $sub_variable * ((float)$g->valor / 100);
            $sub_gastos += $g->costo_calc;
        }

        $r->sub_insumos     = round($sub_insumos,     4);
        $r->sub_propios     = round($sub_propios,      4);
        $r->sub_tercerizado = round($sub_tercerizado,  4);
        $r->sub_gastos      = round($sub_gastos,       4);
        $r->costo_total     = round($sub_variable + $sub_gastos, 4);

        $ct = $r->costo_total > 0 ? $r->costo_total : 1;
        $r->pct_insumos     = round($r->sub_insumos     / $ct * 100, 1);
        $r->pct_propios     = round($r->sub_propios     / $ct * 100, 1);
        $r->pct_tercerizado = round($r->sub_tercerizado / $ct * 100, 1);
        $r->pct_gastos      = round($r->sub_gastos      / $ct * 100, 1);

        return $r;
    }

    public function resumen_dashboard() {
        $hojas = $this->db
            ->select('h.id as hoja_id, h.nombre as hoja_nombre, h.es_principal,
                      p.id as producto_id, p.codigo, p.nombre as producto_nombre,
                      p.precio_unidad')
            ->from('cs_hoja_costo h')
            ->join('vt_producto p', 'p.id = h.producto_id')
            ->where('h.estado', 1)
            ->where('p.estado', 1)
            ->order_by('p.nombre')
            ->get()
            ->result();

        $resumen = array();
        foreach ($hojas as $h) {
            $c      = $this->calcular_costo($h->hoja_id);
            $margen = ($h->precio_unidad > 0 && $c->costo_total > 0)
                ? round(($h->precio_unidad - $c->costo_total) / $h->precio_unidad * 100, 1)
                : NULL;

            $resumen[] = array(
                'hoja_id'         => $h->hoja_id,
                'hoja_nombre'     => $h->hoja_nombre,
                'es_principal'    => $h->es_principal,
                'producto_id'     => $h->producto_id,
                'codigo'          => $h->codigo,
                'nombre'          => $h->producto_nombre,
                'sub_insumos'     => $c->sub_insumos,
                'sub_propios'     => $c->sub_propios,
                'sub_tercerizado' => $c->sub_tercerizado,
                'sub_gastos'      => $c->sub_gastos,
                'costo_total'     => $c->costo_total,
                'precio_venta'    => $h->precio_unidad,
                'margen_pct'      => $margen,
            );
        }
        return $resumen;
    }

    // =========================================================
    // HELPERS — listas para selects
    // =========================================================

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

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

    public function listar_proveedores() {
        return $this->db
            ->select('id, razon_social, nro_documento')
            ->where('estado', 1)
            ->order_by('razon_social')
            ->get('lt_proveedor')
            ->result();
    }


    public function buscar_productos($term) {
        return $this->db
            ->select('p.id, p.codigo, p.nombre')
            ->from('vt_producto p')
            ->group_start()
                ->like('p.nombre', $term)
                ->or_like('p.codigo', $term)
            ->group_end()
            ->where('p.estado', 1)
            ->order_by('p.nombre', 'ASC')
            ->limit(20)
            ->get()
            ->result();
    }
}
