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

class Inventario extends CI_Controller
{
	public function __construct()
	{
		parent::__construct();

		if ($this->session->userdata('logged_in') !== TRUE) {
			redirect('login');
		}

		$this->load->model('Inventario_model');
		$this->load->model('App_config_model');
	}

	public function index()
	{
		$this->materiales();
	}

	public function materiales()
	{
		$materiales = $this->Inventario_model->obtener_materiales();
		$material_groups = array();
		$parents = array();
		$children_by_parent = array();

		foreach ($materiales as $m) {
			if (!empty($m->parent_id)) {
				$pid = (int) $m->parent_id;
				if (!isset($children_by_parent[$pid])) {
					$children_by_parent[$pid] = array();
				}
				$children_by_parent[$pid][] = $m;
			} else {
				$parents[] = $m;
			}
		}

		foreach ($parents as $p) {
			$pid = (int) $p->id;
			$children = isset($children_by_parent[$pid]) ? $children_by_parent[$pid] : array();
			if (!empty($children)) {
				usort($children, function ($a, $b) {
					return strcasecmp((string) $a->nombre, (string) $b->nombre);
				});
			}
			$material_groups[] = array(
				'parent' => $p,
				'children' => $children
			);
			unset($children_by_parent[$pid]);
		}

		if (!empty($children_by_parent)) {
			foreach ($children_by_parent as $pid => $orphans) {
				foreach ($orphans as $o) {
					$material_groups[] = array(
						'parent' => $o,
						'children' => array(),
						'orphan' => TRUE
					);
				}
			}
		}

		if (!empty($material_groups)) {
			usort($material_groups, function ($a, $b) {
				$an = isset($a['parent']->nombre) ? (string) $a['parent']->nombre : '';
				$bn = isset($b['parent']->nombre) ? (string) $b['parent']->nombre : '';
				return strcasecmp($an, $bn);
			});
		}

		$data['tab'] = 'materiales';
		$data['items'] = $materiales;
		$data['material_groups'] = $material_groups;
		$data['materiales_padre'] = $this->Inventario_model->obtener_materiales();
		$data['accion_guardar'] = 'inventario/guardar-material';
		$data['app_config'] = $this->App_config_model->obtener();
		$this->load->view('inventario/index', $data);
	}

	public function productos()
	{
		$items = $this->Inventario_model->obtener_productos();
		$pedido_ids = array();
		foreach ($items as $it) {
			$pid = (isset($it->pedido_id) && (int) $it->pedido_id > 0) ? (int) $it->pedido_id : 0;
			if ($pid <= 0 && isset($it->nombre) && preg_match('/Pedido\s*#\s*(\d+)/i', (string) $it->nombre, $m)) {
				$pid = (int) $m[1];
			}
			if ($pid > 0) {
				$it->pedido_id = $pid;
				$pedido_ids[] = $pid;
			}
		}

		$data['tab'] = 'productos';
		$data['items'] = $items;
		$data['fotos_por_pedido'] = $this->Inventario_model->obtener_fotos_por_pedidos($pedido_ids);
		$data['accion_guardar'] = 'inventario/guardar-producto';
		$data['app_config'] = $this->App_config_model->obtener();
		$this->load->view('inventario/index', $data);
	}

	public function categorias()
	{
		$categorias = $this->Inventario_model->obtener_categorias();
		$template_groups = array();
		$parents = array();
		$children_by_parent = array();

		foreach ($categorias as $c) {
			if (!empty($c->parent_id)) {
				$pid = (int) $c->parent_id;
				if (!isset($children_by_parent[$pid])) {
					$children_by_parent[$pid] = array();
				}
				$children_by_parent[$pid][] = $c;
			} else {
				$parents[] = $c;
			}
		}

		foreach ($parents as $p) {
			$pid = (int) $p->id;
			$children = isset($children_by_parent[$pid]) ? $children_by_parent[$pid] : array();
			if (!empty($children)) {
				usort($children, function ($a, $b) {
					return strcasecmp((string) $a->nombre, (string) $b->nombre);
				});
			}
			$template_groups[] = array(
				'parent' => $p,
				'children' => $children
			);
			unset($children_by_parent[$pid]);
		}

		if (!empty($children_by_parent)) {
			foreach ($children_by_parent as $orphans) {
				foreach ($orphans as $o) {
					$template_groups[] = array(
						'parent' => $o,
						'children' => array(),
						'orphan' => TRUE
					);
				}
			}
		}

		if (!empty($template_groups)) {
			usort($template_groups, function ($a, $b) {
				$an = isset($a['parent']->nombre) ? (string) $a['parent']->nombre : '';
				$bn = isset($b['parent']->nombre) ? (string) $b['parent']->nombre : '';
				return strcasecmp($an, $bn);
			});
		}

		$data['tab'] = 'categorias';
		$data['items'] = array();
		$data['accion_guardar'] = 'inventario/guardar-categoria';
		$data['categorias'] = $categorias;
		$data['template_groups'] = $template_groups;
		$data['materiales_disponibles'] = $this->Inventario_model->obtener_materiales();
		$data['app_config'] = $this->App_config_model->obtener();
		$this->load->view('inventario/index', $data);
	}

