<?php
class Cliente_model extends CI_Model {

	public function get_all() {
		$this->db->select('*');
		$this->db->from('clientes');
		$this->db->where('deleted', 0);
		$this->db->order_by('nombre', 'ASC');
		$query = $this->db->get();

		return $query->result_array();
	}

	public function get($id) {
		$this->db->select('*');
		$this->db->from('clientes');
		$this->db->where('id', $id);
		$this->db->where('deleted', 0);
		$query = $this->db->get();
		$cliente = $query->result_array();
		
		if (!empty($cliente)) {
			return $cliente[0];
		}
		else{
			return [];
		}
	}

	public function list() {
		$this->db->select('id, nombre');
		$this->db->from('clientes');
		$this->db->where('deleted', 0);
		$this->db->order_by('nombre', 'ASC');
		$query = $this->db->get();
		$clientes = $query->result_array();

		$r = [];
		foreach ($clientes as $c) {
			$r[$c['id']] = $c['nombre'];
		}
		return $r;
	}

	public function email_list() {
		$this->db->select('id, email');
		$this->db->from('clientes');
		$this->db->where('email !=', '');
		$this->db->where('deleted', 0);
		$this->db->order_by('id', 'ASC');
		$query = $this->db->get();
		$clientes = $query->result_array();

		$r = [];
		foreach ($clientes as $c) {
			$r[$c['id']] = $c['email'];
		}
		return $r;
	}

	public function ps_list() {
		$this->db->select('id, ps_id');
		$this->db->from('clientes');
		$this->db->where('ps_id !=', 0);
		$this->db->where('deleted', 0);
		$this->db->order_by('id', 'ASC');
		$query = $this->db->get();
		$clientes = $query->result_array();

		$r = [];
		foreach ($clientes as $c) {
			$r[$c['id']] = $c['ps_id'];
		}
		return $r;
	}

	public function ps_nombre_list() {
		$this->db->select('ps_id, nombre');
		$this->db->from('clientes');
		$this->db->where('ps_id !=', 0);
		$this->db->where('deleted', 0);
		$this->db->order_by('id', 'ASC');
		$query = $this->db->get();
		$clientes = $query->result_array();

		$r = [];
		foreach ($clientes as $c) {
			$r[$c['ps_id']] = $c['nombre'];
		}
		return $r;
	}

	public function autocomplete_email($s){
		// Busca clientes que email empiece por $s
		$this->db->select('id, email, nombre, ps_id');
		$this->db->from('clientes');
		$this->db->where('deleted', 0);
		$this->db->like('email', $s, 'after');
		$this->db->order_by('email', 'ASC');

		$clientes = $this->db->get()->result_array();

		$r = [];
		foreach($clientes as $c) {
			$r[] = [
				'id' => $c['id'],
				'label' => $c['email'],
				'value' => $c['email'],
				'nombre' => $c['nombre'],
				'ps_id' => $c['ps_id']
			];
		}
		return $r;
	}


	/* Busca cliente en ps por el email, si existe lo crea en VDM */
	public function search_by_email($email) {
		$ps = $this->load->database('prestashop', TRUE);
		$ps->select('id_customer, firstname, lastname');
		$ps->from('ps_customer');
		$ps->where('email', $email);
		$ps->where('active', 1);
		$ps->where('is_guest', 0);
		$ps->where('deleted', 0);
		$customer = $ps->get()->row_array();

		// busca cliente en VDM por email
		$this->db->select('id, ps_id');
		$this->db->from('clientes');
		$this->db->where('email', $email);
		$this->db->where('deleted', 0);
		$cliente = $this->db->get()->row_array();

		if (!empty($customer)) {
			$data = [
				'ps_id' => $customer['id_customer'],
				'nombre' => $customer['firstname'] . ' ' . $customer['lastname'],
				'email' => $email,
				'created' => date('Y-m-d H:i:s')
			];
			if (!empty($cliente)) {
				if (empty($cliente['ps_id'])) {
					// Asocia ps_id a cliente en VDM
					$this->db->where('id', $cliente['id']);
					$this->db->update('clientes', $data);
					
				}
				$data['id'] = $cliente['id'];
				return $data;
			}
			else {
				// Crea cliente en VDM
				$this->db->insert('clientes', $data);
				$data['id'] = $this->db->insert_id();
				return $data;
			}
		}
		else {
			return null;
		}
	}


