<?php

namespace App\Support;

use Illuminate\Contracts\Auth\Authenticatable;

/**
 * Staff vs account-owner UX: team members are limited to the apps they were
 * invited to. Single-app staff skip Home/launcher; all scoped staff hide
 * Billing/Wallet (the account owner pays).
 *
 * In Care/Meet/etc., values are cached at SSO via Identity (StaffUx::remember).
 * In the monolith, TeamAccessService resolves them live when available.
 */
class StaffUx
{
    public const SESSION_KEY = 'ladill.staff_ux';

    public static function showProductHub(?Authenticatable $user = null): bool
    {
        $user ??= auth()->user();
        if (! $user) {
            return false;
        }

        if ($resolved = self::fromTeamAccess($user)) {
            return $resolved['show_hub'];
        }

        $cached = session(self::SESSION_KEY);
        if (is_array($cached) && array_key_exists('show_hub', $cached)) {
            return (bool) $cached['show_hub'];
        }

        // Unknown in a silo before SSO cache — assume owner (fail open for hub).
        return true;
    }

    public static function showBilling(?Authenticatable $user = null): bool
    {
        $user ??= auth()->user();
        if (! $user) {
            return false;
        }

        if ($resolved = self::fromTeamAccess($user)) {
            return $resolved['show_billing'];
        }

        $cached = session(self::SESSION_KEY);
        if (is_array($cached) && array_key_exists('show_billing', $cached)) {
            return (bool) $cached['show_billing'];
        }

        return true;
    }

    /** @return list<string>|null Null means unrestricted / unknown. */
    public static function allowedAppSlugs(?Authenticatable $user = null): ?array
    {
        $user ??= auth()->user();
        if (! $user) {
            return [];
        }

        if ($resolved = self::fromTeamAccess($user)) {
            return $resolved['full_access'] ? null : $resolved['apps'];
        }

        $cached = session(self::SESSION_KEY);
        if (is_array($cached)) {
            if (! empty($cached['full_access'])) {
                return null;
            }
            if (array_key_exists('apps', $cached) && is_array($cached['apps'])) {
                return array_values(array_map('strval', $cached['apps']));
            }
        }

        return null;
    }

    /**
     * @param  array{full_access?: bool, apps?: list<string>, show_hub?: bool, show_billing?: bool}  $payload
     */
    public static function remember(array $payload): void
    {
        session([self::SESSION_KEY => [
            'full_access' => (bool) ($payload['full_access'] ?? false),
            'apps' => array_values(array_map('strval', (array) ($payload['apps'] ?? []))),
            'show_hub' => (bool) ($payload['show_hub'] ?? false),
            'show_billing' => (bool) ($payload['show_billing'] ?? false),
        ]]);
    }

    /** @return array{full_access: bool, apps: list<string>, show_hub: bool, show_billing: bool}|null */
    private static function fromTeamAccess(Authenticatable $user): ?array
    {
        $service = 'App\\Services\\Team\\TeamAccessService';
        $userClass = 'App\\Models\\User';

        if (! class_exists($service) || ! is_a($user, $userClass)) {
            return null;
        }

        try {
            $access = app($service);

            return [
                'full_access' => $access->hasFullProductAccess($user),
                'apps' => $access->accessibleAppSlugs($user),
                'show_hub' => $access->showProductHub($user),
                'show_billing' => $access->showBilling($user),
            ];
        } catch (\Throwable) {
            return null;
        }
    }
}
