<?php

namespace Modules\Base\Http\Controllers\Api;

use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Support\Facades\DB;
use Modules\Base\Notifications\TestNotify;
use Modules\Base\Services\SystemNotificationService;
use Modules\Base\Transformers\AnnouncementTransformer;
use Modules\Base\Transformers\NotificationTransformer;
use SMG\Page\PageModel;

class NotificationsController extends ApiController
{
    /**
     * @return mixed
     *
     * @OA\Get(
     *     tags={"用户"},
     *     summary="通知列表",
     *     path="/api/base/user/notifications",
     *     security={{"jwt_auth":{}}},
     *     @OA\Parameter(
     *         name="filter",
     *         in="query",
     *         required=false,
     *         description="要过滤的类型，目前支持的 type 即 filter[type]=Modules\Base\Notifications\TestNotify",
     *         @OA\Schema(
     *             type="array",
     *             @OA\Items(type="string"),
     *         )
     *     ),
     *     @OA\Parameter(
     *         name="read",
     *         in="query",
     *         required=false,
     *         description="把筛选的结果标记为已读（即在过滤某个类型的通知并标记为已读使用）",
     *         @OA\Schema(
     *             type="string",
     *             default="0",
     *         )
     *     ),
     *     @OA\Parameter(
     *         name="read_all",
     *         in="query",
     *         required=false,
     *         description="把所有通知标记为已读（不包括系统通知）",
     *         @OA\Schema(
     *             type="string",
     *             default="0",
     *         )
     *     ),
     *     @OA\Response(
     *          response="200",
     *          description="成功",
     *          @OA\MediaType(
     *             mediaType="application/json",
     *              @OA\Schema(
     *                  type="object",
     *                  @OA\Property(
     *                      property="data",
     *                      type="array",
     *                      @OA\Items(ref="#/components/schemas/Notification"),
     *                      description="列表"
     *                  ),
     *              )
     *          )
     *      )
     * )
     */
    public function index()
    {
        $notifications = $this->user->notifications()->filter(null, ['type'])->paginate(20);

        if (request('read', 0)) {
            $this->user()->unreadNotifications()->filter(null, ['type'])->update(['read_at' => now()]);
        } elseif (request('read_all', 0)) {
            $this->user()->unreadNotifications()->update(['read_at' => now()]);
        }

        return $this->response->paginator($notifications, new NotificationTransformer());
    }

    /**
     * @return mixed
     *
     * @OA\Get(
     *     tags={"用户"},
     *     summary="系统公告列表",
     *     path="/api/base/user/announcements",
     *     security={{"jwt_auth":{}}},
     *     @OA\Parameter(
     *         name="read_all",
     *         in="query",
     *         required=false,
     *         description="把所有通知标记为已读（不包括系统通知）",
     *         @OA\Schema(
     *             type="string",
     *             default="0",
     *         )
     *     ),
     *     @OA\Response(
     *          response="200",
     *          description="成功",
     *          @OA\MediaType(
     *             mediaType="application/json",
     *              @OA\Schema(
     *                  type="object",
     *                  @OA\Property(
     *                      property="data",
     *                      type="array",
     *                      @OA\Items(ref="#/components/schemas/Announcement"),
     *                      description="列表"
     *                  ),
     *              )
     *          )
     *      )
     * )
     */
    public function announcement()
    {
        $user = $this->user;
        $read_at = $user->system_notice_lastest_read_at ?? $user->created_at;

        $list = PageModel::where('type', 'announcement')->where('disabled', 0)->where('created_at', '>', $user->created_at)->orderBy("id", 'desc')->paginate();
        if (request('read_all', 0)) {
            $user->system_notice_lastest_read_at = now();
            $user->save();
        }

        return $this->response->paginator($list, new AnnouncementTransformer($read_at));
    }

    /**
     * @return mixed
     *
     * @OA\Put(
     *     tags={"用户"},
     *     summary="系统公告列表标记为已读",
     *     path="/api/base/user/announcements",
     *     security={{"jwt_auth":{}}},
     *     @OA\Response(
     *          response="204",
     *          description="成功"
     *      )
     * )
     */
    public function announcementRead()
    {
        $user = $this->user;
        $user->system_notice_lastest_read_at = now();
        $user->save();

        return $this->response->noContent();
    }

