<?php

namespace Modules\Callback\Http\Controllers;

use Catch\Base\CatchController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Common\Errors\Errors;
use Modules\Common\Exceptions\CommonBusinessException;
use Modules\User\Http\Controllers\UserTrait;

class JuliangAccountController extends CatchController
{
    use UserTrait;
    use ValidatesRequests;

    public function list(Request $request) {
        $advAccountId = $request->input('account_id');
        $advAccountName = $request->input('account_name');
        $unBind = $request->input('unbind', 0);
        $id =  $request->input('id', 0);
        $alreadyBindConfigIds = null;
        $promotionId = $request->input('promotion_id',0);

        if($unBind) {
            $alreadyBindConfigIds = DB::table('promotions')
                ->where([
                    'uid' => $this->getOptimizerUid(),
                    'callback_type' => 1,
                    'status' => 1,
                    'is_enabled' => 1,
                ])->where('callback_config_id' , '<>', 0)
                ->distinct()
                ->select('callback_config_id')
                ->get()->pluck('callback_config_id')->toArray();
        }
        $configIds = null;
        if ($promotionId){
            $configIds =  DB::table('promotions')
                ->where([
                    'uid' => $this->getOptimizerUid(),
                    'id' =>  $promotionId,
                    'callback_type' => 1,
                    'status' => 1,
                    'is_enabled' => 1,
                ])->where('callback_config_id' , '<>', 0)
                ->distinct()
                ->select('callback_config_id')
                ->get()->pluck('callback_config_id')->toArray();
                // 没有数据
                if (empty($configIds)){
                    return   DB::table('juliang_account_callback_config')->where('id','<','0')->paginate($request->input('limit', 30));
                }
        }

        $list =  DB::table('juliang_account_callback_config')
            ->where(['company_uid' => $this->getOptimizerUid()])
            ->when($advAccountId, function ($query, $advAccountId) {
                return $query->where('adv_account_id' , $advAccountId);
            })->when($advAccountName, function ($query, $advAccountName) {
                return $query->where('adv_account_name', 'like', '%'. $advAccountName. '%');
            })->when($alreadyBindConfigIds, function ($query, $alreadyBindConfigIds) {
                return $query->whereNotIn('id', $alreadyBindConfigIds);
            })->when($id,function ($query, $id) {
                return $query->where('id', $id);
            })->when($configIds,function ($query,  $configIds) {
                return $query->whereIn('id',$configIds );
            })
            ->orderBy('id', 'desc')
            ->paginate($request->input('limit', 30));
        $ids = collect($list->items())->pluck('id');
        $promotions = DB::table('promotions')
            ->where([
                'uid' => $this->getOptimizerUid(),
                'callback_type' => 1,
                'status' => 1,
                'is_enabled' => 1,
            ])->whereIn('callback_config_id', $ids)
            ->select('name', 'id', 'callback_config_id')
            ->get()->keyBy('callback_config_id');
        foreach ($list as $item) {
            $item->promotion_name = $promotions->get($item->id)->name ?? '';
            $item->promotion_id = $promotions->get($item->id)->id ?? '';
        }

        return $list;
    }

    public function addAccount(Request $request) {
        $this->validate($request, [
            'account_id' => 'required',
            // 'account_name' => 'required|string|max:64',
            'state' => 'required|integer|in:0,1',
            'protect_num' => 'required|integer|min:0',
            'default_rate' => 'required|min:0|max:100',
            'rate_time_config' => 'nullable|array',
            'min_money' => 'required|min:0',
            'max_money' => 'required|min:0'
        ]);

        if(DB::table('juliang_account_callback_config')
            ->where(['company_uid' => $this->getOptimizerUid(), 'adv_account_id' => $request->input('account_id')])
            ->exists()) {
            CommonBusinessException::throwError(Errors::JULIANG_ACCOUNT_EXISTS);
        }
        if($request->input('rate_time_config') &&
            !$this->is_time_cross($request->input('rate_time_config'))) {
            CommonBusinessException::throwError(Errors::CALLBACK_RATE_TIME_RANGE_ERROR);
        }
        $now = date('Y-m-d H:i:s');
        $param = [
            'adv_account_id' => $request->input('account_id'),
            'adv_account_name' => $request->input('account_name',''),
            'state' => $request->input('state'),
            'protect_num' => $request->input('protect_num'),
            'default_rate' => $request->input('default_rate'),
            'rate_time_config' => \json_encode($request->input('rate_time_config', [])),
            'min_money' => $request->input('min_money'),
            'max_money' => $request->input('max_money'),
            'company_uid' => $this->getOptimizerUid(),
            'created_at' => $now,
            'updated_at' => $now,
        ];
        if (empty($param['adv_account_name'])){
            unset($param['adv_account_name']);
        }
        DB::table('juliang_account_callback_config')
            ->insert($param);
        DB::table('juliang_account_rate_config_log')
            ->insert([
                'company_uid' => $this->getOptimizerUid(),
                'account_id' => $request->input('account_id'),
                'config_per' => $request->input('default_rate'),
                'created_at' => $now,
                'updated_at' => $now,
            ]);
        if($request->input('rate_time_config')) {
            $this->saveTimeConfig($this->getOptimizerUid(), $request->input('account_id'), $request);
        }
        return 'ok';
    }

