<?php

declare(strict_types=1);

namespace Maestro\Core\Http\Controllers\Superadmin;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
use Maestro\Core\Http\Controllers\Controller;
use Maestro\Core\Models\MaestroAppSetting;
use Maestro\Core\Support\MaestroAppSettingsPresenter;

class MaestroAppSettingsController extends Controller
{
    /**
     * @var list<string>
     */
    private const BRANDING_SLOTS = ['sidebar', 'header', 'compact', 'favicon', 'loginHero'];

    /**
     * @var array<string, string>
     */
    private const COLUMN_BY_SLOT = [
        'sidebar' => 'logo_sidebar_path',
        'header' => 'logo_header_path',
        'compact' => 'logo_compact_path',
        'favicon' => 'favicon_path',
        'loginHero' => 'login_hero_path',
    ];

    public function update(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'theme' => ['sometimes', 'array'],
            'publicPage' => ['sometimes', 'array'],
            'publicPage.enabled' => ['sometimes', 'boolean'],
            'publicPage.mode' => ['sometimes', 'string', Rule::in(['core_default', 'customer_override'])],
            'publicPage.rootMode' => ['sometimes', 'string', Rule::in(['dashboard', 'login', 'public'])],
        ]);

        if (! array_key_exists('theme', $validated) && ! array_key_exists('publicPage', $validated)) {
            abort(422, 'At least one of `theme` or `publicPage` must be provided.');
        }

        $row = MaestroAppSetting::instance();

        if (array_key_exists('theme', $validated)) {
            $incoming = self::normalizeThemePayload($validated['theme']);
            $row->theme = array_replace($row->theme ?? [], $incoming);
        }

        if (array_key_exists('publicPage', $validated)) {
            $incoming = self::normalizePublicPagePayload($validated['publicPage']);
            $current = is_array($row->public_page) ? $row->public_page : [];
            $row->public_page = array_replace($current, $incoming);
        }

        $row->save();

        return response()->json(MaestroAppSettingsPresenter::toArray($row));
    }

    /**
     * @param  array<string, mixed>  $theme
     * @return array<string, mixed>
     */
    private static function normalizeThemePayload(array $theme): array
    {
        $out = [];

        foreach (['preset', 'primary', 'menuMode', 'menuTheme', 'cardStyle'] as $key) {
            if (! array_key_exists($key, $theme)) {
                continue;
            }
            $out[$key] = (string) $theme[$key];
        }

        if (array_key_exists('surface', $theme)) {
            $surface = $theme['surface'];
            $out['surface'] = ($surface === null || $surface === '') ? null : (string) $surface;
        }

        if (array_key_exists('darkTheme', $theme)) {
            $dark = $theme['darkTheme'];
            $parsed = filter_var($dark, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
            $out['darkTheme'] = $parsed ?? (bool) $dark;
        }

        return $out;
    }

    /**
     * @param  array<string, mixed>  $publicPage
     * @return array<string, mixed>
     */
    private static function normalizePublicPagePayload(array $publicPage): array
    {
        $out = [];

        if (array_key_exists('enabled', $publicPage)) {
            $enabled = $publicPage['enabled'];
            $parsed = filter_var($enabled, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
            $out['enabled'] = $parsed ?? (bool) $enabled;
        }

        if (array_key_exists('mode', $publicPage)) {
            $out['mode'] = (string) $publicPage['mode'];
        }

        if (array_key_exists('rootMode', $publicPage)) {
            $out['root_mode'] = (string) $publicPage['rootMode'];
        }

        return $out;
    }

    public function uploadBranding(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'slot' => ['required', 'string', Rule::in(self::BRANDING_SLOTS)],
            'file' => ['required', 'file', 'max:4096', 'mimes:png,jpg,jpeg,webp,gif,svg,ico'],
        ]);

        $column = self::COLUMN_BY_SLOT[$validated['slot']];
        $row = MaestroAppSetting::instance();

        $disk = Storage::disk('public');
        $path = $request->file('file')->store('branding', 'public');

        if ($row->{$column}) {
            $disk->delete($row->{$column});
        }

        $row->{$column} = $path;
        $row->save();

        return response()->json(MaestroAppSettingsPresenter::toArray($row));
    }

    public function clearBranding(string $slot): JsonResponse
    {
        abort_unless(in_array($slot, self::BRANDING_SLOTS, true), 404);

        $column = self::COLUMN_BY_SLOT[$slot];
        $row = MaestroAppSetting::instance();

        if ($row->{$column}) {
            Storage::disk('public')->delete($row->{$column});
            $row->{$column} = null;
            $row->save();
        }

        return response()->json(MaestroAppSettingsPresenter::toArray($row));
    }

    public function uploadOfferDocumentBackground(Request $request): JsonResponse
    {
        $request->validate([
            'file' => ['required', 'file', 'max:8192', 'mimes:jpg,jpeg,png,webp'],
        ]);

        $row = MaestroAppSetting::instance();
        $paths = $row->offer_document_background_paths ?? [];
        if (! is_array($paths)) {
            $paths = [];
        }

        if (count($paths) >= 24) {
            abort(422, 'Maximum number of custom offer backgrounds reached.');
        }

        $disk = Storage::disk('public');
        $stored = $request->file('file')->store('branding/offer-backgrounds', 'public');

        $paths[] = $stored;
        $row->offer_document_background_paths = array_values($paths);
        $row->save();

        return response()->json(MaestroAppSettingsPresenter::toArray($row));
    }

    public function deleteOfferDocumentBackground(int $index): JsonResponse
    {
        $row = MaestroAppSetting::instance();
        $paths = $row->offer_document_background_paths ?? [];
        if (! is_array($paths) || ! array_key_exists($index, $paths)) {
            abort(404);
        }

        $relative = (string) $paths[$index];
        $disk = Storage::disk('public');
        if ($relative !== '' && $disk->exists($relative)) {
            $disk->delete($relative);
        }

        unset($paths[$index]);
        $row->offer_document_background_paths = array_values($paths);
        $row->save();

        return response()->json(MaestroAppSettingsPresenter::toArray($row));
    }
}
