<?php

namespace Mtc\Core;

use Mtc\Core\Admin\Menu;

class Permissions
{
    const MENU_PERMISSIONS = 'PERMISSIONS';

    const DOCTOR_SIGNATURE = 'DOCTOR_SIGNATURE';
    const RESTRICTED_ORDER_CATEGORIES = 'RESTRICTED_ORDER_CATEGORIES';
    const DOCTOR_ORDER_VIEW = 'DOCTOR_ORDER_VIEW';
    const PHARMACIST_ORDER_VIEW = 'PHARMACIST_ORDER_VIEW';
    const SEE_ALL_REVIEW_ALERTS = 'SEE_ALL_REVIEW_ALERTS';
    const CLINICALLY_CHECK_ORDER = 'CLINICALLY_CHECK_ORDER';
    const LOGIN_AS_PATIENT = 'LOGIN_AS_PATIENT';
    const EXPORT_ELECTRONIC_PRIVATE_REGISTER = 'EXPORT_ELECTRONIC_PRIVATE_REGISTER';
    const REVIEW_DOCTOR_ORDERS = 'REVIEW_DOCTOR_ORDERS';
    const REVIEW_PHARMACY_ORDERS = 'REVIEW_PHARMACY_ORDERS';
    const REVIEW_NHS_ORDERS = 'REVIEW_NHS_ORDERS';
    const REVIEW_PRIVATE_PRESCRIPTION_ORDERS = 'REVIEW_PRIVATE_PRESCRIPTION_ORDERS';
    const DO_BULK_ORDER_ACTIONS = 'DO_BULK_ORDER_ACTIONS';
    const FULL_ORDER_ACCESS = 'FULL_ORDER_ACCESS';
    const EDIT_MESSAGE_TEMPLATES = 'EDIT_MESSAGE_TEMPLATES';

    public static array $allPermissions = [
        self::DOCTOR_SIGNATURE => 'Has Doctor Signature',
        self::RESTRICTED_ORDER_CATEGORIES => 'Has Restricted Order Categories',
        self::DOCTOR_ORDER_VIEW => 'Sees the Doctor order view',
        self::PHARMACIST_ORDER_VIEW => 'Sees the Pharmacist order view',
        self::SEE_ALL_REVIEW_ALERTS => 'Can see all review alerts (not just own)',
        self::CLINICALLY_CHECK_ORDER => 'Can clinically check orders',
        self::LOGIN_AS_PATIENT => 'Can login as patient',
        self::EXPORT_ELECTRONIC_PRIVATE_REGISTER => 'Can Export Electronic Private Register',
        self::REVIEW_DOCTOR_ORDERS => 'Can review Doctor orders',
        self::REVIEW_PHARMACY_ORDERS => 'Can review Pharmacy orders',
        self::REVIEW_NHS_ORDERS => 'Can review NHS orders',
        self::REVIEW_PRIVATE_PRESCRIPTION_ORDERS => 'Can review Private Prescription orders',
        self::DO_BULK_ORDER_ACTIONS => 'Can do bulk order actions',
        self::FULL_ORDER_ACCESS => 'Has full order access',
        self::EDIT_MESSAGE_TEMPLATES => 'Can edit message templates',
    ];

    /**
     * These permissions won't be auto-assigned to MTC admin to not limit functionality
     *
     * @var array|string[]
     */
    public static array $nonAutoMtcPermissions = [
        self::DOCTOR_SIGNATURE,
        self::RESTRICTED_ORDER_CATEGORIES,
        self::DOCTOR_ORDER_VIEW,
        self::PHARMACIST_ORDER_VIEW,
        self::CLINICALLY_CHECK_ORDER,
        self::REVIEW_DOCTOR_ORDERS,
        self::REVIEW_PHARMACY_ORDERS,
        self::REVIEW_NHS_ORDERS,
        self::REVIEW_PRIVATE_PRESCRIPTION_ORDERS,
    ];

    /**
     * Make sure all permissions exist in the database
     *
     * @return void
     */
    public static function initPermissions(): void
    {
        $permissionItems = Menu::all();
        $permissionMenuItem = $permissionItems->where('constant', self::MENU_PERMISSIONS)
            ->first();

        if (empty($permissionMenuItem)) {
            $permissionMenuItem = Menu::query()
                ->create([
                    'sub_id' => 0,
                    'constant' => self::MENU_PERMISSIONS,
                    'title' => 'Permissions',
                ]);
        }

        foreach (self::$allPermissions as $constant => $permissionName) {
            if ($permissionItems->where('constant', $constant)->count() > 0) {
                continue;
            }
            Menu::query()
                ->create([
                    'sub_id' => $permissionMenuItem->id,
                    'constant' => $constant,
                    'title' => $permissionName,
                ]);
        }
    }

    /**
     * Has permission assigned, check by constant
     *
     * @param $permission
     * @param $adminID
     * @return bool
     */
    public static function can($permission, $adminID = null)
    {
        static $permissionCache = [];

        if (!array_key_exists($permission, $permissionCache)) {
            $permissionCache[$permission] = Menu::getByConstant($permission);
        }

        $permissionModel = $permissionCache[$permission];
        if ($permissionModel === null) {
            return false;
        }

        return \AdminUser::can($permissionModel, $adminID);
    }

    /**
     * Whether the user is a reviewer
     *
     * @param $adminID
     * @return bool
     */
    public static function isReviewer($adminID = null): bool
    {
        return self::can(self::REVIEW_DOCTOR_ORDERS) ||
            self::can(self::REVIEW_PHARMACY_ORDERS) ||
            self::can(self::REVIEW_PRIVATE_PRESCRIPTION_ORDERS);
    }
}
