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

class Reporte_model extends CI_Model
{
	public function obtener_resumen()
	{
		$resumen = array(
			'total_clientes' => 0,
			'pedidos_pendientes' => 0,
			'pedidos_cerrados' => 0,
			'ventas_hoy' => 0.00,
			'ventas_mes' => 0.00,
			'ventas_totales' => 0.00,
			'productos_stock' => 0,
			'materiales_padre' => 0
		);

		if ($this->db->table_exists('clientes')) {
			$resumen['total_clientes'] = (int) $this->db->count_all('clientes');
		}

		if ($this->db->table_exists('pedidos')) {
			$resumen['pedidos_pendientes'] = (int) $this->db
				->from('pedidos')
				->group_start()
					->where('estado', 'pendiente')
					->or_where('estado IS NULL', NULL, FALSE)
					->or_where("estado = ''", NULL, FALSE)
				->group_end()
				->count_all_results();

			$resumen['pedidos_cerrados'] = (int) $this->db
				->from('pedidos')
				->where_in('estado', array('producto', 'agregado_producto', 'finalizado'))
				->count_all_results();
		}

		$resumen['ventas_hoy'] = $this->obtener_total_ventas(TRUE);
		$resumen['ventas_mes'] = $this->obtener_total_ventas_mes();
		$resumen['ventas_totales'] = $this->obtener_total_ventas(FALSE);

		if ($this->db->table_exists('inventario_productos')) {
			$row = $this->db
				->select('COALESCE(SUM(cantidad), 0) AS total_stock', FALSE)
				->from('inventario_productos')
				->where('cantidad >', 0)
				->get()
				->row();
			$resumen['productos_stock'] = $row ? (int) $row->total_stock : 0;
		}

		if ($this->db->table_exists('inventario_materiales')) {
			$resumen['materiales_padre'] = (int) $this->db
				->from('inventario_materiales')
				->where("(parent_id IS NULL OR parent_id = 0)", NULL, FALSE)
				->count_all_results();
		}

		return $resumen;
	}

	public function obtener_cierres_recientes()
	{
		if (!$this->db->table_exists('pedidos')) {
			return array();
		}

		$this->db
			->select('p.*')
			->from('pedidos p');

		if ($this->db->table_exists('clientes')) {
			$this->db->select('c.nombre AS cliente_nombre');
			$this->db->join('clientes c', 'c.id = p.cliente_id', 'left');
		} else {
			$this->db->select("'' AS cliente_nombre", FALSE);
		}

		if ($this->db->table_exists('inventario_categorias')) {
			$this->db->select('t.nombre AS template_nombre');
			$this->db->join('inventario_categorias t', 't.id = p.template_id', 'left');
		} else {
			$this->db->select("'' AS template_nombre", FALSE);
		}

		$rows = $this->db
			->where_in('p.estado', array('producto', 'agregado_producto', 'finalizado'))
			->order_by('p.id', 'DESC')
			->limit(20)
			->get()
			->result();

		if (empty($rows)) {
			return array();
		}

		$pedido_ids = array();
		foreach ($rows as $r) {
			$pedido_ids[] = (int) $r->id;
		}

		$lineas_map = array();
		if ($this->db->table_exists('pedido_materiales')) {
			$this->db
				->select('pm.pedido_id, pm.cantidad, pm.subtotal, m.nombre AS material_nombre, m.unidad')
				->from('pedido_materiales pm');
			if ($this->db->table_exists('inventario_materiales')) {
				$this->db->join('inventario_materiales m', 'm.id = pm.material_id', 'left');
			} else {
				$this->db->select("'' AS material_nombre, '' AS unidad", FALSE);
			}
			$lineas = $this->db
				->where_in('pm.pedido_id', $pedido_ids)
				->order_by('pm.id', 'ASC')
				->get()
				->result();

			foreach ($lineas as $l) {
				$pid = (int) $l->pedido_id;
				if (!isset($lineas_map[$pid])) {
					$lineas_map[$pid] = array();
				}
				$lineas_map[$pid][] = $l;
			}
		}

		$fotos_map = $this->obtener_fotos_por_pedido_ids($pedido_ids);

		foreach ($rows as $r) {
			$pid = isset($r->id) ? (int) $r->id : 0;
			$monto_venta = $this->obtener_monto_venta_por_pedido($pid);
			$r->monto_reporte = ($monto_venta !== NULL) ? (float) $monto_venta : (float) $r->total;
			$r->lineas = isset($lineas_map[$pid]) ? $lineas_map[$pid] : array();
			$r->fotos = isset($fotos_map[$pid]) ? $fotos_map[$pid] : array();
		}

		return $rows;
	}

