<?php

namespace backend\models;

use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use common\models\Transfer;
use yii\db\Expression;
use yii\db\Query;
use common\models\Account;
use common\components\Helper;
use common\components\RoleDefinition;

/**
 * TransferSearch represents the model behind the search form about `common\models\Transfer`.
 */
class TransferSearch extends Transfer
{
    public $searchTypeName;

    public $start;
    public $end;

    public $timestampStart;
    public $timestampEnd;

    public $accountTotals;
    public $fullTotal;

    public $types;
    public $totals;

    public $customer_name;
    public $transfer_name;
    public $card_number;
    public $all;

    public $output;

    public $bought_in_interval = false;
    public $payed_in_interval = false;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['id_account', 'id_user', 'type', 'status', 'payment_method','paid_by'], 'integer'],
            [['customer_name','output','transfer_name', 'card_number' ], 'safe'],
//         	[[ 'start', ], 'date'  , 'timestampAttribute' => 'timestampStart' ,'timestampAttributeFormat' => 'yyyy-MM-dd'  ],
//         	[[ 'end' , ], 'date'    , 'timestampAttribute' => 'timestampEnd' ,'timestampAttributeFormat' => 'yyyy-MM-dd' ],
            [['start',], 'date', 'format' => Yii::$app->formatter->datetimeFormat, 'timestampAttribute' => 'timestampStart', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm', 'timeZone' => 'UTC'],
            [['end',], 'date', 'format' => Yii::$app->formatter->datetimeFormat, 'timestampAttribute' => 'timestampEnd', 'timestampAttributeFormat' => 'yyyy-MM-dd HH:mm', 'timeZone' => 'UTC'],
            ['types', 'each', 'rule' => ['integer']],
            [['bought_in_interval','payed_in_interval'],'boolean'] ,
        ];
    }

    /**
     * @inheritdoc
     */
    public function scenarios()
    {
        // bypass scenarios() implementation in the parent class
        return Model::scenarios();
    }

    /**
     * Create the payment method case when sql expression
     * @return Expression the payment method expression
     */
    private function buildPaymentMethodExpression(){
        $s = 'case';
        $arr = Transfer::paymentMethods();
        foreach ( $arr as $key =>$value ){
            $s .= " when transfer.payment_method = $key then  '$value' ";
        }
        $s .= ' end as transfer_payment_method';
        return new Expression($s);
    }

    private function buildTransferNameCondition($transferName){
        $exp =   new Expression( 'case 
            when transfer.type = ' . Transfer::TYPE_TICKET . ' then  ticket_type.name
            when transfer.type = ' . Transfer::TYPE_PRODUCT . ' then product.name 
            when transfer.type = ' . Transfer::TYPE_MONEY_MOVEMENT_OUT . ' then \'Pénzmozgás\' end  = \''.$transferName.'\' ');
        return $exp->__toString() ;
    }


    /**
     * @param $mode         string      the select mode: select or total
     * @param $valid        boolean     the form validation result
     * @return \Yii\db\Query                    the query object
     */
    private function createQuery($mode, $valid)
    {
        $query = new Query();

        if ($mode === 'select') {
            $query->select([
                'transfer.id_transfer as transfer_id_transfer',
                new Expression('case 
            when transfer.type = ' . Transfer::TYPE_TICKET . ' then \'Bérlet\' 
            when transfer.type = ' . Transfer::TYPE_PRODUCT . ' then \'Termék\' 
            when transfer.type = ' . Transfer::TYPE_MONEY_MOVEMENT_OUT . ' then \'Pénzmozgás\' end as transfer_type'),
                new Expression('case 
            when transfer.type = ' . Transfer::TYPE_TICKET . ' then  ticket_type.name
            when transfer.type = ' . Transfer::TYPE_PRODUCT . ' then product.name 
            when transfer.type = ' . Transfer::TYPE_MONEY_MOVEMENT_OUT . ' then \'Pénzmozgás\' end as transfer_name'),
                'user.username as user_username',
                'paid_by.username as paid_by_username',
                'customer.name as customer_name',
                'account.name as account_name',
                'transfer.item_price as transfer_item_price',
                'transfer.count as transfer_count',
                new Expression('case 
            when transfer.direction = ' . Transfer::DIRECTION_IN . ' then  transfer.money
            when transfer.direction = ' . Transfer::DIRECTION_OUT . ' then transfer.money * -1 end  as transfer_money'),
                new Expression('case 
            when transfer.status = ' . Transfer::STATUS_NOT_PAID . ' then  \'Nincs fizetve\'
            when transfer.status = ' . Transfer::STATUS_PAID . ' then \'Fizetve\'
            when transfer.status = ' . Transfer::STATUS_STORNO . ' then \'Törölve\' end  as transfer_status'),
                $this->buildPaymentMethodExpression(),
                'transfer.created_at as transfer_created_at',
                'transfer.paid_at as transfer_paid_at',
                'ticket.start as ticket_start',
                'ticket.end as ticket_end',
                new Expression('case 
                    when transfer.type = ' . Transfer::TYPE_TICKET . ' then  ticket.comment
                    when transfer.type = ' . Transfer::TYPE_PRODUCT . ' then  sale.comment 
                    when transfer.type = ' . Transfer::TYPE_MONEY_MOVEMENT_OUT . ' then  money_movement.comment end as all_comment'),
                ]);
        }else if ( $mode === 'total'){
            $query->select([
               new Expression('coalesce(sum(transfer.count),0) as total_count'),
               new Expression('coalesce(sum(transfer.money),0) as total_money'),
            ]);
        }
        $query->from('transfer');
        $query->innerJoin('account', 'account.id_account = transfer.id_account');
        $query->innerJoin('user', ' user.id = transfer.id_user');
        $query->leftJoin('customer', ' transfer.id_customer = customer.id_customer');
        $query->leftJoin('card', ' card.id_card = customer.id_customer_card');
        $query->leftJoin('user as paid_by', ' paid_by.id = transfer.paid_by');
        $query->leftJoin('ticket', 'ticket.id_ticket = transfer.id_object and transfer.type = ' . Transfer::TYPE_TICKET);
        $query->leftJoin('sale', 'sale.id_sale = transfer.id_object and transfer.type = ' . Transfer::TYPE_PRODUCT);
        $query->leftJoin('money_movement', 'money_movement.id_money_movement = transfer.id_object and transfer.type = ' . Transfer::TYPE_MONEY_MOVEMENT_OUT);
        $query->leftJoin('ticket_type', 'ticket_type.id_ticket_type = ticket.id_ticket_type');
        $query->leftJoin('product', 'product.id_product = sale.id_product');

        if (!$valid) {
            $query->where('0=1');
            return $query;
        }

        if (!RoleDefinition::isAdmin()) {
            $query->innerJoin('user_account_assignment', 'transfer.id_account = user_account_assignment.id_account');
            $query->andWhere(['user_account_assignment.id_user' => Yii::$app->user->id]);
            $query->andWhere(['account.type' => Account::TYPE_ALL]);

            if (RoleDefinition::isReception()) {
                $query->andWhere(['transfer.id_user' => Yii::$app->user->id]);
            }
        }

        $query->andFilterWhere([
            'transfer.id_account' => $this->id_account,
            'transfer.status' => $this->status,
            'transfer.payment_method' => $this->payment_method,
            'customer.name' => $this->customer_name,
            'card.number' => $this->card_number
        ]);

        if ( !empty($this->transfer_name)) {
            $query->andWhere($this->buildTransferNameCondition($this->transfer_name) );
        }
        $query->andFilterWhere(['in', 'transfer.type', $this->types]);


        $all = ($this->bought_in_interval && $this->payed_in_interval)
            || ( !$this->bought_in_interval && !$this->payed_in_interval);


        $orConditions = [];

        if ( $all || $this->bought_in_interval){
            $created_condition = ['and', ['>=', 'transfer.created_at', $this->timestampStart], ['<', 'transfer.created_at', $this->timestampEnd]];
            $orConditions[] = $created_condition;
        }

        if ( $all || $this->payed_in_interval ){
            $paid_condition = ['and', ['>=', 'transfer.paid_at', $this->timestampStart], ['<', 'transfer.paid_at', $this->timestampEnd]];
            $orConditions[] = $paid_condition;
        }


        if ( count($orConditions) === 2){
            $query->andFilterWhere(['or', $orConditions[0], $orConditions[1]]);
        }else if ( count($orConditions) === 1 ){
            $query->andFilterWhere($orConditions[0]);
        }

        if (isset($this->id_user)) {
            $query->andFilterWhere([
                'or',
                ['transfer.id_user' => $this->id_user],
            ]);
        }
        if (isset($this->paid_by)) {
            $query->andFilterWhere([
                'or',
                ['transfer.paid_by' => $this->paid_by],
            ]);
        }

        if (!RoleDefinition::isAdmin()) {
            Helper::restrictIfNotAdminTheStartDate($query, $this->timestampStart, ['transfer.created_at', 'transfer.paid_at']);
        }

        return $query;
    }

    /**
     * Creates data provider instance with search query applied
     *
     * @param array $params
     *
     * @return ActiveDataProvider
     */
    public function search($params)
    {

        $this->load($params);
        $valid = $this->validate();

        $query = $this->createQuery('total',$valid);
        $this->all = $query->one();
        $query = $this->createQuery( 'select', $valid);

        $dataProviderSetup = [
            'query' => $query,
            'sort' => [
                'defaultOrder' => [
                    'transfer_created_at' => SORT_DESC
                ],
                'attributes' => Helper::mkYiiSortItems([
                    ['transfer_id_transfer'],
                    ['transfer_created_at'],
                    ['transfer_type'],
                    ['transfer_name'],
                    ['user_username'],
                    ['paid_by_username'],
                    ['customer_name'],
                    ['account_name'],
                    ['transfer_item_price'],
                    ['transfer_count'],
                    ['transfer_money'],
                    ['transfer_status'],
                    ['transfer_payment_method'],
                    ['transfer_paid_at'],
                    ['ticket_start'],
                    ['ticket_end'],
                    ['all_comment'],
                ])
            ]
        ];

        if ($this->output === 'pdf' || $this->output === 'xls') {
            $dataProviderSetup['pagination'] = false;
        };

        return  new ActiveDataProvider($dataProviderSetup);

    }


    /**
     * @throws \yii\db\Exception
     */
    public function totalsTransfers()
    {
        $accounts = Account::read();
        $idUser = $this->id_user;

        /**mk totals need date time format*/
        $start = $this->timestampStart;
        if (isset($start) && !empty($start)) {
            $start .= ' 00:00';
        }

        $this->totals = Transfer::mkTotals($start, $this->timestampEnd, $idUser, $this->types, $this->id_account, $accounts);


    }

    public function attributeLabels()
    {
        return
            array_merge(
            parent::attributeLabels() ,
                [
                    'bought_in_interval' => 'Kiadva az időszakban',
                    'payed_in_interval' => 'Fizetve az időszakban',
                ]
    );
    }


}
