<?php

namespace Modules\User\Http\Controllers\Api\Sign;

use App\Api\Controllers\Controller;
use Carbon\Carbon;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Jason\Api\Api;
use Modules\Coupon\Http\Resources\User\UserBaseResource;
use Modules\User\Facades\Calendar;
use Modules\User\Facades\UserSign;
use Modules\User\Http\Resources\Sign\SignBannerResource;
use Modules\User\Http\Resources\Sign\SignTextResource;
use Modules\User\Http\Resources\UserInfoBaseResource;
use Modules\User\Models\Sign;
use Modules\User\Models\SignBanner;
use Modules\User\Models\SignConfig;
use Modules\User\Models\SignLog;
use Modules\User\Models\SignText;
use Overtrue\ChineseCalendar\Calendar as OvertrueCalendar;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Vinkla\Hashids\Facades\Hashids;

class IndexController extends Controller
{

    /**
     * Notes   : 签到的主页，根据配置展示相应内容
     *
     * @Date   : 2021/5/28 4:41 下午
     * @Author : <Jason.C>
     * @param  Request  $request
     * @return JsonResponse
     */
    public function index(Request $request): JsonResponse
    {
        $type = SignConfig::getParams('show_type');

        $user = Api::user();

        switch ($type) {
            case 'week':
                ##todo 根据自然周进行展示，等待完善
                break;
            case 'month':
                //获取年
                $year = $request->year ?? now()->year;
                //获取月份
                $month     = $request->month ?? now()->month;
                $yearMonth = sprintf("%d-%s", $year, $month);
                $data      = $this->month($yearMonth, $user);
                break;
            default:
                $days = $request->days ?? 7;
                $data = $this->sevenDay($days, $user);
                break;
        }
        return $this->success($data);
    }

    /**
     * Notes   : 7天签到图
     *
     * @Date   : 2022/1/7 15:07
     * @Author : Mr.wang
     * @param $days
     * @param $user
     * @return array
     */
    private function sevenDay($days, $user)
    {
        $continue_days = $user->sign->continue_days;
        $modDay        = bcmod($continue_days, $days);
        $cycle         = bcdiv($continue_days, $days, 0);
        $data          = [
            'can_sign'  => ! UserSign::canSign($user, now()),
            'next_task' => '',
        ];
        $task          = UserSign::getNextTaskCrystal($continue_days);
        if ($task) {
            $data['next_task'] = [
                'day'     => $task['day'],
                'diff'    => $task['day'] - $continue_days,
                'crystal' => $task['number'] ?? 0,
            ];
        }
        for ($i = 1; $i <= $days; $i++) {
            $day  = $cycle * $days + $i;
            $text = '第'.$day.'天';
            if ($i == $modDay) {
                $text = '今天';
            }
            $data['lists'][$i] = [
                'sign'    => ($i <= $modDay),
                'crystal' => UserSign::getSignCrystal($day),
                'text'    => $text,
            ];

        }
        if ($user->sign) {
            return $data;
        } else {
            return [];
        }
    }

    /**
     * Notes   : 一月签到图
     *
     * @Date   : 2022/1/7 15:11
     * @Author : Mr.wang
     * @param $yearMonth
     * @param $user
     * @return array[]
     */
    private function month($yearMonth, $user)
    {
        $base = [
            'month'    => $yearMonth,
            'continue' => $user->sign->continue_days,
            'total'    => $user->sign->counts,
            'isSign'   => $user->isSign(),
        ];

        $calendar = Calendar::show($yearMonth)['calendar'];
        $calendar = $calendar->map(function ($info) use ($user) {
            $canSign = UserSign::canSign($user, Carbon::parse($info['today']));
            return array_merge($info, [
                'isSign'    => $user->isSign($info['today']),
                'canSign'   => $canSign,
                'canReSign' => UserSign::canReSign($user, Carbon::parse($info['today']))
            ]);
        });

//        //获取月份第一天所在的星期
//        $firstDayOfWeek = Carbon::parse("$yearMonth-01")->dayOfWeek;
//        //补全
//        $day      = 0;
//        $calendar = [];
//        for ($i = 0; $i < 6; $i++) {
//            for ($j = 0; $j < 7; $j++) {
//                if ($firstDayOfWeek != 0 and $i == 0) {
//                    //根据月初第一天所在的星期，计算出之前几天的日子
//                    $day    = Carbon::parse("$yearMonth-01")->subDays($firstDayOfWeek - $j)->day;
//                    $date   = Carbon::parse("$yearMonth-01")->subDays($firstDayOfWeek - $j);
//                    $hidden = $date->lt(Carbon::parse("$yearMonth-01")->startOfMonth());
//                } else {
//                    $day++;
//                    $date   = Carbon::parse("$yearMonth-01")->addDays($day - 1);
//                    $hidden = $date->gt(Carbon::parse("$yearMonth-01")->endOfMonth());
//                }
//                $calen          = [
//                    'date'     => $date->format("j"),
//                    'isPast'   => $date->isPast(),
//                    'isHidden' => $hidden,
//                    'isSign'   => $user->isSign($date->format('Y-m-d')),
//                ];
//                $calendar[$i][] = $calen;
//            }
//        }

        return [
            'base'     => $base,
            'calendar' => $calendar->splitIn(5),
        ];
    }

