<?php

namespace Modules\Channel\Http\Controllers;

use Carbon\Carbon;
use Catch\Base\CatchController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Channel\Exceptions\ChannelBusinessException;
use Modules\Channel\Models\PayProduct;
use Modules\Channel\Models\PayTemplate;
use Modules\Channel\Models\PayTemplateItem;
use Modules\Channel\Services\User\UserService;
use Modules\Common\Errors\Errors;

class PayTemplateController extends CatchController
{
    use ValidatesRequests;
    public function __construct(protected readonly PayTemplate $payTemplate,protected readonly PayTemplateItem $payTemplateItem,protected readonly PayProduct $payProduct)
    {

    }
    private $sequence_map = [
        '','位置一','位置二','位置三','位置四','位置五','位置六','位置七','位置八'
    ];

    /**
     * 充值模板列表
     *
     * @param Request $request
     * @return void
     */
    public function index(Request $request)
    {
        $uid = $this->getLoginUser()->id;
        if(UserService::userHasRole($uid,'administrator')){
            $uid = 0;
        }
        if($uid) {
            $this->initPayTemplate($uid);
        }
        $name = $request->get('name');
        // 1-首充模板,2-非首充模板
        $type = $request->input('type');
        $where = [['uid','=',$uid,], ['type', '=', $type,]];
        if($name){
            $where[] = ['name','like','%'.$name.'%'];
        }
        $result = $this->payTemplate->orderBy('id','desc')->where($where)->paginate($request->input('limit', 20));
        foreach ($result as $item) {
            $item->status_str = $item->status ? '默认模板': '非默认模板';
            $item->type_str = 1 == $item->type ? '首充模板' : '非首充模板';
        }

        return $result;
    }

    /**
     * 如果优化是没有设置充值模板,那么就是用官方模板进行初始化
     * @param $uid
     */
    private function initPayTemplate($uid) {
        if(!$this->payTemplate->where('uid', $uid)->count()) {
            $systemPayTemplates = $this->payTemplate->where('uid', 0)->get();
            $now = date('Y-m-d H:i:s');
            foreach ($systemPayTemplates as $systemPayTemplate) {
                $payTemplate = $this->payTemplate->create([
                    'uid' => $uid,
                    'name' => $systemPayTemplate->name,
                    'status' => $systemPayTemplate->status,
                    'type' => $systemPayTemplate->type,
                ]);
                $payTemplateItems = $this->payTemplateItem->where([
                    'pay_template_id' => $systemPayTemplate->id, 'status' => 1,
                ])->get();
                $payTemplateItemDatas = [];

                foreach ($payTemplateItems as $item) {
                    $payTemplateItemDatas[] = [
                        'pay_template_id' => $payTemplate->id,
                        'pay_product_id' => $item->pay_product_id,
                        'is_default' => $item->is_default,
                        'status' => $item->status,
                        'sequence' => $item->sequence,
                        'created_at' => $now,
                        'updated_at' => $now,
                    ];
                }
                $this->payTemplateItem->insert($payTemplateItemDatas);
            }
        }
    }