	public function guardar_material()
	{
		$parent_id = (int) $this->input->post('parent_id', TRUE);
		$this->configurar_validacion_material($parent_id > 0);
		if ($this->form_validation->run() === TRUE) {
			if ($parent_id > 0 && !$this->Inventario_model->existe_material($parent_id)) {
				$this->session->set_flashdata('error', 'El material padre seleccionado no existe.');
				redirect('inventario/materiales');
			}

			$this->Inventario_model->crear_material(array(
				'nombre' => $this->input->post('nombre', TRUE),
				'parent_id' => $parent_id,
				'unidad' => ($parent_id > 0) ? $this->input->post('unidad', TRUE) : '',
				'stock_minimo' => ($parent_id > 0) ? (int) $this->input->post('stock_minimo', TRUE) : 0,
				'costo' => ($parent_id > 0) ? (float) $this->input->post('costo', TRUE) : 0,
				'proveedor' => ($parent_id > 0) ? $this->input->post('proveedor', TRUE) : '',
				'nota' => ($parent_id > 0) ? $this->input->post('nota', TRUE) : ''
			));
			$this->session->set_flashdata('ok', 'Material agregado al inventario.');
		} else {
			$this->session->set_flashdata('error', validation_errors('<div>', '</div>'));
		}

		redirect('inventario/materiales');
	}

	public function editar_material()
	{
		$id = (int) $this->input->post('material_id', TRUE);
		$actual = $this->Inventario_model->obtener_material_por_id($id);
		if (!$actual) {
			$this->session->set_flashdata('error', 'El material no existe.');
			redirect('inventario/materiales');
		}

		$parent_id = (int) $this->input->post('parent_id', TRUE);
		$this->configurar_validacion_material($parent_id > 0);
		if ($this->form_validation->run() === TRUE) {
			if ($parent_id === $id) {
				$this->session->set_flashdata('error', 'Un material no puede ser su propio material padre.');
				redirect('inventario/materiales');
			}
			if ($parent_id > 0 && !$this->Inventario_model->existe_material($parent_id)) {
				$this->session->set_flashdata('error', 'El material padre seleccionado no existe.');
				redirect('inventario/materiales');
			}

			$this->Inventario_model->actualizar_material($id, array(
				'nombre' => $this->input->post('nombre', TRUE),
				'parent_id' => $parent_id,
				'unidad' => ($parent_id > 0) ? $this->input->post('unidad', TRUE) : '',
				'stock_minimo' => ($parent_id > 0) ? (int) $this->input->post('stock_minimo', TRUE) : 0,
				'costo' => ($parent_id > 0) ? (float) $this->input->post('costo', TRUE) : 0,
				'proveedor' => ($parent_id > 0) ? $this->input->post('proveedor', TRUE) : '',
				'nota' => ($parent_id > 0) ? $this->input->post('nota', TRUE) : ''
			));
			$this->session->set_flashdata('ok', 'Material actualizado correctamente.');
		} else {
			$this->session->set_flashdata('error', validation_errors('<div>', '</div>'));
		}

		redirect('inventario/materiales');
	}

	public function guardar_producto()
	{
		$this->validar_formulario_base();
		if ($this->form_validation->run() === TRUE) {
			$this->Inventario_model->crear_producto(array(
				'nombre' => $this->input->post('nombre', TRUE),
				'cantidad' => (int) $this->input->post('cantidad', TRUE),
				'precio' => (float) $this->input->post('precio', TRUE)
			));
			$this->session->set_flashdata('ok', 'Producto agregado al inventario.');
		} else {
			$this->session->set_flashdata('error', validation_errors('<div>', '</div>'));
		}

		redirect('inventario/productos');
	}

	public function vender_producto()
	{
		$this->form_validation->set_rules('producto_id', 'Producto', 'trim|required|integer|greater_than[0]');
		$this->form_validation->set_rules('precio_venta', 'Precio de venta', 'trim|required|numeric|greater_than_equal_to[0]');

		if ($this->form_validation->run() !== TRUE) {
			$this->session->set_flashdata('error', validation_errors('<div>', '</div>'));
			redirect('inventario/productos');
		}

		$producto_id = (int) $this->input->post('producto_id', TRUE);
		$precio_venta = (float) $this->input->post('precio_venta', TRUE);
		$result = $this->Inventario_model->vender_producto($producto_id, $precio_venta);
		$this->session->set_flashdata($result['ok'] ? 'ok' : 'error', $result['message']);
		redirect('inventario/productos');
	}

