<?php

namespace App\Services\Attendance;

use App\Models\Role;
use Illuminate\Contracts\Auth\Authenticatable;

class AttendancePolicyService
{
    public function canEditDay(array $dayRow, array $currentUser): bool
    {
        $status = strtolower((string)($dayRow['status'] ?? 'draft'));
        $roles = array_map([$this, 'normalizeRole'], (array)($currentUser['roles'] ?? []));
        $permissions = array_map('strtolower', (array)($currentUser['permissions'] ?? []));

        $isAdmin = $this->isAdminLike($roles, $permissions);
        $isTeacher = in_array('teacher', $roles, true) || in_array('ta', $roles, true) || in_array('teacher_assistant', $roles, true);

        if ($status === 'finalized' || $status === 'published') {
            return $isAdmin;
        }

        if ($status === 'submitted') {
            return $isAdmin;
        }

        if ($status === 'draft') {
            return $isAdmin || $isTeacher;
        }

        return $isAdmin;
    }

    public function isTeacher(array $roles): bool
    {
        $roles = array_map([$this, 'normalizeRole'], $roles);
        return in_array('teacher', $roles, true)
            || in_array('ta', $roles, true)
            || in_array('teacher_assistant', $roles, true)
            || in_array('assistant_teacher', $roles, true);
    }

    public function isAdminLike(array $roles, array $permissions = []): bool
    {
        $roles = array_map([$this, 'normalizeRole'], $roles);
        $adminTokens = $this->adminRoleTokens();

        if (!empty($adminTokens) && count(array_intersect($roles, $adminTokens)) > 0) {
            return true;
        }

        foreach ($permissions as $permission) {
            $permission = strtolower(trim((string) $permission));
            if (str_contains($permission, 'attendance.manage') || str_contains($permission, 'attendance.admin')) {
                return true;
            }
        }

        return false;
    }

    public function normalizeRole(?string $role): string
    {
        return str_replace([' ', '-'], '_', strtolower(trim((string)$role)));
    }

    public function canManageEarlyDismissals(array $userRoles): bool
    {
        $normalized = array_map([$this, 'normalizeRole'], $userRoles);
        $adminTokens = $this->adminRoleTokens();
        $isAdminLike = count(array_intersect($normalized, $adminTokens)) > 0;
        $isTeacher = in_array('teacher', $normalized, true) || in_array('teacher_assistant', $normalized, true);

        return $isAdminLike || $isTeacher;
    }

    private function adminRoleTokens(): array
    {
        static $cache = null;
        if (is_array($cache)) {
            return $cache;
        }

        $tokens = [];
        $normalize = fn (string $value): string => $this->normalizeRole($value);

        try {
            $rows = Role::query()
                ->where('is_active', 1)
                ->get(['name', 'slug']);

            $excluded = array_map($normalize, [
                'guest',
                'parent',
                'student',
                'teacher',
                'teacher_assistant',
                'ta',
            ]);

            foreach ($rows as $row) {
                $name = $normalize((string) ($row->name ?? ''));
                $slug = $normalize((string) ($row->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;
                }
            }
        } catch (\Throwable) {
            // ignore and fall back to defaults
        }

        foreach (['administrator', 'admin', 'principal', 'vice_principal', 'vice-principal'] as $fallback) {
            $tokens[$normalize($fallback)] = true;
        }

        $cache = array_keys($tokens);
        return $cache;
    }
}
