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

class Orden_pedido extends MY_Controller {

    public function __construct() {
        parent::__construct();
        $this->load->model('ventas/Orden_pedido_model');
        $this->load->model('logistica/Requerimiento_model');
        $this->load->model('configuracion/Empresa_model');
        $this->load->model('almacen/Guiaremitente_model');
    }

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

    public function index() {
        $this->validar_permiso('orden_pedido_ver');

        $estado_id = $this->input->get('estado_id', TRUE);
        if ($estado_id === null || $estado_id === '') {
            $estado_id = 5; // GENERADO por defecto
        }

        $data['titulo']    = 'Orden de Pedido';
        $data['ordenes']   = $this->Orden_pedido_model->listar($estado_id);
        $data['estados']   = $this->Orden_pedido_model->listar_estados();
        $data['estado_id'] = (int)$estado_id;

        $this->layout('ventas/orden_pedido/index', $data);
    }

    public function ver($id) {
        $this->validar_permiso('orden_pedido_ver');

        $orden = $this->db
            ->select('
                o.*,
                cli.razon_social,
                cli.nro_documento,
                con.nombre as contacto_nombre,
                con.celular as contacto_celular,
                con.email as contacto_email,
                loc.direccion as local_direccion,
                tc.nombre as comprobante,
                tc.nombre_corto as comprobante_corto,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                u.usuario as usuario_creador
            ')
            ->from('vt_orden_pedido o')
            ->join('vt_cliente cli', 'cli.id = o.cliente_id')
            ->join('vt_cliente_contacto con', 'con.id = o.contacto_id', 'left')
            ->join('vt_cliente_local loc', 'loc.id = o.local_id', 'left')
            ->join('mt_tipo_comprobante tc', 'tc.id = o.comprobante_id')
            ->join('estado e', 'e.id = o.estado_id')
            ->join('usuarios u', 'u.id = o.created_by', 'left')
            ->where('o.id', $id)
            ->get()
            ->row();

        if (!$orden) {
            show_404();
        }

        $detalle = $this->Orden_pedido_model->obtener_detalle($id);
        $historial = $this->Orden_pedido_model->obtener_historial_estados($id);

        $data['titulo'] = 'Detalle de Orden de Pedido';
        $data['orden'] = $orden;
        $data['detalle'] = $detalle;
        $data['historial'] = $historial;

        $this->layout('ventas/orden_pedido/ver', $data);
    }

    public function anular($id) {
        $this->validar_permiso('orden_pedido_anular');

        $orden = $this->Orden_pedido_model->obtener($id);

        if (!$orden) {
            show_404();
        }

        $estadoActual = $this->db
            ->where('id', $orden->estado_id)
            ->get('estado')
            ->row();

        if ($estadoActual && $estadoActual->codigo == 'ANU') {
            $this->session->set_flashdata('error', 'La orden de pedido ya se encuentra anulada');
            redirect('ventas/orden_pedido');
        }

        if ($estadoActual && $estadoActual->codigo == 'FAC') {
            $this->session->set_flashdata('error', 'No se puede anular una orden ya facturada');
            redirect('ventas/orden_pedido');
        }

        $estadoAnulado = $this->Orden_pedido_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'ANU');

        if (!$estadoAnulado) {
            $this->session->set_flashdata('error', 'No se encontró el estado ANULADO para orden de pedido');
            redirect('ventas/orden_pedido');
        }

        $this->db->trans_begin();

        $this->Orden_pedido_model->actualizar($id, array(
            'estado_id' => $estadoAnulado->id,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        ));

        $this->Orden_pedido_model->insertar_estado(array(
            'orp_id' => $id,
            'estado_id' => $estadoAnulado->id,
            'orp_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', 'No se pudo anular la orden de pedido');
            redirect('ventas/orden_pedido');
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Orden de pedido anulada correctamente');
        redirect('ventas/orden_pedido');
    }

    public function print($id) {
        $this->validar_permiso('orden_pedido_ver');

        $orden = $this->db
            ->select('
                o.*,
                cli.razon_social,
                cli.nro_documento,
                cli.fp_descripcion,
                con.nombre as contacto_nombre,
                con.celular as contacto_celular,
                con.email as contacto_email,
                loc.direccion as local_direccion,
                tc.nombre as comprobante,
                tc.nombre_corto as comprobante_corto,
                e.nombre as estado_nombre,
                e.codigo as estado_codigo,
                u.usuario as usuario_creador,
                CONCAT(IFNULL(v.apellidos, ""), " ", IFNULL(v.nombres, "")) as vendedor_nombre
            ')
            ->from('vt_orden_pedido o')
            ->join('vt_cliente cli', 'cli.id = o.cliente_id')
            ->join('vt_cliente_contacto con', 'con.id = o.contacto_id', 'left')
            ->join('vt_cliente_local loc', 'loc.id = o.local_id', 'left')
            ->join('mt_tipo_comprobante tc', 'tc.id = o.comprobante_id')
            ->join('estado e', 'e.id = o.estado_id')
            ->join('usuarios u', 'u.id = o.created_by', 'left')
            ->join('vt_cotizacion c', 'c.id = o.ctc_id', 'left')
            ->join('rh_empleado v', 'v.id = c.vendedor_id', 'left')
            ->where('o.id', $id)
            ->get()
            ->row();

        if (!$orden) {
            show_404();
        }

        $detalle = $this->Orden_pedido_model->obtener_detalle($id);
        $empresa = $this->Empresa_model->obtener_activa();
        $sucursales = array();

        if ($empresa) {
            $sucursales = $this->Empresa_model->obtener_sucursales_activas($empresa->id);
        }

        $data['orden'] = $orden;
        $data['detalle'] = $detalle;
        $data['empresa'] = $empresa;
        $data['sucursales'] = $sucursales;

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


    public function estado_historial($id) {
        $this->validar_permiso_ajax('orden_pedido_ver');

        $historial = $this->Orden_pedido_model->obtener_historial_estados($id);
        echo json_encode($historial);
    }

    public function requerimientos($id) {
        $this->validar_permiso('requerimientos_ver');

        $orden = $this->Orden_pedido_model->obtener($id);

        if (!$orden) {
            show_404();
        }

        $requerimientos = $this->Requerimiento_model->listar_por_orp($id);

        $data['titulo'] = 'Requerimientos de Orden de Pedido';
        $data['orden'] = $orden;
        $data['requerimientos'] = $requerimientos;

        $this->layout('ventas/orden_pedido/requerimientos', $data);
    }

    public function procesar_atencion($id) {
        $this->validar_permiso('orden_pedido_editar');

        $orden = $this->Orden_pedido_model->obtener($id);

        if (!$orden) {
            show_404();
        }

        $estadoActual = $this->db
            ->where('id', $orden->estado_id)
            ->get('estado')
            ->row();

        if (!$estadoActual || in_array($estadoActual->codigo, array('TNE', 'ENF', 'FAC', 'ANU'))) {
            $this->session->set_flashdata('error', 'La orden ya no puede ser atendida');
            redirect('ventas/orden_pedido');
        }

        $items = $this->input->post('items');

        if (empty($items) || !is_array($items)) {
            $this->session->set_flashdata('error', 'No se recibieron items para atender');
            redirect('ventas/orden_pedido/atender/'.$id);
        }

        $estadoParcial = $this->Orden_pedido_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'PAR');
        $estadoTerminado = $this->Orden_pedido_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'TNE');

        if (!$estadoParcial || !$estadoTerminado) {
            $this->session->set_flashdata('error', 'No se encontraron los estados requeridos');
            redirect('ventas/orden_pedido/atender/'.$id);
        }

        $this->db->trans_begin();

        $todosTerminados = true;

        foreach ($items as $itemId => $dataItem) {
            $detalle = $this->Orden_pedido_model->obtener_detalle_por_id($itemId);

            if (!$detalle || (int)$detalle->orp_id !== (int)$id) {
                continue;
            }

            $cantidadAtendida = isset($dataItem['cantidad_atendida']) ? (float)$dataItem['cantidad_atendida'] : 0;
            $saldoActual = (float)$detalle->orpd_saldo;

            if ($cantidadAtendida <= 0) {
                if ((float)$detalle->orpd_saldo > 0) {
                    $todosTerminados = false;
                }
                continue;
            }

            if ($cantidadAtendida > $saldoActual) {
                $this->db->trans_rollback();
                $this->session->set_flashdata('error', 'La cantidad atendida no puede ser mayor que el saldo pendiente');
                redirect('ventas/orden_pedido/atender/'.$id);
            }

            $nuevoSaldo = round($saldoActual - $cantidadAtendida, 2);

            if ($nuevoSaldo <= 0) {
                $nuevoSaldo = 0;
                $nuevoEstadoId = $estadoTerminado->id;
            } else {
                $nuevoEstadoId = $estadoParcial->id;
                $todosTerminados = false;
            }

            $this->Orden_pedido_model->actualizar_detalle($detalle->id, array(
                'orpd_saldo' => $nuevoSaldo,
                'estado_id' => $nuevoEstadoId,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));
        }

        $detallesActualizados = $this->Orden_pedido_model->obtener_detalle($id);

        $todosTerminados = true;
        foreach ($detallesActualizados as $d) {
            $estadoDetalle = $this->db->where('id', $d->estado_id)->get('estado')->row();
            if (!$estadoDetalle || $estadoDetalle->codigo != 'TNE') {
                $todosTerminados = false;
                break;
            }
        }

        $nuevoEstadoCabecera = $todosTerminados ? $estadoTerminado->id : $estadoParcial->id;

        $this->Orden_pedido_model->actualizar($id, array(
            'estado_id' => $nuevoEstadoCabecera,
            'updated_at' => date('Y-m-d H:i:s'),
            'updated_by' => $this->session->userdata('id')
        ));

        $this->Orden_pedido_model->insertar_estado(array(
            'orp_id' => $id,
            'estado_id' => $nuevoEstadoCabecera,
            'orp_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', 'No se pudo procesar la atención de la orden');
            redirect('ventas/orden_pedido/atender/'.$id);
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Atención de la orden procesada correctamente');
        redirect('ventas/orden_pedido/ver/'.$id);
    }

    public function generar_guia($id) {
        $this->validar_permiso('orden_pedido_editar');

        $orden = $this->Orden_pedido_model->obtener_completo($id);

        if (!$orden) {
            show_404();
        }

        $estadoActual = $this->db->where('id', $orden->estado_id)->get('estado')->row();

        if (!$estadoActual || in_array($estadoActual->codigo, array('ANU', 'FAC'))) {
            $this->session->set_flashdata('error', 'La orden no permite generar guía por su estado actual');
            redirect('ventas/orden_pedido');
        }

        $detalle = $this->Orden_pedido_model->obtener_detalle_para_guia($id);

        $detalleDisponible = array();
        foreach ($detalle as $item) {
            if ((float)$item->cantidad_disponible_guia > 0) {
                $detalleDisponible[] = $item;
            }
        }

        if (empty($detalleDisponible)) {
            $this->session->set_flashdata('error', 'La orden no tiene cantidades atendidas disponibles para guiar');
            redirect('ventas/orden_pedido/ver/'.$id);
        }

        $tipoComprobante = $this->Guiaremitente_model->obtener_tipo_comprobante_guia();

        $data['titulo']         = 'Generar Guía desde Orden de Pedido';
        $data['orden']          = $orden;
        $data['detalle']        = $detalleDisponible;
        $data['serie_actual']   = $tipoComprobante ? $tipoComprobante->serie : '';
        $data['numero_actual']  = $tipoComprobante ? str_pad($tipoComprobante->correlativo_actual, 8, '0', STR_PAD_LEFT) : '';

        $data['motivos']        = $this->Guiaremitente_model->listar_motivos();
        $data['unidades_peso']  = $this->Guiaremitente_model->listar_unidades_peso();
        $data['origenes']       = $this->Guiaremitente_model->listar_origenes();
        $data['destinos']       = $this->Guiaremitente_model->listar_destinos();
        $data['vehiculos']      = $this->Guiaremitente_model->listar_vehiculos();
        $data['conductores']    = $this->Guiaremitente_model->listar_conductores();
        $data['transportistas'] = $this->Guiaremitente_model->listar_transportistas();

        $this->layout('ventas/orden_pedido/generar_guia', $data);
    }    

    public function store_guia($id) {
        $this->validar_permiso('orden_pedido_editar');

        $orden = $this->Orden_pedido_model->obtener_completo($id);

        if (!$orden) {
            show_404();
        }

        $estadoActual = $this->db->where('id', $orden->estado_id)->get('estado')->row();

        if (!$estadoActual || in_array($estadoActual->codigo, array('ANU', 'FAC'))) {
            $this->session->set_flashdata('error', 'La orden no permite generar guía');
            redirect('ventas/orden_pedido');
        }

        $this->form_validation->set_rules('motivo_traslado_id', 'Motivo de traslado', 'required');
        $this->form_validation->set_rules('um_peso_bruto_id', 'Unidad de peso bruto', 'required');
        $this->form_validation->set_rules('peso_bruto_carga', 'Peso bruto carga', 'required|numeric');
        $this->form_validation->set_rules('origen_id', 'Origen', 'required');
        $this->form_validation->set_rules('destino_id', 'Destino', 'required');
        $this->form_validation->set_rules('tipo_transporte', 'Tipo transporte', 'required');
        $this->form_validation->set_rules('fecha_traslado', 'Fecha traslado', 'required');

        if ($this->form_validation->run() == FALSE) {
            return $this->generar_guia($id);
        }

        $tipo_transporte    = $this->input->post('tipo_transporte', TRUE);
        $vehiculo_id        = $this->input->post('vehiculo_id', TRUE);
        $conductor_id       = $this->input->post('conductor_id', TRUE);
        $transportista_id   = $this->input->post('transportista_id', TRUE);

        // misma lógica de validación de transporte que ya usas en guía remitente
        if ($tipo_transporte == 'PRIVADO') {
            if (empty($vehiculo_id)) {
                $this->session->set_flashdata('error', 'Debe seleccionar un vehículo para transporte privado');
                redirect('ventas/orden_pedido/generar_guia/'.$id);
            }
            if (empty($conductor_id)) {
                $this->session->set_flashdata('error', 'Debe seleccionar un conductor para transporte privado');
                redirect('ventas/orden_pedido/generar_guia/'.$id);
            }
        }

        if ($tipo_transporte == 'PUBLICO') {
            if (empty($transportista_id)) {
                $this->session->set_flashdata('error', 'Debe seleccionar un transportista para transporte público');
                redirect('ventas/orden_pedido/generar_guia/'.$id);
            }
        }

        $items = $this->input->post('items');
        if (empty($items) || !is_array($items)) {
            $this->session->set_flashdata('error', 'No se recibieron items para generar la guía');
            redirect('ventas/orden_pedido/generar_guia/'.$id);
        }

        $tipoComprobante = $this->Guiaremitente_model->obtener_tipo_comprobante_guia();

        if (!$tipoComprobante) {
            $this->session->set_flashdata('error', 'No existe configuración del tipo de comprobante de guía');
            redirect('ventas/orden_pedido/generar_guia/'.$id);
        }

        $serie = trim($tipoComprobante->serie);
        $correlativoActual = (int)$tipoComprobante->correlativo_actual;
        $numero = str_pad($correlativoActual, 8, '0', STR_PAD_LEFT);

        $fecha_traslado = date('Y-m-d H:i:s', strtotime($this->input->post('fecha_traslado', TRUE)));

        $cabeceraGuia = array(
            'serie'                 => $serie,
            'numero'                => $numero,
            'comercio_exterior'     => $this->input->post('comercio_exterior') ? 1 : 0,
            'motivo_traslado_id'    => $this->input->post('motivo_traslado_id', TRUE),
            'cliente_id'            => $orden->cliente_id,
            'um_peso_bruto_id'      => $this->input->post('um_peso_bruto_id', TRUE),
            'peso_bruto_carga'      => $this->input->post('peso_bruto_carga', TRUE),
            'origen_id'             => $this->input->post('origen_id', TRUE),
            'destino_id'            => $this->input->post('destino_id', TRUE),
            'tipo_transporte'       => $tipo_transporte,
            'transbordo_programado' => $this->input->post('transbordo_programado') ? 1 : 0,
            'traslado_vehiculo'     => $this->input->post('traslado_vehiculo') ? 1 : 0,
            'vehiculo_id'           => ($tipo_transporte == 'PRIVADO') ? $vehiculo_id : null,
            'conductor_id'          => ($tipo_transporte == 'PRIVADO') ? $conductor_id : null,
            'transportista_id'      => ($tipo_transporte == 'PUBLICO') ? $transportista_id : null,
            'fecha_traslado'        => $fecha_traslado,
            'retorno_envases_vacios' => $this->input->post('retorno_envases_vacios') ? 1 : 0,
            'retorno_vehiculo_vacio' => ($tipo_transporte == 'PRIVADO' && $this->input->post('retorno_vehiculo_vacio')) ? 1 : 0,
            'observaciones'         => trim($this->input->post('observaciones', TRUE)),
            'estado_id'             => 29,
            'created_by'            => $this->session->userdata('id')
        );

        $this->db->trans_begin();

        $grId = $this->Guiaremitente_model->insertar($cabeceraGuia);

        if (!$grId) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'No se pudo registrar la guía');
            redirect('ventas/orden_pedido/generar_guia/'.$id);
        }

        $this->Guiaremitente_model->insertar_estado(array(
            'gr_remitente_id'           => $grId,
            'estado_id'                 => 29,
            'gr_remitente_fechaestado'  => date('Y-m-d H:i:s'),
            'usuario_id'                => $this->session->userdata('id')
        ));

        $seGeneroAlMenosUnItem = false;

        foreach ($items as $orpdId => $dataItem) {
            $detalle = $this->Orden_pedido_model->obtener_detalle_por_id($orpdId);

            if (!$detalle || (int)$detalle->orp_id !== (int)$id) {
                continue;
            }

            $cantidad = isset($dataItem['cantidad_guiar']) ? (float)$dataItem['cantidad_guiar'] : 0;

            $cantidadAtendida = (float)$detalle->orpd_cantidad - (float)$detalle->orpd_saldo;
            $cantidadDisponible = $cantidadAtendida - (float)$detalle->orpd_cantidad_guiada;

            if ($cantidad <= 0) {
                continue;
            }

            if ($cantidad > $cantidadDisponible) {
                $this->db->trans_rollback();
                $this->session->set_flashdata('error', 'La cantidad a guiar supera lo disponible para el item ID '.$orpdId);
                redirect('ventas/orden_pedido/generar_guia/'.$id);
            }

            $this->Guiaremitente_model->insertar_detalle(array(
                'gr_remitente_id'   => $grId,
                'producto_id'       => $detalle->producto_id, 
                'um_id'             => $detalle->um_id_venta,
                'cantidad'          => $cantidad
            ));

            $this->Orden_pedido_model->actualizar_cantidad_guiada_detalle(
                $detalle->id,
                $cantidad,
                $this->session->userdata('id')
            );

            $this->Orden_pedido_model->insertar_relacion_guia_orp_detalle(array(
                'gr_remitente_id'   => $grId,
                'orp_id'            => $id,
                'orpd_id'           => $detalle->id,
                'cantidad_guiada'   => $cantidad
            ));

            $seGeneroAlMenosUnItem = true;
        }

        if (!$seGeneroAlMenosUnItem) {
            $this->db->trans_rollback();
            $this->session->set_flashdata('error', 'Debe ingresar al menos una cantidad válida para guiar');
            redirect('ventas/orden_pedido/generar_guia/'.$id);
        }

        $nuevoCorrelativo = $correlativoActual + 1;
        $this->Guiaremitente_model->actualizar_correlativo_tipo_comprobante($tipoComprobante->id, $nuevoCorrelativo);

        $estadoEntregadoNoFacturado = $this->Orden_pedido_model->obtener_estado_por_tipo_codigo('ORDEN PEDIDO', 'ENF');

        if ($estadoEntregadoNoFacturado && $this->Orden_pedido_model->detalle_op_totalmente_guiado($id)) {
            $this->Orden_pedido_model->actualizar($id, array(
                'estado_id' => $estadoEntregadoNoFacturado->id,
                'updated_at' => date('Y-m-d H:i:s'),
                'updated_by' => $this->session->userdata('id')
            ));

            $this->Orden_pedido_model->insertar_estado(array(
                'orp_id' => $id,
                'estado_id' => $estadoEntregadoNoFacturado->id,
                'orp_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', 'No se pudo generar la guía');
            redirect('ventas/orden_pedido/generar_guia/'.$id);
        }

        $this->db->trans_commit();

        $this->session->set_flashdata('success', 'Guía generada correctamente: '.$serie.'-'.$numero);
        redirect('almacen/guiaremitente/ver/'.$grId);
    }

}