<?php
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\ORM\Query;

class PromotionsTable extends Table
{
	public function initialize(array $config): void
	{
		parent::initialize($config);
		$this->setTable('promotion');
		$this->setPrimaryKey('id');
		$this->addBehavior('Timestamp');
		$this->belongsTo('User', ['foreignKey' => 'user_id']);
		$this->belongsTo('Video', ['foreignKey' => 'video_id']);
		$this->belongsTo('Audience', ['foreignKey' => 'audience_id']);
	}

	public function getDetails($id): array
	{
		$entity = $this->find()->where(['Promotion.id' => $id])->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getUserPromotions($user_id, $start_datetime, $end_datetime, $starting_point): array
	{
		return $this->find()
			->where([
				'Promotion.user_id' => $user_id,
				'DATE(Promotion.created) >=' => $start_datetime,
				'DATE(Promotion.created) <=' => $end_datetime
			])
			->limit(10)
			->offset($starting_point * 10)
			->order(['Promotion.id' => 'DESC'])
			->toArray();
	}

	public function getAll(): array
	{
		return $this->find()
			->order(['Promotion.id' => 'DESC'])
			->toArray();
	}

	public function getUserActivePromotions($user_id, $datetime): array
	{
		return $this->find()
			->where([
				'Promotion.user_id' => $user_id,
				'Promotion.end_datetime >=' => $datetime,
				'Promotion.active' => 1
			])
			->toArray();
	}

	public function getActivePromotionAudience($id, $datetime): array
	{
		$entity = $this->find()
			->where([
				'Promotion.audience_id' => $id,
				'Promotion.end_datetime >=' => $datetime
			])
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getUserCompletedPromotions($user_id, $datetime): array
	{
		return $this->find()
			->where([
				'Promotion.user_id' => $user_id,
				'Promotion.end_datetime <=' => $datetime,
				'Promotion.active' => 1
			])
			->toArray();
	}

	public function getNonActivePromotions($user_id): array
	{
		return $this->find()
			->where([
				'Promotion.user_id' => $user_id,
				'Promotion.active IN' => [0, 2]
			])
			->toArray();
	}

	public function getVideoPromotions($video_id): array
	{
		return $this->find()
			->where(['Promotion.video_id' => $video_id])
			->toArray();
	}

	public function getVideoPromotionDetail($video_id): array
	{
		$entity = $this->find()
			->where([
				'Promotion.video_id' => $video_id,
				'Promotion.reach < Promotion.price'
			])
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getActivePromotionAgainstPromotionID($promotion_id, $datetime): array
	{
		$entity = $this->find()
			->where([
				'Promotion.id' => $promotion_id,
				'Promotion.start_datetime >=' => $datetime,
				'Promotion.end_datetime <=' => $datetime,
				'Promotion.active' => 1
			])
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getActivePromotionAgainstVideoID($video_id, $datetime): array
	{
		$entity = $this->find()
			->where([
				'Promotion.video_id' => $video_id,
				'Promotion.start_datetime >=' => $datetime,
				'Promotion.end_datetime <=' => $datetime,
				'Promotion.active' => 1
			])
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getPromotionalVideo($user_id, $dob, $gender): array
	{
		$this->addBehavior('Containable');
		$min_age = date_diff(date_create($dob), date_create('now'))->y;
		$max_age = $min_age + 10;
		$entity = $this->find()
			->join([
				'VideoWatch' => [
					'table' => 'video_watch',
					'type' => 'LEFT',
					'conditions' => [
						'VideoWatch.video_id = Promotion.video_id',
						'VideoWatch.user_id' => $user_id
					]
				]
			])
			->where([
				'Promotion.start_datetime <=' => date('Y-m-d H:i:s'),
				'Promotion.end_datetime >=' => date('Y-m-d H:i:s'),
				'Audience.min_age <=' => $max_age,
				'Audience.max_age >=' => $min_age,
				'Promotion.user_id !=' => $user_id,
				'Promotion.reach < Promotion.total_reach',
				'OR' => [
					['Audience.gender' => $gender],
					['Audience.gender' => 'all']
				]
			])
			->contain(['Video.User.PrivacySetting', 'Audience', 'Video.User.PushNotification', 'Video.Sound', 'Video.PinComment', 'Video.VideoComment.User'])
			->order('rand()')
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function getPromotedVideo($user_id, $datetime): array
	{
		$this->addBehavior('Containable');
		$entity = $this->find()
			->where([
				'Promotion.user_id !=' => $user_id,
				'Promotion.reach < Promotion.total_reach',
				'Promotion.start_datetime <=' => $datetime,
				'Promotion.end_datetime >=' => $datetime
			])
			->contain(['Video.User.PrivacySetting', 'Video.User.PushNotification', 'Video.Sound', 'Video.VideoComment.User'])
			->first();
		return $entity ? $entity->toArray() : [];
	}

	public function countPromotionCoin($user_id): array
	{
		$result = $this->find()
			->select(['total_amount' => $this->find()->func()->sum('coin')])
			->where(['Promotion.user_id' => $user_id])
			->first();
		return $result ? $result->toArray() : [];
	}

	public function getPromotionsBasedOnStatus($date, $active): array
	{
		return $this->find()
			->where([
				'Promotion.active' => $active,
				'Promotion.end_datetime >=' => $date
			])
			->order(['Promotion.id' => 'ASC'])
			->toArray();
	}
}