	public function guardar_categoria()
	{
		$this->form_validation->set_rules('nombre', 'Nombre del template', 'trim|required|max_length[120]');
		$this->form_validation->set_rules('parent_id', 'Template padre', 'trim|integer|greater_than_equal_to[0]');

		if ($this->form_validation->run() !== TRUE) {
			$this->session->set_flashdata('error', validation_errors('<div>', '</div>'));
			redirect('inventario/categorias');
		}

		$nombre = trim((string) $this->input->post('nombre', TRUE));
		$parent_id = (int) $this->input->post('parent_id', TRUE);
		$material_ids = (array) $this->input->post('material_ids');

		if ($parent_id > 0) {
			$parent = $this->Inventario_model->obtener_categoria_por_id($parent_id);
			if (!$parent) {
				$this->session->set_flashdata('error', 'El template padre seleccionado no existe.');
				redirect('inventario/categorias');
			}
		} else {
			$material_ids = array();
		}

		$ok = $this->Inventario_model->crear_categoria($nombre, $parent_id, $material_ids);
		if ($ok) {
			$this->session->set_flashdata('ok', 'Template creado correctamente.');
		} else {
			$this->session->set_flashdata('error', 'No se pudo guardar el template.');
		}

		redirect('inventario/categorias');
	}

	public function historial_material($id = 0)
	{
		$id = (int) $id;
		$this->output->set_content_type('application/json');

		if ($id <= 0) {
			$this->output->set_status_header(400);
			$this->output->set_output(json_encode(array(
				'ok' => FALSE,
				'message' => 'Material invalido.'
			), JSON_UNESCAPED_UNICODE));
			return;
		}

		$material = $this->Inventario_model->obtener_material_por_id($id);
		if (!$material) {
			$this->output->set_status_header(404);
			$this->output->set_output(json_encode(array(
				'ok' => FALSE,
				'message' => 'Material no encontrado.'
			), JSON_UNESCAPED_UNICODE));
			return;
		}

		$es_padre = empty($material->parent_id);
		$movimientos = $this->Inventario_model->obtener_movimientos_stock($id, $es_padre);
		$filas = array();

		foreach ($movimientos as $mov) {
			$cantidad = (int) $mov->cantidad;
			$costo = (float) $mov->costo_unitario;
			$filas[] = array(
				'material' => (string) $mov->material_nombre,
				'proveedor' => (string) $mov->proveedor,
				'cantidad' => $cantidad,
				'unidad' => (string) $mov->unidad,
				'costo_unitario' => $costo,
				'monto' => $cantidad * $costo,
				'referencia' => (string) $mov->compra_ref,
				'fecha' => date('d/m/Y H:i', strtotime($mov->creado_en))
			);
		}

		$this->output->set_output(json_encode(array(
			'ok' => TRUE,
			'material' => (string) $material->nombre,
			'incluye_hijos' => $es_padre,
			'movimientos' => $filas
		), JSON_UNESCAPED_UNICODE));
	}

	private function validar_formulario_base()
	{
		$this->form_validation->set_rules('nombre', 'Nombre', 'trim|required|max_length[120]');
		$this->form_validation->set_rules('cantidad', 'Cantidad', 'trim|required|integer|greater_than_equal_to[0]');
		$this->form_validation->set_rules('precio', 'Precio', 'trim|required|numeric|greater_than_equal_to[0]');
	}

	private function validar_formulario_material()
	{
		$this->configurar_validacion_material(TRUE);
	}

	private function configurar_validacion_material($requiere_detalle)
	{
		$this->form_validation->set_rules('nombre', 'Nombre', 'trim|required|max_length[120]');
		$this->form_validation->set_rules('parent_id', 'Material padre', 'trim|integer|greater_than_equal_to[0]');

		if ($requiere_detalle) {
			$this->form_validation->set_rules('unidad', 'Unidad', 'trim|required|max_length[30]');
			$this->form_validation->set_rules('stock_minimo', 'Stock minimo', 'trim|required|integer|greater_than_equal_to[0]');
			$this->form_validation->set_rules('costo', 'Costo', 'trim|required|numeric|greater_than_equal_to[0]');
			$this->form_validation->set_rules('proveedor', 'Proveedor', 'trim|required|max_length[120]');
			$this->form_validation->set_rules('nota', 'Nota', 'trim|max_length[500]');
		} else {
			$this->form_validation->set_rules('unidad', 'Unidad', 'trim|max_length[30]');
			$this->form_validation->set_rules('stock_minimo', 'Stock minimo', 'trim|integer|greater_than_equal_to[0]');
			$this->form_validation->set_rules('costo', 'Costo', 'trim|numeric|greater_than_equal_to[0]');
			$this->form_validation->set_rules('proveedor', 'Proveedor', 'trim|max_length[120]');
			$this->form_validation->set_rules('nota', 'Nota', 'trim|max_length[500]');
		}
	}
}
