<?php

class LaporController extends BaseController
{
    public function index()
    {
        $this->checkScopes(['report.moderate']);

        $params = $this->request->get();

        $params['limit'] = $this->getDefaultLimit($params);
        $params["offset"] = array_key_exists("offset", $params) ? $params["offset"] : 0;
        $params["filter_status"] = array_key_exists("filter_status", $params) ? $params["filter_status"] : null;

        $validatedRequest = $this->validate(
            $params,
            [
                'limit' => ['validators' => ['digit']],
                'offset' => ['validators' => ['digit']],
                'filter_status' => ['validators' => ['digit']]
            ]
        );

        $query = DiskusiLapor::query()
            ->limit($validatedRequest['limit'], $validatedRequest['offset'])
            ->orderBy('id DESC');

        $countParams = [];

        if (!is_null($validatedRequest['filter_status'])) {
            $query->AndWhere('status=:status:', ['status' => $validatedRequest['filter_status']]);
            $countParams = ['status=:status:', 'bind' => ['status' => $validatedRequest['filter_status']]];
        }

        $result = $query->execute();

        $totalRecord = DiskusiLapor::count($countParams);

        return new PaginatedResponse($result, $totalRecord, $validatedRequest["limit"], $validatedRequest["offset"]);
    }

    public function detail()
    {
        $this->checkIsAuthenticated();
        $params = $this->request->get();

        $validatedRequest = $this->validate(
            $params,
            [
                'id_diskusi' => ['validators' => ['required']],
                'id_komentar' => ['validators' => []]
            ]
        );

        if (empty($validatedRequest['id_komentar'])) {
            $result = DiskusiLapor::find([
                'id_diskusi = :id_diskusi: AND id_user = :id_user:',
                'bind' => [
                    'id_diskusi' => $validatedRequest['id_diskusi'],
                    'id_user' => $this->shared->user->um_id
                ]
            ]);
        } else {
            $result = DiskusiLapor::find([
                'id_diskusi = :id_diskusi: AND id_komentar=:id_komentar: AND id_user = :id_user:',
                'bind' => [
                    'id_diskusi' => $validatedRequest['id_diskusi'],
                    'id_komentar' => $validatedRequest['id_komentar'],
                    'id_user' => $this->shared->user->um_id
                ]
            ]);
        }

        return new CollectionPaginatedResponse($result);
    }

    public function categoryList()
    {
        $result = DiskusiLaporKategori::find();

        return new CollectionPaginatedResponse($result);
    }

    public function userCategoryList()
    {
        $result = UserLaporKategori::find();

        return new CollectionPaginatedResponse($result);
    }