	private function obtener_total_ventas($solo_hoy = FALSE)
	{
		$total = 0.0;
		$pedidos_con_venta = array();

		if ($this->db->table_exists('inventario_ventas_productos')) {
			$this->db
				->select('id, precio_venta, cantidad')
				->from('inventario_ventas_productos');
			if ($solo_hoy) {
				$this->db->where('DATE(creado_en) = CURDATE()', NULL, FALSE);
			}
			$ventas = $this->db->order_by('id', 'DESC')->get()->result();
			foreach ($ventas as $v) {
				$total += ((float) $v->precio_venta) * ((int) $v->cantidad);
			}

			if ($this->db->field_exists('pedido_id', 'inventario_ventas_productos')) {
				$this->db
					->select('pedido_id')
					->from('inventario_ventas_productos')
					->where('pedido_id IS NOT NULL', NULL, FALSE)
					->where('pedido_id >', 0);
				if ($solo_hoy) {
					$this->db->where('DATE(creado_en) = CURDATE()', NULL, FALSE);
				}
				$rows = $this->db->get()->result();
				foreach ($rows as $r) {
					$pedidos_con_venta[(int) $r->pedido_id] = TRUE;
				}
			}
		}

		if (!$this->db->table_exists('pedidos')) {
			return $total;
		}

		$this->db
			->select('id, total')
			->from('pedidos')
			->where('estado', 'finalizado');
		if ($solo_hoy) {
			$this->db->where('DATE(creado_en) = CURDATE()', NULL, FALSE);
		}
		$finalizados = $this->db->get()->result();

		foreach ($finalizados as $p) {
			$pid = (int) $p->id;
			if ($pid <= 0) {
				continue;
			}
			if (isset($pedidos_con_venta[$pid]) || $this->pedido_tiene_venta_por_producto($pid)) {
				continue;
			}
			$total += (float) $p->total;
		}

		return $total;
	}

	private function obtener_total_ventas_mes()
	{
		$total = 0.0;
		$pedidos_con_venta = array();

		if ($this->db->table_exists('inventario_ventas_productos')) {
			$this->db
				->select('id, precio_venta, cantidad')
				->from('inventario_ventas_productos')
				->where('YEAR(creado_en) = YEAR(CURDATE())', NULL, FALSE)
				->where('MONTH(creado_en) = MONTH(CURDATE())', NULL, FALSE);
			$ventas = $this->db->order_by('id', 'DESC')->get()->result();
			foreach ($ventas as $v) {
				$total += ((float) $v->precio_venta) * ((int) $v->cantidad);
			}

			if ($this->db->field_exists('pedido_id', 'inventario_ventas_productos')) {
				$rows = $this->db
					->select('pedido_id')
					->from('inventario_ventas_productos')
					->where('pedido_id IS NOT NULL', NULL, FALSE)
					->where('pedido_id >', 0)
					->where('YEAR(creado_en) = YEAR(CURDATE())', NULL, FALSE)
					->where('MONTH(creado_en) = MONTH(CURDATE())', NULL, FALSE)
					->get()
					->result();
				foreach ($rows as $r) {
					$pedidos_con_venta[(int) $r->pedido_id] = TRUE;
				}
			}
		}

		if (!$this->db->table_exists('pedidos')) {
			return $total;
		}

		$finalizados = $this->db
			->select('id, total')
			->from('pedidos')
			->where('estado', 'finalizado')
			->where('YEAR(creado_en) = YEAR(CURDATE())', NULL, FALSE)
			->where('MONTH(creado_en) = MONTH(CURDATE())', NULL, FALSE)
			->get()
			->result();

		foreach ($finalizados as $p) {
			$pid = (int) $p->id;
			if ($pid <= 0) {
				continue;
			}
			if (isset($pedidos_con_venta[$pid]) || $this->pedido_tiene_venta_por_producto($pid)) {
				continue;
			}
			$total += (float) $p->total;
		}

		return $total;
	}

