<?php

/**
 * Branding helpers — themes, colors, logos, favicons.
 *
 * Extracted from app.php to keep visual-identity concerns in one place.
 */

/**
 * Available themes. Fixed two-entry catalog — light and dark.
 *
 * @return array<string, string>
 */
function appThemes(): array
{
    return [
        'light' => 'Light',
        'dark' => 'Dark',
    ];
}

/**
 * Resolve default theme: tenant value, else hardcoded 'light'.
 *
 * Appearance is tenant-scoped — there is no global fallback layer. Pages
 * without a tenant context (login, error) land on 'light'.
 */
function appDefaultTheme(): string
{
    $themes = appThemes();
    $tenantTheme = strtolower(trim((string) ($_SESSION['current_tenant']['default_theme'] ?? '')));
    if ($tenantTheme !== '' && isset($themes[$tenantTheme])) {
        return $tenantTheme;
    }
    return 'light';
}

/**
 * Resolve effective theme with optional per-user override.
 */
function currentTheme(): string
{
    $themes = appThemes();
    $theme = appDefaultTheme();
    if (!allowUserTheme()) {
        return $theme;
    }
    $user = $_SESSION['user'] ?? [];
    $userTheme = strtolower(trim((string) ($user['theme'] ?? '')));
    if ($userTheme !== '' && isset($themes[$userTheme])) {
        return $userTheme;
    }
    return $theme;
}

/**
 * Resolve the theme value to set on the html data-theme attribute.
 *
 * Returns an empty string when no explicit preference has been set by either
 * the user or the tenant — callers should then OMIT data-theme entirely so
 * the browser's prefers-color-scheme media query can drive the theme. Use
 * this only for the html element. Internal consumers (theme toggle,
 * logo URL resolution) keep using currentTheme() / appDefaultTheme() which
 * always return a concrete theme string.
 */
function appExplicitTheme(): string
{
    $themes = appThemes();

    if (allowUserTheme()) {
        $userTheme = strtolower(trim((string) ($_SESSION['user']['theme'] ?? '')));
        if ($userTheme !== '' && isset($themes[$userTheme])) {
            return $userTheme;
        }
    }

    $tenantTheme = strtolower(trim((string) ($_SESSION['current_tenant']['default_theme'] ?? '')));
    if ($tenantTheme !== '' && isset($themes[$tenantTheme])) {
        return $tenantTheme;
    }

    return '';
}

/**
 * Resolve active primary color from the current tenant.
 *
 * Returns null when no tenant is in session (login / error pages) or when
 * the tenant has no primary_color set. Callers must be null-safe — there is
 * no global fallback; appPrimaryCssVars() emits an empty string in that case
 * so Pico defaults apply.
 */
function appPrimaryColor(): ?string
{
    $tenantColor = $_SESSION['current_tenant']['primary_color'] ?? null;
    if ($tenantColor === null) {
        return null;
    }
    $tenantColor = strtolower(trim((string) $tenantColor));
    if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $tenantColor)) {
        return null;
    }
    return $tenantColor;
}

/**
 * Convert current hex color to CSS HSL custom properties.
 */
function appPrimaryCssVars(): string
{
    $hex = appPrimaryColor();
    if ($hex === null) {
        return '';
    }
    $hex = ltrim($hex, '#');
    if (strlen($hex) === 3) {
        $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
    }
    $r = hexdec(substr($hex, 0, 2)) / 255;
    $g = hexdec(substr($hex, 2, 2)) / 255;
    $b = hexdec(substr($hex, 4, 2)) / 255;

    // Short-circuit grayscale values to avoid unstable hue math.
    $monoThreshold = 0.000001;
    if (abs($r - $g) < $monoThreshold && abs($g - $b) < $monoThreshold) {
        $l = round($r * 100, 2) . '%';
        return "--app-primary-h-base: 0; --app-primary-s-base: 0%; --app-primary-l-base: {$l}; --app-primary-h-light: 0; --app-primary-s-light: 0%; --app-primary-l-light: {$l};";
    }

    $max = max($r, $g, $b);
    $min = min($r, $g, $b);
    $delta = $max - $min;

    if ($delta === 0.0) {
        $l = round((($max + $min) / 2) * 100, 2) . '%';
        return "--app-primary-h-base: 0; --app-primary-s-base: 0%; --app-primary-l-base: {$l}; --app-primary-h-light: 0; --app-primary-s-light: 0%; --app-primary-l-light: {$l};";
    }

    $h = 0.0;
    if ($max === $r) {
        $h = 60 * fmod((($g - $b) / $delta), 6);
    } elseif ($max === $g) {
        $h = 60 * ((($b - $r) / $delta) + 2);
    } else {
        $h = 60 * ((($r - $g) / $delta) + 4);
    }
    if ($h < 0) {
        $h += 360;
    }

    $l = ($max + $min) / 2;
    $denominator = 1 - abs(2 * $l - 1);
    if ($delta === 0.0 || $denominator === 0.0) {
        $s = 0.0;
    } else {
        $s = $delta / $denominator;
    }

    $h = round($h, 2);
    $s = round($s * 100, 2) . '%';
    $l = round($l * 100, 2) . '%';

    return "--app-primary-h-base: {$h}; --app-primary-s-base: {$s}; --app-primary-l-base: {$l}; --app-primary-h-light: {$h}; --app-primary-s-light: {$s}; --app-primary-l-light: {$l};";
}