    public function create()
    {
        $this->checkScopes(['report.create']);

        $rawBody = $this->request->getJsonRawBody(true);
        $validatedRequest = $this->validate(
            $rawBody,
            [
                'id_user_terlapor' => ['validators' => ['digit']],
                'id_diskusi' => ['validators' => ['required', 'digit']],
                'id_kategori' => ['validators' => ['required', 'digit']],
                'id_komentar' => ['validators' => ['digit']],
                'isi' => ['validators' => ['required']],
                'lainnya' => ['validators' => []]
            ]
        );

        if (empty($validatedRequest['id_user_terlapor'])) {
            $kategori = DiskusiLaporKategori::findFirst($validatedRequest['id_kategori']);

            if (empty($kategori)) {
                throw new ValidationException([
                    'field' => 'id_kategori',
                    'message' => 'Kategori tidak ditemukan'
                ]);
            }
        } else {
            $kategori = UserLaporKategori::findFirst($validatedRequest['id_kategori']);

            if (empty($kategori)) {
                throw new ValidationException([
                    'field' => 'id_kategori',
                    'message' => 'Kategori tidak ditemukan'
                ]);
            }
        }

        if (empty($validatedRequest['id_user_terlapor'])) {
            $diskusi = Diskusi::findFirst($validatedRequest['id_diskusi']);

            if (empty($diskusi)) {
                throw new ValidationException([
                    'field' => 'id_diskusi',
                    'message' => 'Diskusi tidak ditemukan'
                ]);
            }

            if (!empty($validatedRequest['id_komentar'])) {
                $komentar = DiskusiComment::findFirst($validatedRequest['id_komentar']);

                if (empty($komentar)) {
                    throw new ValidationException([
                        'field' => 'id_komentar',
                        'message' => 'Komentar tidak ditemukan'
                    ]);
                }

                if ($diskusi->id != $komentar->diskusi_id) {
                    throw new ValidationException([
                        'field' => 'id_komentar',
                        'message' => 'ID komentar dan ID diskusi tidak match'
                    ]);
                }
            }

            if (!empty($validatedRequest['id_komentar'])) {
                $previousReport = DiskusiLapor::find([
                    'id_user = :id_user: AND id_diskusi = :id_diskusi: AND id_komentar = :id_komentar:',
                    'bind' => [
                        'id_user' => $this->shared->user->um_id,
                        'id_diskusi' => $validatedRequest['id_diskusi'],
                        'id_komentar' => $validatedRequest['id_komentar']
                    ]
                ]);
            } else {
                $previousReport = DiskusiLapor::find([
                    'id_user = :id_user: AND id_diskusi = :id_diskusi: AND id_komentar is NULL',
                    'bind' => [
                        'id_user' => $this->shared->user->um_id,
                        'id_diskusi' => $validatedRequest['id_diskusi']
                    ]
                ]);
            }

            if (count($previousReport) > 0) {
                throw new ValidationException([
                    'field' => 'id',
                    'message' => 'User telah melaporkan diskusi/komentar ini sebelumnya'
                ]);
            }
        }

        $report = new DiskusiLapor;
        $report->id_user = $this->shared->user->um_id;
        $report->id_diskusi = $validatedRequest['id_diskusi'];
        $report->id_komentar = $validatedRequest['id_komentar'];
        $report->isi = $validatedRequest['isi'];
        $report->id_kategori = $validatedRequest['id_kategori'];
        if (!empty($validatedRequest['id_user_terlapor'])) {
            $report->id_user_terlapor = $validatedRequest['id_user_terlapor'];
        }
        $report->lainnya = $validatedRequest['lainnya'];
        $report->status = DiskusiLapor::STATUS_INIT;

        $success = $report->create();

        if (!empty($validatedRequest['id_user_terlapor'])) {
            NotificationHelper::batchSend(
                Roles::getAdminUserIds(),
                $report->id_user,
                $report->getAdminNotificationMessageForUser(),
                NotificationHelper::ACTION_REPORT,
                $report->id,
                "/admin/reports",
				NotificationHelper::CATEGORY_REPORT,
                $report->getAdminNotificationMessageForUserEnglish()
            );
        } else {
            NotificationHelper::batchSend(
                Roles::getAdminUserIds(),
                $report->id_user,
                $report->getAdminNotificationMessage(),
                NotificationHelper::ACTION_REPORT,
                $report->id,
                "/admin/reports",
				NotificationHelper::CATEGORY_REPORT,
                $report->getAdminNotificationMessageEnglish()
            );
        }


        $report = DiskusiLapor::findFirst($report->id);

        return new CollectionPaginatedResponse([$report]);;
    }

    public function followUp()
    {
        $this->checkScopes(['report.moderate']);

        $rawBody = $this->request->getJsonRawBody(true);
        $validatedRequest = $this->validate(
            $rawBody,
            [
                'status' => ['validators' => ['required', 'digit']],
                'id' => ['validators' => ['required', 'digit']]
            ]
        );

        $report = DiskusiLapor::findFirst($validatedRequest['id']);

        if (empty($report)) {
            throw new ValidationException([
                'field' => 'id',
                'message' => 'Laporan tidak ditemukan'
            ]);
        }

        if (!DiskusiLapor::isValidStatus($validatedRequest['status'])) {
            throw new ValidationException([
                'field' => 'status',
                'message' => 'Status tidak valid'
            ]);
        }

        $report->updated_by = $this->shared->user->um_id;
        $previousStatus = $report->status;
        $report->status = $validatedRequest['status'];
        $report->updated_at = date('Y-m-d H:i:s');
        $success = $report->save();

        if ($success) {
            if ($previousStatus != $report->status) {
                NotificationHelper::send(
                    $report->getReportedUserId(),
                    $report->id_user,
                    $report->getOwnerNotificationMessage(),
                    NotificationHelper::ACTION_REPORTED,
                    $report->diskusi->uuid,
                    $report->getReportedObjectLink(),
					NotificationHelper::CATEGORY_REPORT,
                    $report->getOwnerNotificationMessageEnglish()
                );

				$currId = $this->shared->user->um_id;
				$adminIds = Roles::getAdminUserIds();
				if (($key = array_search($currId, $adminIds)) !== false) {
					unset($adminIds[$key]);
				}

				NotificationHelper::batchSend(
                    $adminIds,
                    $this->shared->user->um_id,
                    $report->getAllAdminNotificationMessage($this->shared->user->um_user_name),
                    NotificationHelper::ACTION_REPORT,
                    $report->id,
					"/admin/reports",
					NotificationHelper::CATEGORY_REPORT,
                    $report->getAllAdminNotificationMessageEnglish($this->shared->user->um_user_name)
                );
            }
            return new CollectionPaginatedResponse([$report]);
        } else {
            throw new ValidationException($report->getMessages());
        }
    }