	private function obtener_monto_venta_por_pedido($pedido_id)
	{
		$pedido_id = (int) $pedido_id;
		if ($pedido_id <= 0 || !$this->db->table_exists('inventario_ventas_productos')) {
			return NULL;
		}

		if ($this->db->field_exists('pedido_id', 'inventario_ventas_productos')) {
			$row = $this->db
				->select('precio_venta, cantidad')
				->from('inventario_ventas_productos')
				->where('pedido_id', $pedido_id)
				->order_by('id', 'DESC')
				->limit(1)
				->get()
				->row();
			if ($row) {
				return ((float) $row->precio_venta) * ((int) $row->cantidad);
			}
		}

		if ($this->db->table_exists('inventario_productos')) {
			$row = $this->db
				->select('vp.precio_venta, vp.cantidad')
				->from('inventario_ventas_productos vp')
				->join('inventario_productos ip', 'ip.id = vp.producto_id', 'inner')
				->where('ip.pedido_id', $pedido_id)
				->order_by('vp.id', 'DESC')
				->limit(1)
				->get()
				->row();
			if ($row) {
				return ((float) $row->precio_venta) * ((int) $row->cantidad);
			}
		}

		// Fallback para ventas antiguas sin pedido_id: buscar por texto "Pedido #ID" en el nombre.
		$row = $this->db
			->select('precio_venta, cantidad')
			->from('inventario_ventas_productos')
			->like('nombre_producto', 'Pedido #'.$pedido_id)
			->order_by('id', 'DESC')
			->limit(1)
			->get()
			->row();
		if ($row) {
			return ((float) $row->precio_venta) * ((int) $row->cantidad);
		}

		return NULL;
	}

	private function pedido_tiene_venta_por_producto($pedido_id)
	{
		$pedido_id = (int) $pedido_id;
		if (
			$pedido_id <= 0 ||
			!$this->db->table_exists('inventario_ventas_productos') ||
			!$this->db->table_exists('inventario_productos')
		) {
			return FALSE;
		}

		$row = $this->db
			->select('vp.id')
			->from('inventario_ventas_productos vp')
			->join('inventario_productos ip', 'ip.id = vp.producto_id', 'inner')
			->where('ip.pedido_id', $pedido_id)
			->limit(1)
			->get()
			->row();

		return (bool) $row;
	}

	private function obtener_fotos_por_pedido_ids($pedido_ids)
	{
		$ids = array_unique(array_map('intval', (array) $pedido_ids));
		$ids = array_values(array_filter($ids, function ($v) {
			return (int) $v > 0;
		}));
		if (empty($ids)) {
			return array();
		}

		$map = array();
		$paths = array();
		foreach ($ids as $pid) {
			$map[$pid] = array();
			$paths[$pid] = array();
		}

		if ($this->db->table_exists('pedido_fotos')) {
			$rows = $this->db
				->select('pedido_id, foto_path')
				->from('pedido_fotos')
				->where_in('pedido_id', $ids)
				->order_by('id', 'DESC')
				->get()
				->result();

			foreach ($rows as $r) {
				$pid = (int) $r->pedido_id;
				$path = isset($r->foto_path) ? trim((string) $r->foto_path) : '';
				if ($path === '' || isset($paths[$pid][$path])) {
					continue;
				}
				$paths[$pid][$path] = TRUE;
				$map[$pid][] = $path;
			}
		}

		if ($this->db->table_exists('pedidos') && $this->db->field_exists('foto_path', 'pedidos')) {
			$legacy = $this->db
				->select('id, foto_path')
				->from('pedidos')
				->where_in('id', $ids)
				->get()
				->result();

			foreach ($legacy as $r) {
				$pid = (int) $r->id;
				$path = isset($r->foto_path) ? trim((string) $r->foto_path) : '';
				if ($path === '' || isset($paths[$pid][$path])) {
					continue;
				}
				$paths[$pid][$path] = TRUE;
				$map[$pid][] = $path;
			}
		}

		return $map;
	}
}