/**
 * Resolve app logo path (custom upload with fallback asset).
 */
function appLogoUrl(?int $size = null): string
{
    if (class_exists('MintyPHP\\Service\\Branding\\BrandingLogoService')) {
        $logoService = app(\MintyPHP\Service\Branding\BrandingLogoService::class);
        if ($logoService->hasLogo()) {
            $query = $size ? '?size=' . (int) $size : '';
            return lurl('branding/logo' . $query);
        }
    }
    return asset('brand/logo.svg');
}

/**
 * Resolve a tenant-scoped logo URL for a given theme with fallback cascade:
 *   1. Tenant logo for the requested theme
 *   2. Tenant logo for the other theme (single-theme tenants work on both sides)
 *   3. Global app logo
 *   4. Hardcoded brand asset
 *
 * $theme defaults to currentTheme() when omitted, which is the correct choice
 * for on-page rendering. For contexts without theme (PDF, e-mail) callers
 * should pass 'light' explicitly via appTenantLogoUrlAbsolute().
 */
function appTenantLogoUrl(?int $size = null, ?string $theme = null): string
{
    $theme = $theme ?? (function_exists('currentTheme') ? currentTheme() : 'light');
    $otherTheme = $theme === 'dark' ? 'light' : 'dark';

    $tenantUuid = $_SESSION['current_tenant']['uuid'] ?? '';
    if ($tenantUuid !== '' && class_exists('MintyPHP\\Service\\Tenant\\TenantLogoService')) {
        $service = app(\MintyPHP\Service\Tenant\TenantLogoService::class);
        foreach ([$theme, $otherTheme] as $candidate) {
            if ($service->hasLogo($tenantUuid, $candidate)) {
                $query = '?uuid=' . rawurlencode($tenantUuid) . '&theme=' . rawurlencode($candidate);
                if ($size) {
                    $query .= '&size=' . (int) $size;
                }
                return lurl('auth/tenant-logo-file' . $query);
            }
        }
    }
    return appLogoUrl($size);
}

/**
 * Absolute tenant-logo URL for flows without theme context (PDF, e-mail).
 * Defaults to the light variant — the single-theme convention for those flows.
 */
function appTenantLogoUrlAbsolute(int $size = 256, string $theme = 'light'): string
{
    return appUrl(appTenantLogoUrl($size, $theme));
}

/**
 * Resolve logo for auth pages: tenant logo (theme-aware) -> global logo -> default.
 *
 * After logout the tenant context (`$_SESSION['current_tenant']`) is preserved,
 * so the login page can show the tenant logo instead of the generic app logo.
 */
function appAuthLogoUrl(?int $size = null): string
{
    return appTenantLogoUrl($size);
}

/**
 * Absolute logo URL (used in e-mails and metadata).
 */
function appLogoUrlAbsolute(int $size = 128): string
{
    $url = appLogoUrl($size);
    return appUrl($url);
}

/**
 * Resolve favicon path (tenant favicon with global fallback).
 */
function appFaviconUrl(string $file): string
{
    $tenantUuid = $_SESSION['current_tenant']['uuid'] ?? '';
    if ($tenantUuid !== '' && class_exists('MintyPHP\\Service\\Tenant\\TenantFaviconService')) {
        if (app(\MintyPHP\Service\Tenant\TenantFaviconService::class)->hasFavicon($tenantUuid)) {
            return asset('favicon/tenants/' . $tenantUuid . '/favicon/' . ltrim($file, '/'));
        }
    }
    return asset('favicon/' . ltrim($file, '/'));
}