	public function save($data) {
		//revisar si viene id y si viene se hace update
		if (empty($data['id'])) {
			$cliente = [];
			if (!empty($data['email'])) {
				// Busca que email no esté registrado
				$this->db->select('id');
				$this->db->from('clientes');
				$this->db->where('email', $data['email']);
				$this->db->where('deleted', 0);
				$cliente = $this->db->get()->row_array();
			}

			if (!empty($cliente)) {
				return $cliente['id'];
			}
			else {
				$data['created'] = date('Y-m-d H:i:s');
				$this->db->insert('clientes', $data);
				return $this->db->insert_id();
			}
		}
		else {
			$this->db->where('id', $data['id']);
			$this->db->update('clientes', $data);
			return $data['id'];
		}
	}

	public function crea_ps($email, $nombre, $apellidos, $newsletter) {
		// Busca que email no esté registrado en PS como cliente
		$ps = $this->load->database('prestashop', TRUE);
		$ps->select('id_customer, firstname, lastname, email');
		$ps->from('ps_customer');
		$ps->where('email', $email);
		$ps->where('active', 1);
		$ps->where('is_guest', 0);
		$ps->where('deleted', 0);
		$customer = $ps->get()->row_array();

		if (!empty($customer)) {
			return ['id' => $customer['id_customer'], 'password' => ''];
		}

		$password = generatePassword(8);
		$hash = password_hash($password, 1);
		$secureKey = md5(uniqid(rand(), true));

		// Crea cliente
		$newCustomer = [
			'id_shop_group' => 1,
			'id_shop' => 1,
			'id_default_group' => 3,
			'id_lang' => 1,
			'firstname' => $nombre,
			'lastname' => $apellidos,
			'email' => $email,
			'passwd' => $hash,
			'secure_key' => $secureKey,
			'active' => 1,
			'date_add' => date('Y-m-d H:i:s')
		];

		if ($newsletter) {
			$newCustomer['newsletter'] = 1;
			$newCustomer['newsletter_date_add'] = date('Y-m-d H:i:s');
		}

		$ps->insert('ps_customer', $newCustomer);
		$customerId = $ps->insert_id();

		// Crea cliente grupo
		$newCustomerGroup = [
			'id_customer' => $customerId,
			'id_group' => 3
		];
		$ps->insert('ps_customer_group', $newCustomerGroup);

		$customer = [
			'id' => $customerId,
			'password' => $password
		];

		return $customer;
	}

	public function delete($id) {
		if (!empty($id)) {
			$this->db->set('deleted', 1, FALSE);
			$this->db->where('id', $id);
			$this->db->update('clientes');
		}
	}

