<?php

namespace App\Services;

use App\Models\ChildModel;
use App\Models\CoachModel;

class AuthorizationService
{
    public function getRolesForUser(int $userId): array
    {
        $rows = db_connect()
            ->table('user_roles')
            ->select('roles.slug')
            ->join('roles', 'roles.id = user_roles.role_id')
            ->where('user_roles.user_id', $userId)
            ->orderBy('roles.priority', 'ASC')
            ->get()
            ->getResultArray();

        return array_values(array_map(static fn (array $row): string => $row['slug'], $rows));
    }

    /**
     * @param array<int, string>|string $roles
     */
    public function userHasRole(int $userId, array|string $roles): bool
    {
        $roles = is_array($roles) ? $roles : [$roles];

        return array_intersect($this->getRolesForUser($userId), $roles) !== [];
    }

    public function getPrimaryRole(int $userId): ?string
    {
        return $this->getRolesForUser($userId)[0] ?? null;
    }

    public function getCoachIdForUser(int $userId): ?int
    {
        $coach = model(CoachModel::class)
            ->select('id')
            ->where('user_id', $userId)
            ->first();

        return $coach['id'] ?? null;
    }

    public function userCanAccessChild(int $userId, int $childId): bool
    {
        if ($this->userHasRole($userId, 'admin')) {
            return true;
        }

        if (! $this->userHasRole($userId, 'coach')) {
            return false;
        }

        $coachId = $this->getCoachIdForUser($userId);
        if ($coachId === null) {
            return false;
        }

        $child = model(ChildModel::class)
            ->select('primary_coach_id')
            ->find($childId);

        return $child !== null && (int) ($child['primary_coach_id'] ?? 0) === $coachId;
    }

    public function userCanAccessGroup(int $userId, int $groupId): bool
    {
        if ($this->userHasRole($userId, 'admin')) {
            return true;
        }

        if (! $this->userHasRole($userId, 'coach')) {
            return false;
        }

        $coachId = $this->getCoachIdForUser($userId);
        if ($coachId === null) {
            return false;
        }

        $group = db_connect()
            ->table('academy_groups')
            ->select('primary_coach_id')
            ->where('id', $groupId)
            ->get()
            ->getRowArray();

        return $group !== null && (int) ($group['primary_coach_id'] ?? 0) === $coachId;
    }

    public function userCanAccessSession(int $userId, int $sessionId): bool
    {
        if ($this->userHasRole($userId, 'admin')) {
            return true;
        }

        if (! $this->userHasRole($userId, 'coach')) {
            return false;
        }

        $coachId = $this->getCoachIdForUser($userId);
        if ($coachId === null) {
            return false;
        }

        $session = db_connect()
            ->table('attendance_sessions')
            ->select('academy_group_id, coach_id')
            ->where('id', $sessionId)
            ->get()
            ->getRowArray();

        if ($session === null) {
            return false;
        }

        return (int) ($session['coach_id'] ?? 0) === $coachId || $this->userCanAccessGroup($userId, (int) $session['academy_group_id']);
    }
}