    public function batchFollowUp()
    {
        $this->checkScopes(['report.moderate']);

        $rawBody = $this->request->getJsonRawBody(true);
        $validatedRequest = $this->validate(
            $rawBody,
            [
                'status' => ['validators' => ['required', 'digit']],
                'ids' => ['validators' => ['required']]
            ]
        );

        if (!is_array($validatedRequest['ids'])) {
            throw new ValidationException([
                'field' => 'ids',
                'message' => 'Format salah'
            ]);
        }

        if (!($validatedRequest['ids'] === array_filter($validatedRequest['ids'], 'is_int'))) {
            throw new ValidationException([
                'field' => 'ids',
                'message' => 'Format salah'
            ]);
        }

        if (!DiskusiLapor::isValidStatus($validatedRequest['status'])) {
            throw new ValidationException([
                'field' => 'status',
                'message' => 'Status tidak valid'
            ]);
        }

        $reports = DiskusiLapor::find([
            'id in ({ids:array})',
            'bind' => [
                'ids' => $validatedRequest['ids']
            ]
        ]);

        $result = [
            'success_ids' => [],
            'fail_ids' => []
        ];

        foreach ($reports as $report) {
            $previousStatus = $report->status;

            $report->updated_by = $this->shared->user->um_id;
            $report->status = $validatedRequest['status'];
            $report->updated_at = date('Y-m-d H:i:s');
            $success = $report->save();

            if (!empty($report->id_user_terlapor)) {
                if ($validatedRequest['status'] == 1) {
                    $report->deleted_at = null;
                    $report->save();

                    $user = UmUser::findFirstByUmId($report->id_user_terlapor);
                    $user->is_banned = true;
                    $user->save();

                    $tokens = JwtData::findByUserId($report->id_user_terlapor);
                    foreach ($tokens as $token) {
                        if ($token->status == JwtData::STATUS_ACTIVE) {
                            $token->status = JwtData::STATUS_REVOKED;
                            $token->save();
                        }
                    }
                } else {
                    if ($validatedRequest['status'] == 2) {
                        $report->deleted_at = date('Y-m-d H:i:s');
                        $report->save();
                    } else {
                        $report->deleted_at = null;
                        $report->save();
                    }


                    $user = UmUser::findFirstByUmId($report->id_user_terlapor);
                    $user->is_banned = false;
                    $user->save();

                    $tokens = JwtData::findByUserId($report->id_user_terlapor);
                    foreach ($tokens as $token) {
                        if ($token->status == JwtData::STATUS_REVOKED) {
                            $token->status = JwtData::STATUS_ACTIVE;
                            $token->save();
                        }
                    }
                }
            }

            if ($success) {
                array_push($result['success_ids'], $report->id);

                if ($previousStatus != $report->status) {
					$currId = $this->shared->user->um_id;
					$adminIds = Roles::getAdminUserIds();
					if (($key = array_search($currId, $adminIds)) !== false) {
						unset($adminIds[$key]);
					}

                    if (!empty($report->id_user_terlapor)) {
                        NotificationHelper::send(
                            $report->getReportedUserId(),
                            $report->id_user,
                            $report->getOwnerNotificationMessageForUser(),
                            NotificationHelper::ACTION_REPORTED,
                            $report->diskusi->uuid,
                            $report->getReportedObjectLink(),
							NotificationHelper::CATEGORY_REPORT,
                            $report->getOwnerNotificationMessageForUserEnglish()
                        );

						NotificationHelper::batchSend(
							$adminIds,
							$this->shared->user->um_id,
							$report->getAllAdminNotificationMessageForUser($this->shared->user->um_user_name),
							NotificationHelper::ACTION_REPORT,
							$report->id,
							"/admin/reports",
							NotificationHelper::CATEGORY_REPORT,
                            $report->getAllAdminNotificationMessageForUserEnglish($this->shared->user->um_user_name)
						);
                    } else {
                        NotificationHelper::send(
                            $report->getReportedUserId(),
                            $report->id_user,
                            $report->getOwnerNotificationMessage(),
                            NotificationHelper::ACTION_REPORTED,
                            $report->diskusi->uuid,
                            $report->getReportedObjectLink(),
							NotificationHelper::CATEGORY_REPORT,
                            $report->getOwnerNotificationMessageEnglish()
                        );

						NotificationHelper::batchSend(
							$adminIds,
							$this->shared->user->um_id,
							$report->getAllAdminNotificationMessage($this->shared->user->um_user_name),
							NotificationHelper::ACTION_REPORT,
							$report->id,
							"/admin/reports",
							NotificationHelper::CATEGORY_REPORT,
                            $report->getAllAdminNotificationMessageEnglish($this->shared->user->um_user_name)
						);
                    }
                }
            } else {
                array_push($result['fail_ids'], $report->id);
            }
        }

        return new CollectionPaginatedResponse([$result]);;
    }
}