    /**
     * 添加模板
     *
     * @param Request $request
     * @return void
     */
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'options' => 'required',
            'status' => 'required|in:0,1',
            'type' => 'required|in:1,2'
        ]);
        $uid = $this->getLoginUser()->id;
        $name = $request->post('name');
        // 0-非默认模板,1-默认模板
        $status = $request->post('status');
        $options = $request->post('options');
        // 1-首充模板,2-非首充模板
        $type = $request->input('type');

        if(UserService::userHasRole($uid,'administrator')){
            $uid = 0;
        }

        $option_list = json_decode($options,1);
        $data = [];
        $default_optioin = 0;
        $option_cache = [];
        $type_list = collect($this->optionTypeList())->pluck('value');
        foreach($option_list as $option){
            if(!is_numeric($option['price']) || !is_numeric($option['given'])){
                ChannelBusinessException::throwError(Errors::PARAM_ERROR);
            }
            if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
                if($option['given'] > 3*$option['price']*100){
                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
                    break;
                }
            }

            if(!$type_list->contains($option['type'])){
                ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
            }

            if(in_array($option['price'],$option_cache)){
                ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
            }
            $option_cache[] = $option['price'];

            if(!$default_optioin && $option['is_default']){
                $default_optioin = $option['price'];
            }
        }

        $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];

        if($status == 1 && 0 == $uid){
            $this->payTemplate->where([
                'uid' => $uid, 'type' => $type
            ])->update(['status'=>0]);
        }

        $pay_template_info = $this->payTemplate->create(['name'=>$name,'uid'=>$uid,
            'type' => $type, 'status' => $status]);

        foreach($option_list as $option){
            $type = $option['type'];
            if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
                $type = 'COIN';
            }
            $product_info = $this->getPayProduct($option['price'], $type,$option['given']);
            $data[] = [
                'pay_template_id'=>$pay_template_info->id,'pay_product_id'=>$product_info->id,
                'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
                'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
            ];
        }

        $this->payTemplateItem->insert($data);
        return [];
    }

    /**
     * 模板详情
     *
     * @param int $id
     * @return void
     */
    public function show($id)
    {
        $uid = $this->getLoginUser()->id;
        if(UserService::userHasRole($uid,'administrator')){
            $uid = 0;
        }
        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
        if(!$exists){
            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
        }

        $pay_template_item = $this->payTemplateItem->join('pay_products','pay_products.id','=','pay_template_items.pay_product_id')
            ->where('pay_template_id',$id)
            ->select('pay_products.price','pay_products.type','pay_products.given','pay_template_id','pay_product_id','is_first_pay','is_default','sequence','pay_template_items.id as pay_template_item_id')
            ->where('pay_template_items.status',1)
            ->orderBy('pay_template_items.sequence')
            ->get();
        $type_list = collect($this->optionTypeList());
        foreach($pay_template_item as $item){

            if($item->type == 'COIN' && $item->is_first_pay == 1){
                $item->type == 'FIRST_COIN';
            }
            $item->type_name = $type_list->where('value',$item->type)->first()['name'];
            if($item->type == 'COIN' || $item->type == 'FIRST_COIN'){
                $item->charge_coin = (int)($item->price*100);
            }else{
                $item->charge_coin = $item->type_name;
            }


            $item->sequence_text = $this->sequence_map[$item->sequence];
            $item->default_text = $item->is_default? '默认项':"非默认项";
        }

        return [
            'template_info'=>$exists,
            'template_item_list'=>$pay_template_item
        ];
    }

    /**
     * 更新模板
     *
     * @param [type] $id
     * @param Request $request
     * @return void
     */
    public function update($id, Request $request)
    {
        $name = $request->post('name');
        $status = $request->post('status',-1);
        $options = $request->post('options');
        // 1-首充模板,2-非首充模板
        $type = $request->input('type');
        $uid = $this->getLoginUser()->id;
        if(UserService::userHasRole($uid,'administrator')){
            $uid = 0;
        }
        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
        if(!$exists){
            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
        }
        $template_info_update = false;
        if($name){
            $template_info_update = true;
            $exists->name = $name;
        }
        if($status != -1 && in_array($status,[1,0])){
            $template_info_update = true;
            $exists->status = $status;
        }

        if($status == 1){
            $this->payTemplate->where('uid',$uid)->where('type', $type)->update(['status'=>0]);
            $this->payTemplate->where('id',$id)->update(['status'=>1]);
        }
        if($template_info_update){
            $exists->save();
        }

        if($options){
            $option_list = json_decode($options,1);
            $default_optioin = 0;
            $option_cache = [];
            $type_list = collect($this->optionTypeList())->pluck('value');
            foreach($option_list as $option){
                if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
                    if($option['given'] > 3*$option['price']*100){
                        ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
                        break;
                    }
                }

                if(!$type_list->contains($option['type'])){
                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_OPTIONS_ERROR);
                }

                if(in_array($option['price'],$option_cache)){
                    ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_CONFLICT);
                }

                $option_cache[] = $option['price'];

                if(!$default_optioin && $option['is_default']){
                    $default_optioin = $option['price'];
                }

            }
            $this->payTemplateItem->where('pay_template_id',$id)->update(['status'=>0]);
            $default_optioin = $default_optioin>0?$default_optioin:$option_list[0]['price'];
            foreach($option_list as $option){
                $type = $option['type'];
                if($option['type'] == 'COIN' || $option['type'] == 'FIRST_COIN'){
                    $type = 'COIN';
                }
                $product_info = $this->getPayProduct($option['price'], $type,$option['given']);

                $pay_template_item = $this->payTemplateItem->where('pay_template_id',$id)->where('pay_product_id',$product_info->id)->first();
                if($pay_template_item){
                    $pay_template_item->status = 1;
                    $pay_template_item->sequence = $option['sequence'];
                    $pay_template_item->is_first_pay = $option['type'] == 'FIRST_COIN' ?1:0;
                    $pay_template_item->is_default = $option['price'] == $default_optioin ?1:0;
                    $pay_template_item->save();
                }else{
                    $data = [
                        'pay_template_id'=>$id,'pay_product_id'=>$product_info->id,
                        'is_first_pay'=>$option['type'] == 'FIRST_COIN' ?1:0,'is_default'=>$option['price'] == $default_optioin ?1:0,
                        'status'=>1,'sequence'=>$option['sequence'],'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
                    ];
                    $this->payTemplateItem->insert($data);
                }
            }
        }

        return [];
    }


    /**
     * 编辑单条选项
     *
     * @param [type] $id
     * @param Request $request
     * @return void
     */
    public function updatePayTemplateItem($id,Request $request){
        $info = $this->payTemplateItem->find($id);
        $price = $request->post('price');
        $type = $request->post('type');
        if(empty($price) || empty($type)){
            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
        }
        $given = $request->post('given',0);
        if($given > 3*$price*100){
            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_GIVEN_TOO_MUCH);
        }

        $sequence = $request->post('sequence',0);
        $is_default = $request->post('is_default',0);
        $is_first_pay = 0;
        if($type == 'FIRST_COIN'){
            $type = 'COIN';
            $is_first_pay = 1;
        }
        $product_info = $this->getPayProduct($price,$type,$given);
        if($info->pay_product_id == $product_info->id){
            $info->is_first_pay = $is_first_pay;
            $info->is_default = $is_default;
            $info->save();
        }else{
            $info->status = 0;
            $info->save();
            $data = [
                'pay_template_id'=>$info->pay_template_id,'pay_product_id'=>$product_info->id,
                'is_first_pay'=>$is_first_pay,'is_default'=>$is_default,
                'status'=>1,'sequence'=>$sequence,'created_at'=>Carbon::now(),'updated_at'=>Carbon::now()
            ];
            $this->payTemplateItem->insert($data);
        }

        return [];
    }



    /**
     * 删除单条选项
     *
     * @param [type] $id
     * @return void
     */
    public function deleteOneItem($id){
        $info = $this->payTemplateItem->find($id);
        $info->status = 0;
        $info->save();
        return [];
    }


    /**
     * 更新模板状态
     *
     * @param int $id
     * @param Request $request
     * @return void
     */
    public function updateStatus($id,Request $request){
        $uid = $this->getLoginUser()->id;
        if(UserService::userHasRole($uid,'administrator')){
            $uid = 0;
        }

        $exists = $this->payTemplate->where('uid',$uid)->where('id',$id)->first();
        $status = $request->post('status');
        if(!in_array($status,[1,0])){
            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
        }
        if(!$exists){
            ChannelBusinessException::throwError(Errors::PAY_TEMPLATE_NOT_EXISTS_ERROR);
        }
        if($status == 1){
            $this->payTemplate->where('uid',$uid)->update(['status'=>0]);
        }

        $exists->status = $status;
        $exists->save();
        return [];
    }




    private function getPayProduct($price,$type,$given){
        $where = [
            ['price','=',$price],
            ['type','=',$type],
            ['given','=',$given],
        ];
        $product_info = $this->payProduct->where($where)->first();
        if($product_info){
            return $product_info ;
        }
        return $this->payProduct->create(compact('price','type','given'));
    }


    public function optionTypeList(){
        return [
            ['name'=>'普通充值','value'=>'COIN'],
            ['name'=>'包月','value'=>'MONTH'],
            ['name'=>'包季','value'=>'QUARTER'],
            ['name'=>'包年','value'=>'YEAR']
        ];
    }



    public function optionTypeListOutPut(){
        return collect($this->optionTypeList())->map(function($item){
            return [
                'type'=>$item['value'],'type_name'=>$item['name']
            ];
        })->all();
    }


    public function optionSequence(){
        return [
            ['sequence_text'=>'位置一','sequence'=>1],
            ['sequence_text'=>'位置二','sequence'=>2],
            ['sequence_text'=>'位置三','sequence'=>3],
            ['sequence_text'=>'位置四','sequence'=>4],
            ['sequence_text'=>'位置五','sequence'=>5],
            ['sequence_text'=>'位置六','sequence'=>6]
        ];
    }
}
