<?php

namespace Modules\Manage\Http\Controllers;

use Catch\Exceptions\FailedException;
use Illuminate\Routing\Controller;
use Catch\Base\CatchController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Channel\Exceptions\ChannelBusinessException;
use Modules\Channel\Models\UserHasMiniprograms;
use Modules\Channel\Services\User\UserService;
use Modules\Common\Errors\Errors;
use Modules\Manage\Enmus\MiniprogramType;
use Modules\Manage\Http\Requests\MiniprogramRequest;
use Modules\Manage\Http\Requests\MiniprogramUpdateRequest;
use Modules\Manage\Models\Miniprogram;
use Modules\User\Http\Controllers\UserTrait;


class MiniprogramController extends CatchController
{

    use UserTrait;
    public function __construct(protected readonly Miniprogram $miniprogram,protected readonly UserHasMiniprograms $userHasMiniprograms)
    {

    }

    const  COMPANY_ROLE = 'company';
    const  ADMINISTRATOR_ROLE = 'administrator';
    const  OPTIMIZER_ROLE = 'optimizer';

    /**
     * 小程序列表
     * @param Request $request
     * @return void
     */
    public function index(Request $request)
    {
        $uid = $this->getLoginUser()->id;
        $name = $request->get('name');
        $play_name = $request->get('play_name');
        $company = $request->get('company');
        $type = $request->get('type');
        $page_size = $request->input('limit', 15);
        $where = [];
        if($name){
            $where[] = ['name','like','%'.$name.'%'];
        }
        if($play_name){
            $where[] = ['play_name','like','%'.$play_name.'%'];
        }
        if($company){
            $where[] = ['company','like','%'.$company.'%'];
        }

        if($type){
            $where[] = ['type','=',$type];
        }
        if(UserService::userHasRole($uid,'administrator')){
            $result = $this->miniprogram->where($where)->orderBy('id','desc')->paginate($page_size);
        }else{
            $result = $this->userHasMiniprograms->join('miniprogram','miniprogram.id','=','user_has_miniprograms.miniprogram_id')
            ->where('user_has_miniprograms.is_enabled',1)
            ->where('uid',$uid)
            ->where($where)
            ->select('miniprogram.*')
            ->paginate($page_size);
        }

        foreach($result as $item){
            $item->type_name = MiniprogramType::from($item->type)->name();
            $item->status_name = $item->status == 1 ?'启用':'禁用';
            $item->pay_merchant_name = getProp($item->pay_merchant_info,'name','-');
            unset($item->pay_merchant_info);
        }
        return $result;
    }

    /**
     * 添加小程序
     *
     * @param MiniprogramRequest $request
     * @return void
     */
    public function store(MiniprogramRequest $request)
    {
        $validate_result = $request->validated();
        $validate_result['remark'] = $request->post('remark','') ?? '';
        if (getProp($validate_result,'pay_merchant_id',0)){
            $info = DB::table('pay_merchants')->where('id',$validate_result['pay_merchant_id'])->first();
            if (empty($info)){
                throw  new  FailedException("支付方式不存在");
            }
            if ($info->miniprogram_type != $validate_result['type']){
                throw  new  FailedException("小程序类型和支付的小程序类型不匹配");
            }
            $validate_result['pay_merchant_info'] = [
                'pay_merchant_id' => $info->id,
                'name' => $info->name,
                'pay_type' => $info->pay_type,
                'payee_name' => $info->payee_name,
                'miniprogram_type' => $info->miniprogram_type,
                'pay_appid' => $info->pay_appid,
            ];

        }else{
            $validate_result['pay_merchant_id'] = 0;
            $validate_result['pay_merchant_info'] = [];
        }

        return $this->miniprogram->create($validate_result)->toArray();

    }

    /**
     * 小程序详情
     *
     * @param [type] $id
     * @return void
     */
    public function show($id)
    {
        return $this->miniprogram->find($id)->toArray();
    }

    /**
     * 更新小程序
     *
     * @param [type] $id
     * @param MiniprogramUpdateRequest $request
     * @return void
     */
    public function update($id, MiniprogramUpdateRequest $request)
    {
        $validate_result = $request->validated();
        if($request->post('remark','')){
            $validate_result['remark'] = $request->post('remark','');
        }
        if (getProp($validate_result,'pay_merchant_id',0)){
            $info = DB::table('pay_merchants')->where('id',$validate_result['pay_merchant_id'])->first();
            if (empty($info)){
                throw  new  FailedException("支付方式不存在");
            }
            if ($info->miniprogram_type != $validate_result['type']){
                throw  new  FailedException("小程序类型和支付的小程序类型不匹配");
            }
            $validate_result['pay_merchant_info'] = [
                'pay_merchant_id' => $info->id,
                'name' => $info->name,
                'pay_type' => $info->pay_type,
                'payee_name' => $info->payee_name,
                'miniprogram_type' => $info->miniprogram_type,
                'pay_appid' => $info->pay_appid,
            ];

        }else{
            $validate_result['pay_merchant_id'] = 0;
            $validate_result['pay_merchant_info'] = [];
        }
        $this->miniprogram->where('id',$id)->update($validate_result);
        return [];
    }


