<?php

namespace Modules\Channel\Http\Controllers;

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\Common\Errors\Errors;
use Modules\User\Http\Controllers\UserTrait;
use Modules\User\Models\User;

class AdvertiserController extends CatchController
{
    use ValidatesRequests;
    use UserTrait;
    public function __construct(
        protected readonly User $user
    ) {
    }

    /**
     * 添加投手
     * @param Request $request
     * @return int
     * @throws \Illuminate\Validation\ValidationException
     */
    public function addAdvertiser(Request $request) {
        $this->validate($request, [
            'email' => 'required|email',
            'username' => 'required',
            'password' => 'required',
            'repassword' => 'required|same:password',
            'status' => 'required|in:1,2',
            'remark' => 'string|max:140',
            'miniProgramIds' => 'required|array|min:1',
            'miniProgramIds.*' => 'required|integer'
        ]);
        $this->user->emailUnique($request->input('email'));
        $request['roles'] = [(DB::table('roles')->where('identify', 'optimizer')->value('id') ?? 0)];
        $this->user->storeBy($request->all());
        $this->user->pid = $this->getLoginUserId();
        $this->user->save();
        $insertData = [];
        $now = date('Y-m-d H:i:s');
        foreach ($request->input('miniProgramIds') as $miniProgramId) {
            $insertData[] = [
                'uid' => $this->user->id,
                'miniprogram_id' => $miniProgramId,
                'created_at' => $now,
                'updated_at' => $now,
             ];
        }
        DB::table('user_has_miniprograms')
            ->insert($insertData);
        return 1;
    }

    /**
     * 投手账号列表
     * @param Request $request
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     * @throws \Illuminate\Validation\ValidationException
     */
    public function listAdvertiser(Request $request) {
        $this->validate($request, [
            'email' => 'string|email',
            'username' => 'string',
            'miniProgramId' => 'integer',
        ]);
        $miniProgramId = $request->input('miniProgramId');
        $email = $request->input('email');
        $username = $request->input('username');
        $userContext = $this->getUserContext(null);
        $res =   DB::table('users')
            ->leftJoin('user_has_miniprograms', 'users.id', 'user_has_miniprograms.uid')
            ->leftJoin('wechat_authorization_infos as author', 'author.user_id', 'users.id')
            ->where([
                'users.deleted_at' => 0,
            ])->where('users.pid', '<>', 0)
            ->when($userContext['loginUserRoles']->contains('company'), function ($query) use($userContext){
                return $query->where('users.pid' , $userContext['loginUser']->id);
            })
            ->when($userContext['loginUserRoles']->contains('optimizer'), function ($query) use ($userContext){
                return $query->where('users.id', $userContext['loginUser']->id);
            })
            ->when($email, function ($query, $email) {
                return $query->where('users.email', $email);
            })->when($miniProgramId, function ($query, $miniProgramId){
                return $query->where('user_has_miniprograms.miniprogram_id', $miniProgramId);
            })->when($username, function ($query, $username){
                return $query->where('users.username', 'like', '%'.$username.'%');
            })
            ->select(
                'users.id', 'users.username', 'users.email', 'users.status', 'users.remark',
                DB::raw("from_unixtime(users.created_at) as created_at"),
                DB::raw("group_concat(distinct if(user_has_miniprograms.is_enabled = 1, user_has_miniprograms.miniprogram_id, null)  separator ',') as miniProgramIds"),
                DB::raw("group_concat(distinct author.nick_name  separator ',') as gzh_names"),
                DB::raw("NULL as miniPrograms")
            )->groupBy('users.id')
            ->orderBy('users.id','desc')
            ->paginate($request->input('limit', 15));
        $miniProgramIds = collect();
        collect($res->items())->pluck('miniProgramIds')->each(function ($item) use (&$miniProgramIds) {
            $miniProgramIds = $miniProgramIds->merge(explode(',', $item));
        });
        $logos = config('common.common.logos');
        $moduleMap = config('common.common.moduleMap');
        if($miniProgramIds->count()) {
            $miniPrograms = DB::table('miniprogram')->whereIn('id', $miniProgramIds->unique())
                ->select('id', 'name', 'type')
                ->get()->keyBy('id');
            foreach ($res as $item) {
                $item->miniPrograms = [];
                foreach (explode(',', $item->miniProgramIds) as $miniProgramId) {
                    $miniProgram = $miniPrograms->get($miniProgramId);
                    if($miniProgram) {
                        $miniProgram->type_logo = $logos[$miniProgram->type ?? -1] ?? '';
                        $miniProgram->app_name = $moduleMap[$miniProgram->type ?? -1] ?? '';
                        $item->miniPrograms[] = $miniProgram;
                    }
                }
            }
        }
        return $res;
    }

    /**
     * 更新账号
     * @param Request $request
     * @return int
     * @throws \Illuminate\Validation\ValidationException
     */
    public function updateAdvertiser(Request $request) {
        $this->validate($request, [
            'id' => 'required',
            'username' => 'required',
            'miniProgramIds' => 'required|array|min:1',
            'miniProgramIds.*' => 'required|integer',
            'status' => 'required|in:1,2',
            'remark' => 'nullable|string|max:140',
        ]);
        $uid = $request->input('id');
        $user = DB::table('users')
            ->where([
                'deleted_at' => 0,
                'id' => $uid
            ])->select('id','email', 'username', 'status', 'remark')
            ->first();
        if(!$user) {
            ChannelBusinessException::throwError(Errors::USER_NOT_FOUND);
        }
        $this->user->updateBy($uid, $request->only(['remark', 'status', 'username']));
        $now = date('Y-m-d H:i:s');
        DB::table('user_has_miniprograms')
            ->where([
                'uid' => $uid,
                'is_enabled' => 1
            ])->update([
                'is_enabled' => 0,
                'updated_at' => $now,
            ]);
        $insertData = [];
        foreach ($request->input('miniProgramIds') as $miniProgramId) {
            $insertData[] = [
                'uid' => $uid,
                'miniprogram_id' => $miniProgramId,
                'created_at' => $now,
                'updated_at' => $now,
            ];
        }
        DB::table('user_has_miniprograms')
            ->insert($insertData);

        return 1;
    }

    /**
     * 获取投手信息
     * @param Request $request
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
     * @throws \Illuminate\Validation\ValidationException
     */
    public function getAdvertiser(Request $request) {
        $this->validate($request, [
            'id' => 'required'
        ]);

        $user = DB::table('users')
            ->where([
                'deleted_at' => 0,
                'id' => $request->input('id')
            ])->select('id','email', 'username', 'status', 'remark')
            ->first();
        if(!$user) {
            ChannelBusinessException::throwError(Errors::USER_NOT_FOUND);
        }
        $miniProgramIds = DB::table('user_has_miniprograms')
            ->where([
                'is_enabled' => 1,
                'uid' => $user->id,
            ])->select('miniprogram_id')
            ->get()->pluck('miniprogram_id')->toArray();

        $user->miniProgramIds = $miniProgramIds;
        $logos = config('common.common.logos');
        $user->miniPrograms =  DB::table('miniprogram')->whereIn('id', array_unique($miniProgramIds))
            ->select('id', 'name', 'type')->get()->map(function ($item) use ($logos){
                return [
                    'id' => $item->id,
                    'name' => $item->name,
                    'type' => $item->type,
                    'type_logo' => $logos[$item->type] ?? ''
                ];
            });
        return $user;
    }
}