    public function updateCallbackConfig(Request $request) {
        $this->validate($request, [
            'ids' => 'required|array',
            'state' => 'required|integer|in:0,1',
            'protect_num' => 'required|integer|min:0',
            'default_rate' => 'required|min:0|max:100',
            'rate_time_config' => 'nullable|array',
            'min_money' => 'required|min:0',
            'max_money' => 'required|min:0'
        ]);
        if($request->input('callback_rate_time_config') &&
            !$this->is_time_cross($request->input('rate_time_config'))) {
            CommonBusinessException::throwError(Errors::CALLBACK_RATE_TIME_RANGE_ERROR);
        }
        $now = date('Y-m-d H:i:s');
        foreach ($request->input('ids') as $id) {
            DB::table('juliang_account_callback_config')
                ->where(['id' => $id, 'company_uid' => $this->getOptimizerUid()])
                ->update([
                    'state' => $request->input('state'),
                    'protect_num' => $request->input('protect_num'),
                    'default_rate' => $request->input('default_rate'),
                    'rate_time_config' => \json_encode($request->input('rate_time_config', [])),
                    'min_money' => $request->input('min_money'),
                    'max_money' => $request->input('max_money'),
                    'updated_at' => $now,
                ]);
        }
        $advAccountIds = DB::table('juliang_account_callback_config')
            ->whereIn('id', $request->input('ids'))
            ->where('company_uid', $this->getOptimizerUid())
            ->select('adv_account_id')->get()->pluck('adv_account_id');
        if($advAccountIds->isNotEmpty()) {
            DB::table('juliang_account_rate_config_log')
                ->where('company_uid', $this->getOptimizerUid())
                ->whereIn('account_id', $advAccountIds)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            DB::table('juliang_account_promotion_protect_record')
                ->where('optimizer_uid', $this->getOptimizerUid())
                ->whereIn('advertiser_id', $advAccountIds)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            foreach ($advAccountIds as $accountId) {
                DB::table('juliang_account_rate_config_log')
                    ->insert([
                        'company_uid' => $this->getOptimizerUid(),
                        'account_id' => $accountId,
                        'config_per' => $request->input('default_rate'),
                        'created_at' => $now,
                        'updated_at' => $now,
                    ]);
                $this->saveTimeConfig($this->getOptimizerUid(), $accountId, $request);
            }
        }

        return 'ok';
    }

    /**
     * 判断时 设置的时间范围是否有交集
     *
     * @param string $config_time 开始时间1
     * @return bool
     */
    protected  function is_time_cross($config_time) {
        $timeline = [];
        foreach ($config_time as $key => $value) {
            $start_time = $value['start_time'];
            $start = explode(':', $start_time);
            $cur_start = (int)$start[0] * 60 + $start[1];
            $end_time = $value['end_time'];

            $end = explode(':', $end_time);
            $cur_end = (int)$end[0] * 60 + $end[1];
            if ($cur_end <= $cur_start) {
                return false;
            }

            if ($timeline) {
                foreach ($timeline as $k => $v) {
                    if ($cur_start >= $v['start'] && $cur_start <= $v['end']) {
                        return false;
                    }
                    if ($cur_end >= $v['start'] && $cur_end <= $v['end']) {
                        return false;
                    }
                }
            }
            $timeline[] = ['start'=>$cur_start,'end'=>$cur_end];
        }
        return true;
    }


