<?php

namespace App\Support;

use App\Models\MariachiGroup;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;

class OwnerWorkspace
{
    public const SESSION_KEY = 'owner_workspace_group_id';

    public static function activeGroupId(Request $request, int $organizationId): ?int
    {
        if ($organizationId <= 0) {
            return null;
        }

        /** @var User|null $user */
        $user = $request->user();
        $rawValue = $request->session()->get(self::SESSION_KEY);
        if ($rawValue === null || $rawValue === '' || (int) $rawValue <= 0) {
            return null;
        }

        $groupId = (int) $rawValue;
        $exists = self::groupsForUser($user)
            ->contains(fn ($group) => (int) $group->id === $groupId);

        return $exists ? $groupId : null;
    }

    public static function setActiveGroupId(Request $request, ?int $groupId): void
    {
        if (empty($groupId) || $groupId <= 0) {
            $request->session()->forget(self::SESSION_KEY);
            return;
        }

        $request->session()->put(self::SESSION_KEY, (int) $groupId);
    }

    public static function groupsForOrganization(int $organizationId)
    {
        if ($organizationId <= 0) {
            return collect();
        }

        MariachiGroup::ensureDefaultForOrganization($organizationId);

        return MariachiGroup::query()
            ->where('organization_id', $organizationId)
            ->where('is_active', true)
            ->orderByDesc('is_default')
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get(['id', 'name', 'is_default']);
    }

    public static function groupsForUser(?User $user)
    {
        if (!$user) {
            return collect();
        }

        $organizationId = (int) ($user->organization_id ?? 0);
        if ($organizationId <= 0) {
            return collect();
        }

        $groups = self::groupsForOrganization($organizationId);

        if ($user->role === User::ROLE_CLIENT || $user->has_all_mariachi_groups) {
            return $groups;
        }

        $assignedIds = $user->assignedMariachiGroups()
            ->where('mariachi_groups.organization_id', $organizationId)
            ->pluck('mariachi_groups.id')
            ->map(fn ($id) => (int) $id)
            ->all();

        if (empty($assignedIds)) {
            return collect();
        }

        return $groups->whereIn('id', $assignedIds)->values();
    }

    public static function accessibleGroupIds(?User $user): array
    {
        return self::groupsForUser($user)
            ->pluck('id')
            ->map(fn ($id) => (int) $id)
            ->values()
            ->all();
    }

    public static function canAccessGroup(?User $user, int $groupId): bool
    {
        if (!$user || $groupId <= 0) {
            return false;
        }

        return in_array($groupId, self::accessibleGroupIds($user), true);
    }

    public static function applyScope(Builder $query, Request $request, string $column = 'mariachi_group_id'): Builder
    {
        /** @var User|null $user */
        $user = $request->user();
        $accessibleGroupIds = self::accessibleGroupIds($user);

        if (empty($accessibleGroupIds)) {
            return $query->whereRaw('1 = 0');
        }

        $organizationId = (int) ($user?->organization_id ?? 0);
        $activeGroupId = self::activeGroupId($request, $organizationId);

        if (!empty($activeGroupId)) {
            return $query->where($column, $activeGroupId);
        }

        return $query->whereIn($column, $accessibleGroupIds);
    }
}
