<?php

namespace App\Http\Services\V1;

use App\Generated\Exceptions\ConflictException;
use App\Generated\Exceptions\NotFoundException;
use App\Generated\Exceptions\UnprocessableEntityException;
use App\Generated\V1\Messages\Pair\ActivityLastMessage;
use App\Generated\V1\Messages\Pair\GetActivityConductStageIdMessage;
use App\Generated\V1\Messages\Pair\ActivityRecentMessage;
use App\Generated\V1\Messages\Pair\ActivityInfoMessage;
use App\Generated\V1\Messages\Pair\LastenrollMessage;
use App\Generated\V1\Messages\Pair\GetActivityListMessage;
use App\Generated\V1\Messages\Pair\GetAloneGroupMessage;
use App\Generated\V1\Messages\Pair\RemoveKeepCpMessage;
use App\Generated\V1\Messages\Pair\KeepCpMessage;
use App\Generated\V1\Messages\Pair\GetKeepRoomMessage;
use App\Generated\V1\Messages\Pair\EnrollProMessage;
use App\Generated\V1\Messages\Pair\EnrollFreeMessage;
use App\Generated\V1\Messages\Pair\GetAllTagsMessage;
use App\Generated\V1\Messages\Pair\AddScoreByFlowerMessage;
use App\Generated\V1\Messages\Pair\RefundMessage;
use App\Generated\V1\Messages\Pair\EnrollNextMessage;
use App\Generated\V1\Messages\Pair\ConfirmBeAloneMessage;
use App\Generated\V1\Messages\Pair\OperationalLogMessage;
use App\Generated\V1\Messages\Pair\RegretsMessage;
use App\Generated\V1\Messages\Pair\ConfirmCpMessage;
use App\Generated\Exceptions\CustomErrorMessageException;
use App\Http\Controllers\Core\Auth;
use App\Models\Fpdx\GroupMemberModel;
use App\Models\Fpdx\OperationalLogModel;
use Illuminate\Support\Facades\DB;
use App\Models\TagModel;
use App\Models\Fpdx\ActivityModel;
use App\Models\Fpdx\RoomModel;
use App\Models\User\UserModel;
use App\Models\Fpdx\GroupModel;
use App\Models\Fpdx\PairModel;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Tymon\JWTAuth\Exceptions\JWTException;
use App\Managers\OrderManager;
use App\Managers\PairManager;

class PairService
{
    protected $pairManager;

    protected $orderManager;

    public function __construct(PairManager $pairManager, OrderManager $orderManager)
    {
        $this->pairManager = $pairManager;
        $this->orderManager = $orderManager;
    }

    public function activityLast(ActivityLastMessage $message)
    {
        $activityType = $message->getActivityType() ?: '72h';

        $activity = ActivityModel::where(function ($query) use ($activityType) {
            if ($activityType == 'qbj') {
                $query->where('qbj_stage_id', '>', 0);
            }
        })->orderBy('stage_id', 'desc')->first();

        try {
            $uid = Auth::auth();
            $first_pair = PairModel::where('uid', $uid)->where(function ($query) {
                /** @var PairModel $query */
                $query->whereNotNull('assoc_id')
                    ->orWhere('last_assoc', '>', 0);
            })->first();
            $activity->first_pair = $first_pair ? false : true;
        } catch (JWTException $e) {
        }
        $message->setResponse($activity);
    }

    /**
     * 获取某人最近一期的活动状态
     *
     * @param  ActivityRecentMessage  $message
     */
    public function activityRecent(ActivityRecentMessage $message)
    {
        $uid = Auth::auth();
        $data = $this->pairManager->getRecentState($uid);

        $message->setResponse($data);
    }

    public function activityInfo(ActivityInfoMessage $message)
    {
        $stage_id = $message->getStageId();
        $uid = Auth::auth();
        $data = $this->pairManager->getActivityInfo($uid, $stage_id);
        $message->setResponse($data);
    }

    public function getActivityConductStageId(GetActivityConductStageIdMessage $message)
    {
        $ings = ActivityModel::getActivitys();
        $data = ActivityModel::findOrFail($ings['ing']);

        $message->setResponse($data);
    }

    public function getAllTags(GetAllTagsMessage $message)
    {
        $datas = TagModel::get()->toArray();
        $result = array();
        foreach ($datas as $data) {
            $tmp = array(
                'id' => (string)$data['id'],
                'name' => $data['name'],
                'group' => (string)$data['group']
            );
            $result[$data['group']][$data['id']] = $tmp;
        }

        $message->setResponse($result);
    }

