<?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;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'username',
        'email',
        'password',
        'full_name',
        'permission_group_id',
        'is_active',
        'last_login_at',
        'created_by',
        'twofa_enabled',
        'twofa_secret',
        'twofa_confirmed_at',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
        'twofa_secret',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'last_login_at' => 'datetime',
        'is_active' => 'boolean',
        'twofa_enabled' => 'boolean',
        'twofa_confirmed_at' => 'datetime',
    ];

    /**
     * Get the permission group for this user
     */
    public function permissionGroup()
    {
        return $this->belongsTo(PermissionGroup::class);
    }

    /**
     * Get the user who created this user
     */
    public function creator()
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Get activity logs for this user
     */
    public function activityLogs()
    {
        return $this->hasMany(ActivityLog::class);
    }

    /**
     * Check if user has permission for a specific module and action
     */
    public function hasPermission($module, $action = 'read')
    {
        // Super admin (user ID 1) always has full access
        if ((int) $this->id === 1) {
            return true;
        }

        if (!$this->permissionGroup || !$this->is_active) {
            return false;
        }

        $permissions = $this->permissionGroup->permissions;
        $legacyMap = [
            'users' => 'backoffice_users',
            'permissions' => 'backoffice_permissions',
            'settings' => 'system_settings',
        ];

        $moduleKey = $module;
        if (!isset($permissions[$moduleKey]) && isset($legacyMap[$module])) {
            $moduleKey = $legacyMap[$module];
        }

        // Backward compatibility for pre-multisite groups:
        // if "sites.read" is missing, allow access for users that had settings update permission.
        if (
            $module === 'sites' &&
            !isset($permissions['sites']) &&
            $action === 'read'
        ) {
            $legacySettingsUpdate = $this->permissionValueToBool($permissions['settings']['update'] ?? false);
            $legacySystemSettingsUpdate = $this->permissionValueToBool($permissions['system_settings']['update'] ?? false);
            if ($legacySettingsUpdate || $legacySystemSettingsUpdate) {
                return true;
            }
        }

        if (!isset($permissions[$moduleKey][$action])) {
            return false;
        }

        return $this->permissionValueToBool($permissions[$moduleKey][$action]);
    }

    private function permissionValueToBool($value): bool
    {
        if (is_bool($value)) {
            return $value;
        }

        if (is_int($value)) {
            return $value === 1;
        }

        if (is_string($value)) {
            return in_array(strtolower(trim($value)), ['1', 'true', 'yes', 'on'], true);
        }

        return false;
    }

    /**
     * Get all modules user has access to
     */
    public function getAccessibleModules()
    {
        if (!$this->permissionGroup || !$this->is_active) {
            return [];
        }

        $permissions = $this->permissionGroup->permissions;
        $modules = [];

        foreach ($permissions as $module => $actions) {
            if (isset($actions['read']) && $actions['read'] === true) {
                $modules[] = $module;
            }
        }

        return $modules;
    }
}