    /**
     * @return mixed
     *
     * @OA\Get(
     *     tags={"用户"},
     *     summary="查看通知",
     *     path="/api/base/user/notifications/{notification_id}",
     *     security={{"jwt_auth":{}}},
     *     @OA\Parameter(
     *         name="notification_id",
     *         in="path",
     *         description="通知ID",
     *         required=true,
     *         @OA\Schema(
     *             type="string",
     *         )
     *     ),
     *     @OA\Response(
     *          response="200",
     *          description="成功",
     *          @OA\MediaType(
     *             mediaType="application/json",
     *              @OA\Schema(
     *                  type="object",
     *                  @OA\Property(
     *                      property="data",
     *                      type="array",
     *                      @OA\Items(ref="#/components/schemas/Notification"),
     *                      description="列表"
     *                  ),
     *              )
     *          )
     *      )
     * )
     */
    public function show($notification_id)
    {
        $notification = DatabaseNotification::where('notifiable_id', $this->user->id)->findOrFail($notification_id);

        $notification->markAsRead();

        return $this->response->item($notification, new NotificationTransformer());
    }

    /**
     * @return mixed
     *
     * @OA\Get(
     *     tags={"用户"},
     *     summary="通知数据统计",
     *     path="/api/base/user/notification_stats",
     *     security={{"jwt_auth":{}}},
     *     @OA\Response(
     *          response="200",
     *          description="成功",
     *          @OA\MediaType(
     *             mediaType="application/json",
     *              @OA\Schema(
     *                  type="object",
     *                  @OA\Property(property="count", type="integer", description="消息数量"),
     *                  @OA\Property(property="unread_count", type="integer", description="未读数量"),
     *                  @OA\Property(property="group", type="object", description="分组消息数量"),
     *              )
     *          )
     *      )
     * )
     */
    public function stats()
    {
        $user = $this->user;

        DB::statement("set SESSION sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION ';");

        $query = DatabaseNotification::where('notifiable_id', $user->id);


        $read_at = $user->system_notice_lastest_read_at ?? $user->created_at;
        $query_announcement = PageModel::where('type', 'announcement')->where('disabled', 0);

        $system_notification_count = (clone $query_announcement)->where('created_at', '>', $user->created_at)->count();
        $system_notification_unread_count = (clone $query_announcement)->where('created_at', '>', $read_at)->count();

        $data =[
            'count' => ( clone $query)->count() + $system_notification_count,
            'unread_count' => (clone $query)->whereNull('read_at')->count() + $system_notification_unread_count,
        ];

        $group_count  = (clone $query)->groupBy('type')->select('type', DB::raw('count(id) as count') , DB::raw('max(created_at) as latest') )->get()->toArray();

        $group_unread_count = (clone $query)->whereNull('read_at')->groupBy('type')->select('type', DB::raw('count(id) as count'))->get();

        foreach ($group_count as &$one){
            $type = $one['type'];
            $unread = $group_unread_count->first(function ($item)use($type){
                return $item->type == $type;
            });
            $one['unread_count'] = $unread?$unread->count:0;
        }
        $data['group']=$group_count;
        //系统通知
        $data['system'] = ['count' => $system_notification_count, 'unread_count' => $system_notification_unread_count];

        return $this->response->array($data);
    }

    /**
     * @return \Dingo\Api\Http\Response
     *
     * @OA\Post(
     *     tags={"用户"},
     *     path="/api/base/user/notifications",
     *     summary="向登陆用户发送一条测试消息",
     *     security={
     *         {"jwt_auth": {}}
     *     },
     *     @OA\Response(response="201", description="成功")
     * )
     */
    public function test()
    {
        $this->user()->notify(new TestNotify(['id' => 111,'content' => '这里是内容', 'subject' => '这里是标题']));

        return $this->response->created();
    }

    /**
     * @return mixed
     *
     * @OA\Put(
     *     tags={"用户"},
     *     summary="所有通知标记为已读",
     *     path="/api/base/user/read/notifications",
     *     security={{"jwt_auth":{}}},
     *     @OA\Parameter(
     *         name="filter",
     *         in="query",
     *         required=false,
     *         description="要过滤的类型，目前支持的 type 即 filter[type]=Modules\Base\Notifications\TestNotify",
     *         @OA\Schema(
     *             type="array",
     *             @OA\Items(type="string"),
     *         )
     *     ),
     *     @OA\Response(
     *          response="204",
     *          description="成功"
     *      )
     * )
     */
    public function read()
    {
        $this->user()->unreadNotifications()->filter(null, ['type'])->update(['read_at' => now()]);

        return $this->response->noContent();
    }
}