	public function full_info($id) {
		if (!empty($id)) {
			//Busca info del cliente
			$this->db->select('*');
			$this->db->from('clientes');
			$this->db->where('id', $id);
			$this->db->where('deleted', 0);
			$cliente = $this->db->get()->row_array();

			$ps = $this->load->database('prestashop', TRUE);
			$ps->select('newsletter');
			$ps->from('ps_customer c');
			$ps->where('c.id_customer', $cliente['ps_id']);
			$customer = $ps->get()->row_array();

			$cliente['newsletter'] = (isset($customer['newsletter']) ? $customer['newsletter'] : 0);

			// Busca ventas asociadas concretadas
			$this->db->select('v.*, c.nombre AS cliente_nombre, c.email AS cliente_email');
			$this->db->from('ventas v');
			$this->db->join('clientes c', 'v.id_cliente = c.id', 'left');
			$this->db->where('v.id_cliente', $id);
			$this->db->where('v.vendido', 1);
			$this->db->where('v.deleted', 0);
			$this->db->order_by('v.ps_id_asociado', 'DESC');
			$this->db->order_by('CASE WHEN v.boleta > 0 THEN 1 WHEN id_tipo_venta NOT IN (1, 5, 7, 8, 9, 11, 12) THEN 1 ELSE 0 END', 'ASC', FALSE);
			$this->db->order_by('CASE WHEN v.boleta > 0 THEN v.fecha_boleta ELSE v.fecha_venta END', 'DESC', false);
			$ventas = $this->db->get()->result_array();

			// Mapear productos
			$ventas_ids = array_column($ventas, 'id');
			$productos_map = [];
			if (!empty($ventas_ids)) {
				$this->db->select('pv.id_venta, p.id, p.nombre, pv.cantidad')
						->from('productos_ventas pv')
						->join('productos p', 'pv.id_producto = p.id', 'left')
						->where_in('pv.id_venta', $ventas_ids)
						->where('pv.deleted', 0);
				$productos = $this->db->get()->result_array();
				foreach ($productos as $p) {
					$productos_map[$p['id_venta']][] = [
						'id'       => $p['id'],
						'nombre'   => $p['nombre'],
						'cantidad' => $p['cantidad']
					];
				}
			}

			// Agregar productos a cada venta
			foreach ($ventas as &$v) {
				$v['productos'] = $productos_map[$v['id']] ?? [];
			}

			$facturado = 0;
			$utilidades = 0;
			$asociados = [];
			foreach ($ventas as $key => &$venta) {
				if ($venta['ps_id'] != 0) {
					$venta['ps_state'] = $this->Venta->get_order_state($venta['ps_id']);
					$ps_states[$venta['ps_id']] = $venta['ps_state'];
				}
				if (empty($venta['ps_state'])) {
					$venta['ps_state'] = 0;
				}
				if ($venta['ps_id_asociado'] != 0) {
					$asociados[$venta['ps_id_asociado']][] = $venta;
					unset($ventas[$key]);
				}
				else if (!empty($asociados[$venta['ps_id']])) {
					$venta['asociados'] = $asociados[$venta['ps_id']];
					unset($asociados[$venta['ps_id']]);
				}
				$this->db->select('pv.*, p.nombre, p.costo');
				$this->db->from('productos_ventas pv');
				$this->db->join('productos p', 'pv.id_producto = p.id', 'left');
				$this->db->where('pv.id_venta', $venta['id']);
				$this->db->where('pv.deleted', 0);
				$this->db->where('p.deleted', 0);
				$productosVentas = $this->db->get()->result_array();
				$costoVenta = 0;
				foreach ($productosVentas as $productoVenta) {
					$costoVenta += $productoVenta['costo'] * $productoVenta['cantidad'];
					$venta['productos_ventas'][] = $productoVenta;
				}
				$facturado += $venta['total'];
				$venta['utilidad'] = $venta['total'] - $costoVenta;
				$utilidades += $venta['utilidad'];
			}
			// Revisa si queda alguna venta en asociados que no haya sido asociada a otra ventas
			// Y la retorna al arreglo de ventas
			foreach ($asociados as $va){
				foreach ($va as $v){
					$ventas[] = $v;
				}
			}

			$cliente['facturado'] = $facturado;
			$cliente['utilidades'] = $utilidades;
			$cliente['ventas'] = $ventas;

			// Ventas en proceso
			$this->db->select('v.*, c.nombre AS cliente_nombre, c.email AS cliente_email');
			$this->db->from('ventas v');
			$this->db->join('clientes c', 'v.id_cliente = c.id', 'left');
			$this->db->where('v.id_cliente', $id);
			$this->db->where('v.vendido !=', 1);
			$this->db->where('v.deleted', 0);
			$this->db->order_by('v.ps_id_asociado', 'DESC');
			$this->db->order_by('v.fecha', 'DESC');
			$ventas_proceso = $this->db->get()->result_array();

			// Mapear productos
			$ventas_ids = array_column($ventas_proceso, 'id');
			$productos_map = [];
			if (!empty($ventas_ids)) {
				$this->db->select('pv.id_venta, p.id, p.nombre, pv.cantidad')
						->from('productos_ventas pv')
						->join('productos p', 'pv.id_producto = p.id', 'left')
						->where_in('pv.id_venta', $ventas_ids)
						->where('pv.deleted', 0);
				$productos = $this->db->get()->result_array();
				foreach ($productos as $p) {
					$productos_map[$p['id_venta']][] = [
						'id'       => $p['id'],
						'nombre'   => $p['nombre'],
						'cantidad' => $p['cantidad']
					];
				}
			}

			// Agregar productos a cada venta
			foreach ($ventas_proceso as &$v) {
				$v['productos'] = $productos_map[$v['id']] ?? [];
			}

			$ap = [];
			foreach ($ventas_proceso as $key => &$vp) {
				if ($vp['ps_id'] != 0) {
					$vp['ps_state'] = $this->Venta->get_order_state($vp['ps_id']);
				}
				if (empty($vp['ps_state'])) {
					$vp['ps_state'] = 0;
				}
				if ($vp['ps_id_asociado'] != 0) {
					$ap[$vp['ps_id_asociado']][] = $vp;
					unset($ventas_proceso[$key]);
				}
				else if (!empty($ap[$vp['ps_id']])) {
					$vp['asociados'] = $ap[$vp['ps_id']];
					unset($ap[$vp['ps_id']]);
				}
			}
			// Revisa si queda alguna venta en asociados que no haya sido asociada a otra ventas
			// Y la retorna al arreglo de ventas
			foreach ($ap as $vap){
				foreach ($vap as $vpa){
					$ventas_proceso[] = $vpa;
				}
			}

			$cliente['ventas_proceso'] = $ventas_proceso;

			// Buscar registros de puntos en PS
			// solo si tiene ps_id
			$points = [];
			$tp = 0;
			if ($cliente['ps_id'] != 0) {

				$customerPoints = $this->get_points($cliente['ps_id']);

				$points = $customerPoints['puntos'];
				$tp = $customerPoints['total_puntos'];
			}
			$cliente['puntos'] = $points;
			$cliente['total_puntos'] = $tp;

			return $cliente;
		}
	}

