<?php
/**
 * Construye el objeto Web App Manifest desde settings.pwa y la URL base del sitio.
 */

declare(strict_types=1);

/**
 * @param array<string, mixed> $settings
 * @return array<string, mixed>
 */
function grid_pwa_manifest_array(array $settings, string $baseUrl): array
{
    $p = is_array($settings['pwa'] ?? null) ? $settings['pwa'] : [];
    $name = trim((string)($p['name'] ?? 'Flexia'));
    if ($name === '') {
        $name = 'Flexia';
    }
    $short = trim((string)($p['shortName'] ?? $name));
    if ($short === '') {
        $short = $name;
    }
    $desc = trim((string)($p['description'] ?? ''));
    $lang = trim((string)($p['lang'] ?? 'es')) ?: 'es';
    $theme = grid_pwa_normalize_hex_color((string)($p['themeColor'] ?? '#0ea5e9'), '#0ea5e9');
    $bg = grid_pwa_normalize_hex_color((string)($p['backgroundColor'] ?? '#0f172a'), '#0f172a');
    $display = grid_pwa_enum(
        (string)($p['display'] ?? 'standalone'),
        ['standalone', 'fullscreen', 'minimal-ui', 'browser'],
        'standalone'
    );
    $orientation = grid_pwa_enum(
        (string)($p['orientation'] ?? 'any'),
        ['any', 'natural', 'portrait', 'landscape', 'portrait-primary', 'landscape-primary'],
        'any'
    );
    $startUrl = trim((string)($p['startUrl'] ?? './'));
    if ($startUrl === '') {
        $startUrl = './';
    }
    $scope = trim((string)($p['scope'] ?? './'));
    if ($scope === '') {
        $scope = './';
    }

    $base = rtrim($baseUrl, '/') . '/';
    $icons = [];
    foreach (
        [
            ['rel' => 'icon192Rel', 'sizes' => '192x192', 'purpose' => 'any'],
            ['rel' => 'icon512Rel', 'sizes' => '512x512', 'purpose' => 'any'],
            ['rel' => 'iconMaskable512Rel', 'sizes' => '512x512', 'purpose' => 'maskable'],
        ] as $slot
    ) {
        $rel = (string)($p[$slot['rel']] ?? '');
        if ($rel === '' || strpos($rel, '..') !== false) {
            continue;
        }
        $rel = str_replace('\\', '/', $rel);
        if (!preg_match('#^[a-z0-9_./-]+$#i', $rel)) {
            continue;
        }
        $type = grid_pwa_mime_from_rel($rel);
        $icons[] = [
            'src' => $base . $rel,
            'sizes' => $slot['sizes'],
            'type' => $type,
            'purpose' => $slot['purpose'],
        ];
    }

    $out = [
        'id' => $base,
        'name' => $name,
        'short_name' => $short,
        'description' => $desc !== '' ? $desc : $name,
        'lang' => $lang,
        'dir' => 'ltr',
        'start_url' => $startUrl,
        'scope' => $scope,
        'display' => $display,
        'orientation' => $orientation,
        'theme_color' => $theme,
        'background_color' => $bg,
    ];
    if ($icons !== []) {
        $out['icons'] = $icons;
    }
    $out['categories'] = ['productivity'];

    return $out;
}

function grid_pwa_normalize_hex_color(string $raw, string $fallback): string
{
    $t = trim($raw);
    if (preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $t)) {
        return strtolower($t);
    }
    return $fallback;
}

/**
 * @param list<string> $allowed
 */
function grid_pwa_enum(string $v, array $allowed, string $def): string
{
    $v = strtolower(trim($v));
    return in_array($v, $allowed, true) ? $v : $def;
}

function grid_pwa_mime_from_rel(string $rel): string
{
    $ext = strtolower((string) pathinfo($rel, PATHINFO_EXTENSION));

    return match ($ext) {
        'png' => 'image/png',
        'jpg', 'jpeg' => 'image/jpeg',
        'webp' => 'image/webp',
        'gif' => 'image/gif',
        'svg' => 'image/svg+xml',
        default => 'image/png',
    };
}

/**
 * Metas HTML (sin escapar; usar htmlspecialchars en plantilla).
 *
 * @param array<string, mixed> $settings
 * @return array<string, string>
 */
function grid_pwa_head_meta_lines(array $settings, string $baseUrl): array
{
    $p = is_array($settings['pwa'] ?? null) ? $settings['pwa'] : [];
    if (empty($p['enabled'])) {
        return [];
    }
    $manifestHref = rtrim($baseUrl, '/') . '/manifest.php';
    $name = trim((string)($p['name'] ?? 'Flexia')) ?: 'Flexia';
    $theme = grid_pwa_normalize_hex_color((string)($p['themeColor'] ?? '#0ea5e9'), '#0ea5e9');
    $bg = grid_pwa_normalize_hex_color((string)($p['backgroundColor'] ?? '#0f172a'), '#0f172a');
    $base = rtrim($baseUrl, '/') . '/';

    $lines = [];
    $lines[] = '<link rel="manifest" href="' . htmlspecialchars($manifestHref, ENT_QUOTES, 'UTF-8') . '">';
    $lines[] = '<meta name="theme-color" content="' . htmlspecialchars($theme, ENT_QUOTES, 'UTF-8') . '">';
    $lines[] = '<meta name="apple-mobile-web-app-capable" content="yes">';
    $lines[] = '<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">';
    $lines[] = '<meta name="apple-mobile-web-app-title" content="' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '">';
    $lines[] = '<meta name="application-name" content="' . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . '">';
    $lines[] = '<meta name="msapplication-TileColor" content="' . htmlspecialchars($theme, ENT_QUOTES, 'UTF-8') . '">';
    $lines[] = '<meta name="msapplication-navbutton-color" content="' . htmlspecialchars($theme, ENT_QUOTES, 'UTF-8') . '">';

    $apple = trim((string)($p['appleTouch180Rel'] ?? ''));
    if ($apple !== '' && strpos($apple, '..') === false && preg_match('#^[a-z0-9_./-]+$#i', str_replace('\\', '/', $apple))) {
        $lines[] = '<link rel="apple-touch-icon" href="' . htmlspecialchars($base . str_replace('\\', '/', $apple), ENT_QUOTES, 'UTF-8') . '">';
    }
    $splash = trim((string)($p['splashLaunchRel'] ?? ''));
    if ($splash !== '' && strpos($splash, '..') === false && preg_match('#^[a-z0-9_./-]+$#i', str_replace('\\', '/', $splash))) {
        $lines[] = '<link rel="apple-touch-startup-image" href="' . htmlspecialchars($base . str_replace('\\', '/', $splash), ENT_QUOTES, 'UTF-8') . '">';
    }

    return $lines;
}