    /**
     * 小程序类型列表
     *
     * @return array [ ['name'=>'微信小程序','id'=>1],[],[] ]
     */
    public function typeList(){
        $type_list =  MiniprogramType::cases();
        $data = array_map( fn($item)=>['name'=>$item->name(),'value'=>$item->value()],$type_list );
        return $data;
    }


    /**
     * 获取所有公司
     *
     * @return void
     */
    public function companyList(){
        return $this->miniprogram->select(DB::raw('distinct company'))->get()->pluck('company');
    }



    /**
     * 绑定小程序和投放公司的关系 或者投放公司把小程序分配给优化师
     * @param [type] $miniprogram_id
     * @param Request $request  uid=2,3,4,5 actison=on|off on:分配,off取消分配
     * @return array
     *
     */
    public function allocationStore($miniprogram_id,Request $request)
    {
        $uid = $this->getLoginUser()->id;
        if(!UserService::userHasRoles($uid,[self::COMPANY_ROLE,self::ADMINISTRATOR_ROLE])){
            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
        }
        $uids = $request->post('uids');
        $action = $request->post('action');
        if(empty($miniprogram_id) || empty($uids) || empty($action) || !in_array($action,['on','off'])){
            ChannelBusinessException::throwError(Errors::PARAM_EMPTY);
        }

        $miniprogram_info =  $this->miniprogram->find($miniprogram_id);
        if(!$miniprogram_info || $miniprogram_info->status == 0){
            ChannelBusinessException::throwError(Errors::MINIPROGRAM_STATUS_ERROR);
        }

        return collect(explode(',',$uids))->filter(function (int $value, int $key) use($miniprogram_id,$action){
            $user_access = UserService::userHasRoles($value,[self::COMPANY_ROLE,self::OPTIMIZER_ROLE]);
            //只能分配给投手公司或者优化师
            if($user_access){
                $result = $this->userHasMiniprograms->where('uid',$value)->where('miniprogram_id',$miniprogram_id)->first();
                if($action == 'off'){
                    if($result){
                        $result->is_enabled = 0;
                        $result->save();
                    }
                    return true;
                }
                if($result){
                    if($result->is_enabled == 0){
                        $result->is_enabled = 1;
                        $result->save();
                    }
                    return true;
                }
                $this->userHasMiniprograms->create([
                    'uid'=>$value,'miniprogram_id'=>$miniprogram_id,'is_enabled'=>1
                ]);
                return true;
            }
            return false;
        });

    }


    /**
     * 获取投手公司和小程序的绑定关系,用于前端数据回显
     * @param [type] $miniprogram_id
     * @return []
     * response = [
     *      'on'=>[ ['id'=>1,'username'=>'公司1','user_has_miniprogram'=>1],[]  ],
     *      'off'=>[['id'=>1,'username'=>'公司1','user_has_miniprogram'=>0],[]],
     *      'all'=>[
     *          ['id'=>1,'username'=>'公司1','user_has_miniprogram'=>1],
     *          ['id'=>2,'username'=>'公司1','user_has_miniprogram'=>0]
     *          ]
     *      ]
     *
     */
    public function getAllocationInfo($miniprogram_id){
        $uid = $this->getLoginUser()->id;
        if(UserService::userHasRole($uid,self::ADMINISTRATOR_ROLE)){
            $all_company_account = UserService::listByRole(self::COMPANY_ROLE,['users.username','users.id']);
        }else{
            $all_company_account = UserService::getOptimizers($uid,['users.username','users.id']);
        }

        $result = $all_company_account->map(function ($item,$key) use($miniprogram_id) {
            $info = $this->userHasMiniprograms->where('uid',$item->id)->where('miniprogram_id',$miniprogram_id)->where('is_enabled',1)->count();
            if($info){
                $item->user_has_miniprogram = 1;
                $item->user_has_miniprogram_flag = 'on';
            }else{
                $item->user_has_miniprogram = 0;
                $item->user_has_miniprogram_flag = 'off';
            }
            return $item;
        });
        $group = $result->groupBy('user_has_miniprogram_flag')->toArray();
        if(!isset($group['on'])){
            $group['on'] = [];
        }
        if(!isset($group['off'])){
            $group['off'] = [];
        }
        $group['all'] = $result->toArray();
        return $group;
    }
}