    public function lastenroll(LastenrollMessage $message)
    {
        $ings = ActivityModel::getActivitys();
        /** @var Collection $pairs */
        $pairs = PairModel::where([
            ['stage_id', $ings['next']],
            ['state', '>', 100]
        ])->take(30)->orderBy('id', 'desc')
            ->get(['id', 'sex', 'stage_id', 'create_time', 'uid']);
        $users = UserModel::whereIn('uid', $pairs->pluck('uid'))->get([
            'uid',
            'headimgurl',
            'nickname',
            'sex',
            'address',
            'home'
        ]);
        foreach ($pairs as &$pair) {
            /** @var UserModel $tmp */
            $tmp = $users->where('uid', $pair->uid) ?? [];
            foreach ($tmp as $v) {
                $pair->user = $v;
            }
        }

        $message->setResponse($pairs);
    }

    public function getActivityList(GetActivityListMessage $message)
    {
        $uid = Auth::auth();

        $lists = DB::table("kdgx_partner_charge_activity")
            ->join(
                "kdgx_partner_charge_pair",
                "kdgx_partner_charge_activity.stage_id",
                "kdgx_partner_charge_pair.stage_id"
            )
            ->where([['kdgx_partner_charge_pair.uid', $uid], ['kdgx_partner_charge_pair.hidden_at', 0]])
            ->orderBy("kdgx_partner_charge_pair.stage_id", "desc")->get();

        foreach ($lists as &$list) {
            try {
                $pair = PairModel::find($list->id);
                $progress = $pair->progress();
                $list->progress = $progress;
            } catch (\Exception $e) {
                app('sentry')->captureException($e);
            }

            $userInfo = DB::table("kdgx_partner_charge_pair")
                ->join("kdgx_partner_charge_user", "kdgx_partner_charge_pair.uid", "kdgx_partner_charge_user.uid")
                ->where([
                    ['kdgx_partner_charge_pair.uid', $uid],
                    ['kdgx_partner_charge_pair.stage_id', $list->stage_id]
                ])
                ->first();
            if (is_null($userInfo->assoc_id)) {
                $list->pair_info = ['user_info' => $userInfo];
            } else {
                $partnerInfo = DB::table("kdgx_partner_charge_pair")
                    ->join("kdgx_partner_charge_user", "kdgx_partner_charge_pair.uid", "kdgx_partner_charge_user.uid")
                    ->where('kdgx_partner_charge_pair.id', $userInfo->assoc_id)
                    ->first();
                try {
                    $roomInfo = RoomModel::findOrFail($partnerInfo->room_id);
                    $roomInfo->online = null;
                    $roomInfo->unread_msg = 0;
                } catch (ModelNotFoundException $exception) {
                    $roomInfo = [];
                }
                $list->pair_info = ['user_info' => $userInfo, 'partner_info' => $partnerInfo, 'room_info' => $roomInfo];
            }
        }

        $message->setResponse($lists);
    }

    public function getKeepRoom(GetKeepRoomMessage $message)
    {
        $uid = Auth::auth();
        $room_id = $this->pairManager->getKeepRoom($uid);
        $room = RoomModel::find($room_id);
        $message->setResponse($room);
    }

    public function keepCp(KeepCpMessage $message)
    {
        $uid = Auth::auth();
        $room_id = $message->getRoomId();
        $this->pairManager->keepRoom($uid, $room_id);
    }

    public function removeKeepCp(RemoveKeepCpMessage $message)
    {
        $uid = Auth::auth();
        $room_id = $message->getRoomId();
        $this->pairManager->removeKeepRoom($uid, $room_id);
    }

    public function getAloneGroup(GetAloneGroupMessage $message)
    {
        $uid = Auth::auth();
        $stageId = $message->getStageId();
        $activityType = $message->getActivityType();
        $groups = GroupMemberModel::where('uid', $uid)
            ->when($stageId, function ($query) use ($stageId) {
                return $query->where('stage_id', $stageId);
            })->when($activityType, function ($query) use ($activityType) {
                return $query->where('activity_type', $activityType);
            })->get();
        foreach ($groups as $group) {
            $group->group = GroupModel::find($group->group_id);
        }
        $message->setResponse($group);
    }