	public function search($b = '') {
		$this->db->select('c.*');
		$this->db->from('clientes c');
		$this->db->where('c.deleted', 0);
		$this->db->order_by('c.nombre', 'ASC');

		if (!empty($b)) {
			if (!empty($b)) {
				$keywords = explode(" ", $b); 
				foreach ($keywords as $key) { 
					$this->db->like('c.nombre', $key);
				}
			}
		}

		$nombres = $this->db->get()->result_array();

		$this->db->select('c.*');
		$this->db->from('clientes c');
		$this->db->where('c.deleted', 0);
		$this->db->order_by('c.nombre', 'ASC');

		// Evita traer registros duplicados
		if (!empty($nombres)) {
			foreach($nombres as $nombre) {
				$ids[] = $nombre['id'];
			}
			$this->db->where_not_in('c.id', $ids);
		}

		if (!empty($b)) {
			if (!empty($b)) {
				$keywords = explode(" ", $b); 
				foreach ($keywords as $key) { 
						$this->db->like('c.email', $key);
				}
			}
		}

		$mails = $this->db->get()->result_array();

		$clientes = array_merge($nombres, $mails);
		return $clientes;
	}


	/**
	 * Entrega lista de clientes ordenados por monto pagado segun periodo
	 */
	public function ranking($periodo = ''){
		$this->db->select('id_cliente as id, c.ps_id, SUM(pagado) as suma, c.nombre');
		$this->db->from('ventas v');
		$this->db->join('clientes c', 'v.id_cliente = c.id', 'left');
		//$this->db->where('v.vendido', 1);
		$this->db->where('v.deleted', 0);
		$this->db->group_by('v.id_cliente, c.nombre');
		$this->db->order_by('suma', 'DESC');
		if (strlen($periodo) >= 4) {
			$ano = substr($periodo, 0, 4);
			$this->db->where('YEAR(fecha_venta)', $ano);

			if (strlen($periodo) == 6) {
				$mes = substr($periodo, 4, 2);
				$this->db->where('MONTH(fecha_venta)', $mes);
			}
		}

		$clientes = $this->db->get()->result_array();

		return $clientes;
	}