    /**
     * Notes   : 签到
     *
     * @Date   : 2021/5/28 3:14 下午
     * @Author : <Jason.C>
     * @return JsonResponse
     */
    public function sign(): JsonResponse
    {
        $user = Api::user();
        try {
            [$res, $message] = UserSign::signIn($user);

            if ($res) {
//                $logs = $user->account->logs()
//                    ->where('rule_id', 10)
//                    ->whereDate('created_at', now())
//                    ->get();


                return $this->success($message);

            } else {
                return $this->failed($message);
            }
        } catch (Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }

    /**
     * Notes   : 预留补签功能
     *
     * @Date   : 2021/5/28 3:14 下午
     * @Author : <Jason.C>
     * @param  Request  $request
     * @return JsonResponse
     */
    public function replenish(Request $request): JsonResponse
    {
        $user = Api::user();
        $date = $request->date;
        $date = Carbon::parse($date);

        try {

            [$res, $message] = UserSign::replenish($user, $date);

            if ($res) {
                return $this->success($message);
            } else {
                return $this->failed('补签失败');
            }
        } catch (Exception $exception) {
            return $this->failed($exception->getMessage());
        }
    }

    /**
     * Notes: 月日历
     *
     * @Author: 玄尘
     * @Date: 2022/8/3 11:44
     * @return JsonResponse
     */
    public function date()
    {
        return $this->success(Calendar::show('2022-07'));
    }

    /**
     * Notes: 签到封面
     *
     * @Author: 玄尘
     * @Date: 2022/8/9 8:15
     * @return JsonResponse
     */
    public function backgrounds(): JsonResponse
    {
        $user = Api::user();

        $signTexts  = SignText::shown()->get();
        $signBanner = SignBanner::query()->shown()->inRandomOrder()->first();
        $calendar   = new OvertrueCalendar();
        $lunarMonth = $calendar->toChinaMonth(now()->month);
        $lunarDay   = $calendar->toChinaDay(now()->day);

        $invite = Hashids::connection('code')->encode($user->id);
        $url    = Config::get('user.invite_code.url').'?invite='.$invite;
        $code   = 'data:image/png;base64,'.base64_encode(QrCode::format('png')
                ->size(100)
                ->margin(3)
                ->generate($url));

        //锶源昆仑
        return $this->success([
            'texts'  => SignTextResource::collection($signTexts),
            'banner' => new SignBannerResource($signBanner),
            'time'   => [
                'yearMonth' => now()->format('Y-m'),
                'time'      => now()->format('H:i'),
                'day'       => now()->format('d'),
                'lunar'     => '农历'.$lunarMonth.$lunarDay,
            ],
            'user'   => [
                'username' => $user->username,
                'nickname' => $user->info->nickname ?? '',
                'avatar'   => $user->info->avatar ?? '',
                'code'     => $code,
            ],
            'sign'   => $user->getSignData()
        ]);
    }

    /**
     * Notes: 签到排行
     *
     * @Author: 玄尘
     * @Date: 2022/8/17 13:43
     * @param  Request  $request
     * @return JsonResponse
     */
    public function rank(Request $request): JsonResponse
    {
        $user  = Api::user();
        $ranks = Sign::query()
            ->latest('counts')
            ->take(10)
            ->get()
            ->map(function ($info) use ($user) {
                return [
                    'user'  => [
                        'user_id'  => $info->user_id,
                        'username' => $info->user->username,
                        'nickname' => $info->user->info->nickname ?? '',
                        'avatar'   => $info->user->info->avatar ?? '',
                    ],
                    'is_my' => $info->user_id == $user->id,
                    'total' => $info->counts,
                ];
            })
            ->pad(10, [
                'user'  => [
                    'user_id'  => 0,
                    'username' => '---',
                    'nickname' => '---',
                    'avatar'   => '---',
                ],
                'is_my' => false,
                'total' => 0,
            ]);

        $ranks  = $ranks->toArray();
        $i      = 1;
        $top    = $other = [];
        $myRank = 0;
        foreach ($ranks as &$rank) {
            $rank['rank'] = $i;
            if ($rank['user']['user_id'] == $user->id) {
                $myRank = $i;
            }

            if ($i < 4) {
                $top[] = $rank;
            } else {
                $other[] = $rank;
            }
            $i++;
        }

        if (! $myRank) {
            $myRank = Sign::query()->where('counts', '>', $user->sign->counts)->count();
        }

        $data = [
            'user'  => [
                'username' => $user->username,
                'nickname' => $user->info->nickname,
                'avatar'   => $user->info->avatar,
                'total'    => $user->sign->counts,
                'rank'     => $myRank ?: $myRank + 1,
            ],
            'top'   => $top,
            'other' => $other,
        ];

        return $this->success($data);


    }

}
