<?php

namespace Hura8\Components\User\Model;

use Hura8\Components\Customer\PublicController\UCustomerLoginController;
use Hura8\Interfaces\AppResponse;
use Hura8\Interfaces\iEntityStatistic;
use Hura8\System\Model\aEntityBaseModel;
use Hura8\Interfaces\iEntityModel;
use Hura8\System\Security\DataClean;
use Hura8\System\Security\DataType;


class UserReviewModel extends aEntityBaseModel implements iEntityModel
{

    protected $rules = [
        'require-user-login'        => true,
        'auto-approve-message'      => false,
        'detect-spam-before-create' => true,
    ];

    protected $item_type = '';
    protected $item_id = 0;

    /* @var ?iEntityStatistic $iEntityStatisticModel */
    protected  $iEntityStatisticModel;

    public function __construct($item_type, $item_id = 0) {

        $this->item_type    = $item_type;
        $this->item_id      = $item_id;

        $this->iEntityStatisticModel = get_statistic_model_instance($this->item_type);

        // todo: overwrite default rules by client

        parent::__construct("user-review");
    }


    protected function extendedFilterOptions() : array
    {
        return [
            // empty for now
        ];
    }


    public function getSummary(array $conditions = [])
    {
        $where_conditions = [];
        $bind_types = [];
        $bind_values = [];

        //item_type
        $where_conditions[] = " AND `item_type` = ? ";
        $bind_types[] = 's';
        $bind_values[] = $this->item_type;


        //item_id
        $where_conditions[] = " AND `item_id` = ? ";
        $bind_types[] = 's';
        $bind_values[] = $this->item_id;


        //approved
        if(isset($conditions["approved"])  ){
            $where_conditions[] = " AND `approved` = ? ";
            $bind_types[] = 'd';
            $bind_values[] = ($conditions["approved"] ==  1) ? 1 : 0;
        }

        $query = $this->db->runQuery(
            "SELECT AVG(`rate`) AS avgRate, COUNT(*) AS total FROM `". $this->tb_entity ."` WHERE 1 ".join(" ", $where_conditions),
            $bind_types, $bind_values
        );

        if ( $info = $this->db->fetchAssoc($query)  ) {
            return  [
                "avgRate"   => $info['avgRate'],
                "total"     => $info['total'],
            ];
        }

        return  [
            "avgRate"   => 0,
            "total"     => 0,
        ];
    }


    protected function _buildQueryConditionExtend(array $condition) : ?array
    {
        /*$condition = array(
            "q" => "",
            "status" => 0,
            'read' => 1,-1
        );*/

        $catCondition = [];
        $bind_types = [];
        $bind_values = [];

        if(isset($condition["read"]) && $condition["read"]){
            $catCondition[] = " AND `is_read` = ?  ";
            $bind_types[] = 'd';
            $bind_values[] = ($condition["read"] ==  1) ? 1 : 0;
        }

        return array( join(" ", $catCondition), $bind_types, $bind_values);
    }


    protected function beforeCreateItem(array $input_info) : AppResponse
    {
        //todo: check user's authentication and authorization
        if($this->rules['require-user-login'] && !UCustomerLoginController::getLoggedInCustomerId()) {
            return  new AppResponse('error', "Login required");
        }

        $info = $input_info;

        $info['item_type'] = $this->item_type;
        $info['item_id'] = $this->item_id;

        $info['item_title'] = DataClean::limitLengthFullWords($input_info['item_title'], 50);
        $info['title']      = DataClean::limitLengthFullWords($input_info['title'], 50);
        $info['content']    = DataClean::limitLengthFullWords($input_info['content'], 500);

        $info['user_id'] = '';
        $info['user_email'] = DataClean::makeInputSafe($input_info['user_email'], DataType::EMAIL);
        $info['user_name']  = DataClean::limitLengthFullWords($input_info['user_name'], 50);

        // todo: check files actually exists and belong to this user
        $info['files']      = (is_array($input_info['files'])) ? DataClean::makeListOfInputSafe($input_info['files'], DataType::INTEGER) : null;

        //$info['approved'] = (CONFIG_AUTO_APPROVE_REVIEW) ? 1 : 0;
        $info['rate']       = (in_array($info['rate'], [1,2,3,4,5])) ? $info['rate'] : 0;
        $info['ip_address'] = USER_IP;
        $info['user_agent'] = substr(USER_AGENT, 0, 200);

        /*
        "item_type"		=> $post_info['item_type'],
        "item_id"		=>	$post_info['item_id'],
        "item_title"	=>	$post_info['item_title'],
        "is_user_admin"	=>	$post_info['is_user_admin'],
        "user_id"		=>	USER_ID,
        "user_email"	=>	$post_info['user_email'],
        "user_name"		=>	$post_info['user_name'],
        "user_avatar"	=>	$post_info['user_avatar'],
        "user_note"		=>	$post_info['user_note'],
        "rate"			=>	(int) $post_info['rate'],
        "title"			=>	$post_info['title'],
        "content"		=>	$post_info['content'],
        "files"		    =>	$post_info['files'],
        "approved"		=>	(CONFIG_AUTO_APPROVE_REVIEW) ? 1 : 0,
        "post_time"		=>	CURRENT_TIME,
        "ip_address"    => USER_IP,
        "user_agent"	=>	substr(USER_AGENT, 0, 200),*/

        $info['create_time'] = CURRENT_TIME;

        return new AppResponse('ok', null, $info);
    }


    protected function afterCreateItem($new_item_id, $new_item_info)
    {
        // update summary for item
        $this->updateItemReviewCount();
    }


    protected function beforeUpdateItem($item_id, $current_item_info, $new_input_info) : AppResponse
    {
        //todo: check user's authentication and authorization

        $info = $new_input_info;

        $info['last_update'] = CURRENT_TIME;
        $info['last_update_by'] = '';

        return new AppResponse('ok', null, $info);
    }


    protected function afterUpdateItem($item_id, $old_item_info, $new_item_info)
    {

    }


    protected function beforeDeleteItem($item_id, $item_info) : AppResponse
    {
        //todo: check user's authentication and authorization

        return new AppResponse('ok');
    }


    protected function afterDeleteItem($item_id, $item_info)
    {
        // update summary for item
        $this->updateItemReviewCount();
    }


    protected function updateItemReviewCount()
    {
        // update summary for item
        if($this->iEntityStatisticModel) {
            $summary = $this->getSummary([]);
            $this->iEntityStatisticModel->updateReviewCount($this->item_id, $summary['total'], $summary['avgRate']);
        }
    }
}