	/**
	 * Actualiza email de clientes que quedaron con email vacío
	 */
	public function update_email() {
		//Busca clientes con ps_id pero email = '';
			$this->db->select('*');
			$this->db->from('clientes c');
			$this->db->where('c.email', '');
			$this->db->where('c.deleted', 0);
			$clientes = $this->db->get()->result_array();

			foreach ($clientes as $cliente) {
				$new = [];
				$ps = $this->load->database('prestashop', TRUE);
				$ps->select("email, id_default_group");
				$ps->from('ps_customer c');
				$ps->where('c.id_customer', $cliente['ps_id']);
				$customer = $ps->get()->row_array();

				if (!empty($customer) && $customer['id_default_group'] != 2) {
					$new['email'] = $customer['email'];
					$this->db->where('id', $cliente['id']);
					$this->db->update('clientes', $new);
					pr('Id: ' . $cliente['id']. ' => Actualizado. Email: ' . $customer['email']);
				}
			}
			pr('Fin del proceso.');
			die;
	}


	/**
	 * Entrega lista de clientes que no han comprado en más de 3 meses y han comprado más de 200k
	 */
	public function fuga(){
		/*
		SELECT c.id, c.nombre, SUM(v.TOTAL) as totals, MAX(v.fecha_venta) ultima_compra
		FROM ventas v
		left JOIN clientes c ON c.id = v.id_cliente
		GROUP BY c.id, c.nombre
		having SUM(total) > 200000
		AND MAX(v.fecha_venta) < '2021-05-22'
		ORDER BY totals DESC
		*/
		$tresMeses = date("Y-m-d", strtotime(date("Y-m-d") . "- 3 months"));

		$this->db->select('c.id, c.nombre, SUM(v.TOTAL) as suma_total, MAX(v.fecha_venta) ultima_compra');
		$this->db->from('ventas v');
		$this->db->join('clientes c', 'v.id_cliente = c.id', 'left');
		$this->db->where('v.deleted', 0);
		$this->db->where('c.deleted', 0);
		$this->db->group_by('v.id_cliente, c.nombre');
		$this->db->having('SUM(total) > 200000');
		$this->db->having('MAX(fecha_venta) <', $tresMeses);
		$this->db->group_by('c.id, c.nombre');
		$this->db->order_by('suma_total', 'DESC');

		$clientes = $this->db->get()->result_array();

		pr($clientes);
		die;
		return $clientes;
	}

	/**
	 * Busca registros de puntos del cliente
	 */
	public function get_points ($customerId) {
		// Buscar registros de puntos en PS
		// solo si tiene ps_id
		$points = [];
		$tp = 0;
		if ($customerId != 0) {

			$ps = $this->load->database('prestashop', TRUE);

			// Buscar cuantos días son válidos los puntos
			$ps->select("value");
			$ps->from('ps_configuration');
			$ps->where('name', 'PS_LOYALTY_VALIDITY_PERIOD');
			$conf = $ps->get()->row_array();

			$limit = $conf['value'];
			$hoy = new DateTime();

			$ps->select("*");
			$ps->from('ps_loyalty l');
			$ps->where('l.id_customer', $customerId);
			$ps->order_by('l.date_add DESC');
			$points = $ps->get()->result_array();

			$tp = 0;
			foreach($points as &$point){
				if ($point['id_loyalty_state'] == 2) {
					$fechaPuntos = new DateTime($point['date_add']);
					$diff = $hoy->diff($fechaPuntos);
					if ($diff->days <= $limit) {
						$tp += $point['points'];
					}
					else {
						// Estado 7: Vencidos
						$point['id_loyalty_state'] = 7;
					}
				}
				if (!empty($point['id_order'])) {
					if (!empty($ps_states[$point['id_order']])) {
						$point['ps_state'] = $ps_states[$point['id_order']];
					}
					else {
						$point['ps_state'] = $this->Venta->get_order_state($point['id_order']);
					}
				}
				else {
					$point['ps_state'] = 0;
				}
			}
		}
		$result['puntos'] = $points;
		$result['total_puntos'] = $tp;

		return $result;
	}


