<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    protected $fillable = [
        'name', 'username', 'email', 'password', 'userrole', 'district',
        'partner', 'partnerid', 'status'
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function changestatus($formdata, $now, $userid)
    {
        $status = [];
        $update = $this::updateOrCreate(
            ['id' => $formdata['userid']],
            ['status' => $formdata['status']]
        );

        if ($update) {
            $this->afterupdate($update->id, $now, $userid);
            $status['success_message'] = 'Account Status updated successfully';
        } else {
            $status['error_message'] = 'Account Status update failed';
        }

        return $status;
    }

    public function aftersave($id, $now, $userid)
    {
        $update = $this::find($id);
        if ($update) {
            $update->created_at = $now;
            $update->created_by = $userid;
            $update->save();
        }
    }

    public function afterupdate($id, $now, $userid)
    {
        $update = $this::find($id);
        if ($update) {
            $update->updated_at = $now;
            $update->updated_by = $userid;
            $update->save();
        }
    }

    /**
     * Emergency bypass only. Normal administrators must be assigned permissions.
     * This prevents the old issue where disabling a permission still allowed access.
     *
     * To enable break-glass access, set:
     * NGBVD_EMERGENCY_PERMISSION_BYPASS=true
     * NGBVD_PERMISSION_BYPASS_EMAILS=admin@mglsd.go.ug,administrator@mglsd.go.ug
     */
    public function canBypassNgbvdPermissions(): bool
    {
        if (!filter_var(env('NGBVD_EMERGENCY_PERMISSION_BYPASS', false), FILTER_VALIDATE_BOOLEAN)) {
            return false;
        }

        $email = strtolower(trim((string) $this->email));
        $username = strtolower(trim((string) $this->username));
        $allowed = array_filter(array_map(function ($value) {
            return strtolower(trim($value));
        }, explode(',', (string) env('NGBVD_PERMISSION_BYPASS_EMAILS', ''))));

        return in_array($email, $allowed, true) || in_array($username, $allowed, true);
    }

    /**
     * Kept for backward compatibility with older views/controllers.
     * Do not use this as an automatic permission bypass anymore.
     */
    public function isNgbvdAdministrator(): bool
    {
        $email = strtolower(trim((string) $this->email));
        $username = strtolower(trim((string) $this->username));
        $role = strtolower(trim((string) $this->userrole));
        $name = strtolower(trim((string) $this->name));

        return in_array($email, [
                'admin@mglsd.go.ug',
                'administrator@mglsd.go.ug',
            ], true)
            || in_array($username, [
                'admin@mglsd.go.ug',
                'administrator@mglsd.go.ug',
                'admin',
                'administrator',
            ], true)
            || in_array($role, ['1', 'admin', 'administrator', 'super_admin', 'super administrator'], true)
            || in_array($name, ['admin', 'administrator', 'super admin', 'super administrator'], true);
    }

    public function hasNgbvdPermission(string $permissionKey): bool
    {
        if ($this->canBypassNgbvdPermissions()) {
            return true;
        }

        if (!$this->userrole || strpos($permissionKey, '.') === false) {
            return false;
        }

        [$module, $action] = explode('.', $permissionKey, 2);

        try {
            return \App\Models\RolePermission::where('role_id', $this->userrole)
                ->where('module', $module)
                ->where('permission', $action)
                ->where('is_allowed', 1)
                ->exists();
        } catch (\Throwable $e) {
            return false;
        }
    }

    public function hasAnyNgbvdPermission(array $permissionKeys): bool
    {
        if ($this->canBypassNgbvdPermissions()) {
            return true;
        }

        foreach ($permissionKeys as $permissionKey) {
            if ($this->hasNgbvdPermission($permissionKey)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Compatibility alias used by older Blade views/controllers.
     * The canonical method is hasNgbvdPermission().
     */
    public function canAccessPermission(string $permissionKey): bool
    {
        return $this->hasNgbvdPermission($permissionKey);
    }

    /**
     * Compatibility alias for checking multiple permissions.
     */
    public function canAccessAnyPermission(array $permissionKeys): bool
    {
        return $this->hasAnyNgbvdPermission($permissionKeys);
    }

}