    public  function saveTimeConfig($companyUid, $accountId, $configInfo )
    {
        DB::table('juliang_account_promotion_config_time')
            ->where('is_enable',1)
            ->where('company_uid',$companyUid)
            ->where('account_id',$accountId)->update(['is_enable'=>0]);
        $time_config = $configInfo['rate_time_config'];
        if (empty($time_config)) {
            return false;
        }
        $is = $this->is_time_cross($time_config);
        if (!$is) {
            return false;
        }
        $data = [];
        $temp['company_uid'] = $companyUid;

        $temp['account_id'] = $accountId;
        $temp['other_data']['default_rate'] = $configInfo['default_rate'];
        $temp['other_data']['min_money'] = $configInfo['min_money'];
        $temp['other_data']['max_money'] = $configInfo['max_money'];
        $temp['other_data']['protect_num'] = $configInfo['protect_num'];
        $temp['other_data']['state'] = $configInfo['state'];
        $temp['other_data'] = json_encode($temp['other_data']);
        $temp['next_exec_time'] = date('Y-m-d');

        $temp['is_enable'] = 1;
        $temp['created_at'] = date('Y-m-d H:i:s',time());

        foreach ($time_config as $value) {
            $start_time = $value['start_time'];
            $end_time = $value['end_time'];
            $temp['config_time'] = $start_time;
            $temp['config_per'] = $value['config_per'];
            $data[] = $temp;
            //结束后 百分比改为默认的
            $temp['config_time'] = $end_time;
            $temp['config_per'] = $configInfo['default_rate'];
            $data[] = $temp;
        }
        //插入设置最新的时间段百分比
        DB::table('juliang_account_promotion_config_time')->insert($data);
    }

    /**
     * 回传开关
     * @param Request $request
     * @throws \Illuminate\Validation\ValidationException
     */
    public function turnCallbackState(Request $request) {
        $this->validate($request, ['state' => 'required|integer|in:0,1',
            'id' => 'required']);
        $now = date('Y-m-d H:i:s');
        $config = DB::table('juliang_account_callback_config')
            ->where([
                'id' => $request->input('id'),
                'company_uid' => $this->getOptimizerUid(),
            ])->first();
        if(!$config) {
            CommonBusinessException::throwError(Errors::JULIANG_ACCOUNT_CONFIG_NOT_EXISTS);
        }
        DB::table('juliang_account_callback_config')
            ->where('id', $request->input('id'))
            ->update([
                'state' => $request->input('state'),
                'updated_at' => $now
            ]);
        if(1 == $request->input('state')) {
            DB::table('juliang_account_rate_config_log')
                ->where('company_uid', $this->getOptimizerUid())
                ->where('account_id', $config->adv_account_id)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            DB::table('juliang_account_promotion_protect_record')
                ->where('optimizer_uid', $this->getOptimizerUid())
                ->where('advertiser_id', $config->adv_account_id)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            DB::table('juliang_account_rate_config_log')
                ->insert([
                    'company_uid' => $this->getOptimizerUid(),
                    'account_id' => $config->adv_account_id,
                    'config_per' => $config->default_rate,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
            // 让所有的时间区间比例配置,在定时任务中,重新执行一遍
            DB::table('juliang_account_promotion_config_time')
                ->where('is_enable',1)
                ->where('company_uid',$this->getOptimizerUid())
                ->where('account_id',$config->adv_account_id)
                ->update(['next_exec_time' => date('Y-m-d'), 'updated_at' => $now]);
        }

        return 'ok';
    }

    /**
     * 解绑推广
     * @param Request $request
     */
    public function unbindPromotion(Request $request) {
        $this->validate($request, [
            'id' => 'required'
        ]);

        $config = DB::table('juliang_account_callback_config')
            ->where([
                'id' => $request->input('id'),
                'company_uid' => $this->getOptimizerUid(),
            ])->first();

        if(!$config) {
            CommonBusinessException::throwError(Errors::JULIANG_ACCOUNT_CONFIG_NOT_EXISTS);
        }
        $now = date('Y-m-d H:i:s');
        $affected = DB::table('promotions')
            ->where([
                'callback_type' => 1,
                'callback_config_id' => $request->input('id'),
                'is_enabled' => 1,
                'status' => 1,
            ])->update([
                'status' => 0,
                'updated_at' => $now,
            ]);
        if($affected) {
            DB::table('juliang_account_rate_config_log')
                ->where('company_uid', $this->getOptimizerUid())
                ->where('account_id', $config->adv_account_id)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            DB::table('juliang_account_promotion_protect_record')
                ->where('optimizer_uid', $this->getOptimizerUid())
                ->where('advertiser_id', $config->adv_account_id)
                ->where('is_enabled', 1)
                ->update(['is_enabled' => 0, 'updated_at' => $now]);
            DB::table('juliang_account_rate_config_log')
                ->insert([
                    'company_uid' => $this->getOptimizerUid(),
                    'account_id' => $config->adv_account_id,
                    'config_per' => $config->default_rate,
                    'created_at' => $now,
                    'updated_at' => $now,
                ]);
            // 让所有的时间区间比例配置,在定时任务中,重新执行一遍
            DB::table('juliang_account_promotion_config_time')
                ->where('is_enable',1)
                ->where('company_uid',$this->getOptimizerUid())
                ->where('account_id',$config->adv_account_id)
                ->update(['next_exec_time' => date('Y-m-d'), 'updated_at' => $now]);
        }


        return 'ok';
    }

}