	/**
	 * Busca un cliente por email en PS si lo encuentra carga puntos de las ventas
	 */
	public function search_loyalty($idCliente) {
		$this->db->select('email');
		$this->db->from('clientes');
		$this->db->where('id', $idCliente);
		$this->db->where('deleted', 0);
		$cliente = $this->db->get()->row_array();

		$ps = $this->load->database('prestashop', TRUE);
		$ps->select('id_customer');
		$ps->from('ps_customer c');
		$ps->where('email', $cliente['email']);
		$ps->where('is_guest', 0);
		$customer = $ps->get()->row_array();

		$result['ps_id'] = 0;
		if (!empty($customer)) {

			// Actualiza Cliente con ps_id
			$nCliente['ps_id'] = $customer['id_customer'];
			$this->db->where('id', $idCliente);
			$this->db->update('clientes', $nCliente);
			$result['ps_id'] = $customer['id_customer'];

			$dias = date('Y-m-d', strtotime('-1 year'));
			//busca todas las ventas del cliente que no tenga puntos cargados
			$this->db->select('id');
			$this->db->from('ventas');
			$this->db->where('id_cliente', $idCliente);
			$this->db->where('deleted', 0);
			$this->db->where('puntos_cargados', 0);
			$this->db->where('fecha_venta > ', $dias);
			$ventas = $this->db->get()->result_array();

			$puntos = 0;
			foreach ($ventas as $v) {
				// Calcula, carga puontos y actualiza venta
				$puntos += $this->carga_puntos($v['id'], $customer['id_customer']);
			}
			$result['puntos'] = $puntos;
		}

		return $result;
	}


	/**
	 * Busca un ventas del cliente que no le generaron puntos
	 */
	public function carga_puntos_ventas($idCliente) {
		$this->db->select('*');
		$this->db->from('clientes');
		$this->db->where('id', $idCliente);
		$this->db->where('deleted', 0);
		$cliente = $this->db->get()->row_array();

		$dias = date('Y-m-d', strtotime('-1 year'));
		//busca todas las ventas del cliente que no tenga puntos cargados
		$this->db->select('id');
		$this->db->from('ventas');
		$this->db->where('id_cliente', $idCliente);
		$this->db->where('deleted', 0);
		$this->db->where('puntos_cargados', 0);
		$this->db->where('ps_id', 0);
		$this->db->where('fecha_venta > ', $dias);
		$ventas = $this->db->get()->result_array();
		$puntos = 0;
		foreach($ventas as $v) {
			$ps = $this->load->database('prestashop', TRUE);
			$ps->select('id_venta');
			$ps->from('ps_loyalty l');
			$ps->where('id_venta', $v['id']);
			$loyalty = $ps->get()->row_array();
			if (empty($loyalty) && !empty($cliente['ps_id'])) {
				$puntos += $this->carga_puntos($v['id'], $cliente['ps_id']);
			}
		}
		$result['puntos'] = $puntos;
		return $result;
	}

	public function carga_puntos($idVenta, $idCustomer) {
		$this->db->select('*');
		$this->db->from('productos_ventas');
		$this->db->where('id_venta', $idVenta);
		$this->db->where('deleted', 0);
		$productos_ventas = $this->db->get()->result_array();

		$total = 0;
		$puntos = 0;
		foreach ($productos_ventas as $pv) {
			if ($pv['descuento'] == 0) {
				$total += $pv['precio_total'];
			}
		}
		$puntos = floor($total/50);
		$loyalty = [
			'id_venta' => $idVenta,
			'ps_id_cliente' => $idCustomer,
			'puntos' => $puntos
		];
		$this->Venta->save_loyalty($loyalty);

		return $puntos;
	}
}


