<?php
// app/Libraries/AttendancePolicy.php
namespace App\Libraries;

use App\Models\RoleModel;

class AttendancePolicy
{
    /**
     * Return a normalized set of tokens (slug and name variants) for roles
     * considered "admin-like" according to the roles table.
     *
     * Rule: any active role whose slug is NOT in the excluded non-admin set
     * (guest, parent, student, teacher, teacher_assistant, ta) is treated
     * as admin-like. Fallback to config('Roles')->roles if the table is
     * unavailable.
     */
    private static function adminRoleTokens(): array
    {
        static $cache = null;
        if ($cache !== null) return $cache;

        $normalize = static function (string $v): string {
            $v = strtolower(trim($v));
            return str_replace([' ', '-'], '_', $v);
        };

        $tokens = [];
        try {
            $model = new RoleModel();
            $rows  = $model
                ->select('name, slug')
                ->where('is_active', 1)
                ->findAll();

            // Slugs that are explicitly NOT admin-like
            $excluded = ['guest','parent','student','teacher','teacher_assistant','ta'];
            $excluded = array_map($normalize, $excluded);

            foreach ($rows as $r) {
                $name = $normalize((string)($r['name'] ?? ''));
                $slug = $normalize((string)($r['slug'] ?? $name));
                if ($name === '' && $slug === '') continue;
                if (in_array($slug, $excluded, true) || in_array($name, $excluded, true)) {
                    continue;
                }
                if ($name !== '') $tokens[$name] = true;
                if ($slug !== '') $tokens[$slug] = true;
            }

            // Safety net: ensure common admin labels are present if defined
            foreach (['administrator','admin','principal','vice_principal','vice-principal'] as $s) {
                $tokens[$normalize($s)] = true;
            }
        } catch (\Throwable $e) {
            // Fallback: use Roles config (if provided)
            try {
                $cfg = config('Roles');
                if ($cfg && is_array($cfg->roles ?? null)) {
                    foreach ($cfg->roles as $r) {
                        $tokens[$normalize((string)$r)] = true;
                    }
                }
            } catch (\Throwable $e2) {
                // minimal fallback
                foreach (['administrator','admin','principal','vice_principal'] as $r) {
                    $tokens[$normalize($r)] = true;
                }
            }
        }

        return $cache = array_keys($tokens);
    }

    public static function canManageEarlyDismissals(array $userRoles): bool
    {
        $normalizedRoles = array_map(static function ($r) {
            $r = strtolower((string) $r);
            $r = str_replace([' ', '-'], '_', $r);
            return $r;
        }, $userRoles);

        $adminTokens = self::adminRoleTokens();
        $isAdminLike = count(array_intersect($normalizedRoles, $adminTokens)) > 0;

        $isTeacher = in_array('teacher', $normalizedRoles, true) || in_array('teacher_assistant', $normalizedRoles, true);

        return $isAdminLike || $isTeacher;
    }

    public static function canEditDay(array $day, array $user): bool
    {
        // Normalize roles (e.g., "Vice Principal" -> "vice_principal")
        $roles = array_map(static function ($r) {
            $r = strtolower((string) $r);
            $r = str_replace([' ', '-'], '_', $r);
            return $r;
        }, (array) ($user['roles'] ?? []));

        // Helper: permissions may be provided either as an associative map
        //   ['attendance.admin_edit' => true] or as a flat list ['attendance.admin_edit']
        $perms = $user['permissions'] ?? [];
        $hasPerm = static function (string $key) use ($perms): bool {
            if (is_array($perms)) {
                // Associative-style map
                if (array_key_exists($key, $perms)) {
                    return (bool) $perms[$key];
                }
                // Flat list of strings
                return in_array($key, $perms, true);
            }
            return false;
        };

        // Determine admin-like status from roles table
        $adminTokens = self::adminRoleTokens();
        $isAdminLike = count(array_intersect($roles, $adminTokens)) > 0;

        // Allow via explicit permissions as well
        $canAdminEditSubmitted = $hasPerm('attendance.admin_edit') || $hasPerm('attendance_admin_edit');
        $canOverridePublished  = $hasPerm('attendance.override_publish') || $hasPerm('attendance_override_publish');

        switch ($day['status']) {
            case 'draft':
                // Open for teachers and admins
                return true;
            case 'submitted':
                // Teachers locked; allow admin-like users, or holders of admin-edit permission
                return $isAdminLike || $canAdminEditSubmitted;
            case 'published':
                // Only allow if explicit override permission is granted
                return $canOverridePublished;
            default:
                return false;
        }
    }
}