    /**
     * 付费报名
     * @param  EnrollProMessage  $message
     * @throws ConflictException
     * @throws CustomErrorMessageException
     * @throws NotFoundException
     * @throws UnprocessableEntityException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function enrollPro(EnrollProMessage $message)
    {
        $stageId = $message->getStageId();
        $mediaId = $message->getMediaId() ?: config('miniprogram.public_id');
        $agent = $message->getRequest()->header('user-agent');
        $couponId = $message->getCouponId();
        $device = 'other';
        if (
            strpos($agent, 'macintosh')
            || strpos($agent, 'iPod')
            || strpos($agent, 'iPhone')
            || strpos($agent, 'iPad')
        ) {
            $device = "ios";
        }
        if (strpos($agent, 'Android')) {
            $device = 'android';
        }
        $uid = Auth::auth();
        $user = UserModel::find($uid);
        if (!in_array($user->sex, [1, 2])) {
            throw new UnprocessableEntityException('请选择性别');
        }
        if (!in_array($user->sxo, [1, 2])) {
            throw new UnprocessableEntityException('请选择性取向');
        }
        $activity = ActivityModel::enrolling()->first();
        if (!$activity) {
            throw new NotFoundException("活动不存在");
        }
        if ($activity->stage_id !== $stageId) {
            throw new NotFoundException('活动报名已截止报名');
        }
        $pair = PairModel::where('uid', $uid)->where('stage_id', $stageId)->first();
        if ($pair) {
            throw new ConflictException("您已经报名本期活动，请勿重复报名哦");
        }
        if (isset($pair->order_id) && $pair->order_id > 0) {
            throw new CustomErrorMessageException('一次活动只能付费一次');
        }
        $attach = [
            'uid' => $uid,
            'stage_id' => $stageId,
            'media_id' => $mediaId,
            'state' => 103,
            'device' => $device,
        ];
        $orderId = $this->orderManager->unifyOrderByPair($uid, $attach, $couponId);
        $message->setResponse(['order_id' => $orderId]);
    }


    public function enrollFree(EnrollFreeMessage $message)
    {
        $mediaId = $message->getMediaId() ?: config('miniprogram.public_id');
        $state = $message->getState() ?: 2;
        $score = $message->getScore();
        $stageId = $message->getStageId();
        $allowPhoto = $message->getAllowPhoto();
        $activityType = $message->getActivityType();
        $agent = $message->getRequest()->header('user-agent');
        $device = 'other';
        if (
            strpos($agent, 'macintosh')
            || strpos($agent, 'iPod')
            || strpos($agent, 'iPhone')
            || strpos($agent, 'iPad')
        ) {
            $device = "ios";
        }
        if (strpos($agent, 'Android')) {
            $device = 'android';
        }
        $uid = Auth::auth();
        $user = UserModel::find($uid);
        if (!in_array($user->sex, [1, 2])) {
            throw new CustomErrorMessageException('请先选择性别');
        }

        if ($user->sex == 2) {
            $state = 102;
        }

        $attribute = [
            'stage_id' => $stageId,
            'media_id' => $mediaId,
            'uid' => $uid,
            'sex' => $user->sex,
            'state' => $state,
            'data' => $device,
            'add_score' => $score,
            'allow_photo' => $allowPhoto,
            'activity_type' => $activityType,
        ];
        $pair = PairModel::create($attribute);
        $message->setResponse($pair);
    }


    public function addScoreByFlower(AddScoreByFlowerMessage $message)
    {
        $uid = Auth::auth();
        $pairId = $message->getPairId();
        $flowers = [
            'red_flower' => $message->getRedFlower(),
            'gold_flower' => $message->getGoldFlower(),
        ];
        $ps = new \App\Services\Pair\PairService();
        $ps->addScoreByFlower($pairId, $flowers);
    }


    public function refund(RefundMessage $message)
    {
        $uid = Auth::auth();
        $pairId = $message->getPairId();
        $pair = PairModel::findOrFail($pairId);
        if ($pair->uid != $uid) {
            throw new CustomErrorMessageException('无权限');
        }

        $this->pairManager->refund($pair);
    }

    public function enrollNext(EnrollNextMessage $message)
    {
        $uid = Auth::auth();
        $stageId = $message->getLastStageId();
        $agent = $message->getRequest()->header('user-agent');
        $os = 'other';
        if (
            strpos($agent, 'macintosh')
            || strpos($agent, 'iPod')
            || strpos($agent, 'iPhone')
            || strpos($agent, 'iPad')
        ) {
            $os = "ios";
        }
        if (strpos($agent, 'Android')) {
            $os = 'android';
        }
        $data = [
            'allow_photo' => $message->getAllowPhoto(),
        ];

        $pairService = new \App\Services\Pair\PairService();
        $pairId = $pairService->enrollNext($stageId, $uid, $data, $os);
        $message->setResponse([
            'pair_id' => $pairId
        ]);
    }


    public function confirmBeAlone(ConfirmBeAloneMessage $message)
    {
        $uid = Auth::auth();
        $stageId = $message->getStageId();
        $groupId = $this->pairManager->getAloneGroup($uid, $stageId);
        $group = GroupModel::find($groupId);
        $message->setResponse($group);
    }

    public function operationalLog(OperationalLogMessage $message)
    {
        $uid = Auth::auth();
        $stageId = $message->getStageId();
        $type = $message->getType();
        $content = $message->getContent();
        OperationalLogModel::create([
            'uid' => $uid,
            'stage_id' => $stageId,
            'type' => $type,
            'content' => $content
        ]);
    }

    public function regrets(RegretsMessage $message)
    {
        $pairId = $message->getPairId();
        $ps = new \App\Services\Pair\PairService();
        $ps->goBackConfirm($pairId);
    }

    public function confirmCp(ConfirmCpMessage $message)
    {
        $uid = Auth::auth();
        $confirm = $message->getConfirm();
        $pairId = $message->getPairId();
        $pairService = new \App\Services\Pair\PairService();
        $pairService->confirmPair($pairId, $confirm);
    }
}
