<?php

declare(strict_types=1);

namespace PpPhp\Modules\Settings\Controllers;

use PpPhp\Core\Config;
use PpPhp\Core\PlatformSettings;
use PpPhp\Core\Security;

/**
 * Owner-only "Branding" console — set the product NAME and LOGO once and have them
 * applied across the whole platform (auth screens, account pages, navbars, footers)
 * via the \PpPhp\Core\Brand helper. The logo is stored as a self-contained data-URI
 * in PlatformSettings::BRAND, so there is no file to manage and it travels with a
 * settings export. Nothing here touches generated customer apps.
 */
class BrandingController
{
    /** Accepted logo types → the data-URI mime we store. */
    private const TYPES = [
        'image/svg+xml' => 'image/svg+xml',
        'image/png'     => 'image/png',
        'image/jpeg'    => 'image/jpeg',
        'image/webp'    => 'image/webp',
        'image/gif'     => 'image/gif',
    ];
    private const MAX_BYTES = 200 * 1024; // 200 KB before base64

    public function __construct(private Config $config) {}

    private function gate(): void
    {
        Security::RequireAuth();
        if (!Security::IsOwner()) {
            redirect('/projects');
        }
    }

    /** The Branding form lives inside the Core Configuration console. */
    public function save(): void
    {
        $this->gate();

        if (!Security::CSRF()->Check((string) ($_POST['_token'] ?? ''))) {
            redirect('/settings/core-config?brand_error=' . rawurlencode('Your session expired — please try again.'));
        }

        $brand = PlatformSettings::brand();
        $name  = trim((string) ($_POST['brand_name'] ?? ''));
        $brand['name']    = $name !== '' ? mb_substr($name, 0, 40) : PlatformSettings::DEFAULT_BRAND_NAME;
        $brand['tagline'] = mb_substr(trim((string) ($_POST['brand_tagline'] ?? '')), 0, 80);

        if (!empty($_POST['remove_logo'])) {
            $brand['logo'] = '';
        } elseif (!empty($_FILES['brand_logo']['tmp_name']) && is_uploaded_file($_FILES['brand_logo']['tmp_name'])) {
            $result = $this->readLogo($_FILES['brand_logo']);
            if ($result['ok'] === false) {
                redirect('/settings/core-config?brand_error=' . rawurlencode($result['message']));
            }
            $brand['logo'] = $result['dataUri'];
        }

        PlatformSettings::set(PlatformSettings::BRAND, $brand);
        redirect('/settings/core-config?brand=saved');
    }

    /** Validate + read an uploaded logo into a data-URI. */
    private function readLogo(array $file): array
    {
        if (($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
            return ['ok' => false, 'message' => 'The logo could not be uploaded — please try again.'];
        }
        if (($file['size'] ?? 0) > self::MAX_BYTES) {
            return ['ok' => false, 'message' => 'That logo is larger than 200 KB. Please upload a smaller file.'];
        }
        $data = (string) file_get_contents($file['tmp_name']);
        if ($data === '') {
            return ['ok' => false, 'message' => 'That file appears to be empty.'];
        }
        // Detect the real type (SVG has no finfo image type, so sniff it).
        $mime = '';
        if (str_contains($data, '<svg') && str_contains($data, '</svg')) {
            $mime = 'image/svg+xml';
        } elseif (function_exists('finfo_open')) {
            $fi = finfo_open(FILEINFO_MIME_TYPE);
            $mime = (string) finfo_file($fi, $file['tmp_name']);
            finfo_close($fi);
        }
        if (!isset(self::TYPES[$mime])) {
            return ['ok' => false, 'message' => 'Please upload an SVG, PNG, JPG, WEBP or GIF logo.'];
        }
        return ['ok' => true, 'dataUri' => 'data:' . self::TYPES[$mime] . ';base64,' . base64_encode($data)];
    }
}
