<?php

declare(strict_types=1);

namespace App\Services\Studio;

use App\Models\DashboardPreference;
use App\Models\User;

final class CreatorStudioPreferenceService
{
    /**
     * @return array{
     *   default_content_view: string,
     *   analytics_range_days: int,
     *   dashboard_shortcuts: array<int, string>,
    *   featured_modules: array<int, string>,
    *   featured_content: array<string, int>,
    *   draft_behavior: string,
    *   default_landing_page: string,
    *   widget_visibility: array<string, bool>,
    *   widget_order: array<int, string>,
    *   card_density: string,
    *   scheduling_timezone: string|null,
    *   activity_last_read_at: string|null
     * }
     */
    public function forUser(User $user): array
    {
        $record = DashboardPreference::query()->find($user->id);
        $stored = is_array($record?->studio_preferences) ? $record->studio_preferences : [];

        return [
            'default_content_view' => $this->normalizeView((string) ($stored['default_content_view'] ?? 'grid')),
            'analytics_range_days' => $this->normalizeRange((int) ($stored['analytics_range_days'] ?? 30)),
            'dashboard_shortcuts' => DashboardPreference::pinnedSpacesForUser($user),
            'featured_modules' => $this->normalizeModules($stored['featured_modules'] ?? []),
            'featured_content' => $this->normalizeFeaturedContent($stored['featured_content'] ?? []),
            'draft_behavior' => $this->normalizeDraftBehavior((string) ($stored['draft_behavior'] ?? 'resume-last')),
            'default_landing_page' => $this->normalizeLandingPage((string) ($stored['default_landing_page'] ?? 'overview')),
            'widget_visibility' => $this->normalizeWidgetVisibility($stored['widget_visibility'] ?? []),
            'widget_order' => $this->normalizeWidgetOrder($stored['widget_order'] ?? []),
            'card_density' => $this->normalizeDensity((string) ($stored['card_density'] ?? 'comfortable')),
            'scheduling_timezone' => $this->normalizeTimezone($stored['scheduling_timezone'] ?? null),
            'activity_last_read_at' => $this->normalizeActivityLastReadAt($stored['activity_last_read_at'] ?? null),
        ];
    }

    /**
     * @param array<string, mixed> $attributes
     * @return array{
     *   default_content_view: string,
     *   analytics_range_days: int,
     *   dashboard_shortcuts: array<int, string>,
    *   featured_modules: array<int, string>,
    *   featured_content: array<string, int>,
    *   draft_behavior: string,
    *   default_landing_page: string,
    *   widget_visibility: array<string, bool>,
    *   widget_order: array<int, string>,
    *   card_density: string,
    *   scheduling_timezone: string|null,
    *   activity_last_read_at: string|null
     * }
     */
    public function update(User $user, array $attributes): array
    {
        $current = $this->forUser($user);
        $payload = [
            'default_content_view' => array_key_exists('default_content_view', $attributes)
                ? $this->normalizeView((string) $attributes['default_content_view'])
                : $current['default_content_view'],
            'analytics_range_days' => array_key_exists('analytics_range_days', $attributes)
                ? $this->normalizeRange((int) $attributes['analytics_range_days'])
                : $current['analytics_range_days'],
            'featured_modules' => array_key_exists('featured_modules', $attributes)
                ? $this->normalizeModules($attributes['featured_modules'])
                : $current['featured_modules'],
            'featured_content' => array_key_exists('featured_content', $attributes)
                ? $this->normalizeFeaturedContent($attributes['featured_content'])
                : $current['featured_content'],
            'draft_behavior' => array_key_exists('draft_behavior', $attributes)
                ? $this->normalizeDraftBehavior((string) $attributes['draft_behavior'])
                : $current['draft_behavior'],
            'default_landing_page' => array_key_exists('default_landing_page', $attributes)
                ? $this->normalizeLandingPage((string) $attributes['default_landing_page'])
                : $current['default_landing_page'],
            'widget_visibility' => array_key_exists('widget_visibility', $attributes)
                ? $this->normalizeWidgetVisibility($attributes['widget_visibility'])
                : $current['widget_visibility'],
            'widget_order' => array_key_exists('widget_order', $attributes)
                ? $this->normalizeWidgetOrder($attributes['widget_order'])
                : $current['widget_order'],
            'card_density' => array_key_exists('card_density', $attributes)
                ? $this->normalizeDensity((string) $attributes['card_density'])
                : $current['card_density'],
            'scheduling_timezone' => array_key_exists('scheduling_timezone', $attributes)
                ? $this->normalizeTimezone($attributes['scheduling_timezone'])
                : $current['scheduling_timezone'],
            'activity_last_read_at' => array_key_exists('activity_last_read_at', $attributes)
                ? $this->normalizeActivityLastReadAt($attributes['activity_last_read_at'])
                : $current['activity_last_read_at'],
        ];

        $record = DashboardPreference::query()->firstOrNew(['user_id' => $user->id]);
        $record->pinned_spaces = array_key_exists('dashboard_shortcuts', $attributes)
            ? DashboardPreference::sanitizePinnedSpaces(is_array($attributes['dashboard_shortcuts']) ? $attributes['dashboard_shortcuts'] : [])
            : $current['dashboard_shortcuts'];
        $record->studio_preferences = $payload;
        $record->save();

        return $this->forUser($user);
    }

    private function normalizeView(string $view): string
    {
        return in_array($view, ['grid', 'list'], true) ? $view : 'grid';
    }

    private function normalizeRange(int $days): int
    {
        return in_array($days, [7, 14, 30, 60, 90], true) ? $days : 30;
    }

    /**
     * @param mixed $modules
     * @return array<int, string>
     */
    private function normalizeModules(mixed $modules): array
    {
        $allowed = ['artworks', 'cards', 'collections', 'stories'];

        return collect(is_array($modules) ? $modules : [])
            ->map(fn ($module): string => (string) $module)
            ->filter(fn (string $module): bool => in_array($module, $allowed, true))
            ->unique()
            ->values()
            ->all();
    }

    /**
     * @param mixed $featuredContent
     * @return array<string, int>
     */
    private function normalizeFeaturedContent(mixed $featuredContent): array
    {
        $allowed = ['artworks', 'cards', 'collections', 'stories'];

        return collect(is_array($featuredContent) ? $featuredContent : [])
            ->mapWithKeys(function ($id, $module) use ($allowed): array {
                $moduleKey = (string) $module;
                $normalizedId = (int) $id;

                if (! in_array($moduleKey, $allowed, true) || $normalizedId < 1) {
                    return [];
                }

                return [$moduleKey => $normalizedId];
            })
            ->all();
    }

    private function normalizeDraftBehavior(string $value): string
    {
        return in_array($value, ['resume-last', 'open-drafts', 'focus-published'], true)
            ? $value
            : 'resume-last';
    }

    private function normalizeLandingPage(string $value): string
    {
        return in_array($value, ['overview', 'content', 'drafts', 'scheduled', 'analytics', 'activity', 'calendar', 'inbox', 'search', 'growth', 'challenges', 'preferences'], true)
            ? $value
            : 'overview';
    }

    private function normalizeDensity(string $value): string
    {
        return in_array($value, ['compact', 'comfortable'], true)
            ? $value
            : 'comfortable';
    }

    private function normalizeTimezone(mixed $value): ?string
    {
        if (! is_string($value)) {
            return null;
        }

        $value = trim($value);

        return $value !== '' ? $value : null;
    }

    private function normalizeActivityLastReadAt(mixed $value): ?string
    {
        if (! is_string($value)) {
            return null;
        }

        $value = trim($value);

        return $value !== '' ? $value : null;
    }

    /**
     * @param mixed $value
     * @return array<string, bool>
     */
    private function normalizeWidgetVisibility(mixed $value): array
    {
        $defaults = collect($this->allowedWidgets())->mapWithKeys(fn (string $widget): array => [$widget => true]);

        return $defaults->merge(
            collect(is_array($value) ? $value : [])
                ->filter(fn ($enabled, $widget): bool => in_array((string) $widget, $this->allowedWidgets(), true))
                ->map(fn ($enabled): bool => (bool) $enabled)
        )->all();
    }

    /**
     * @param mixed $value
     * @return array<int, string>
     */
    private function normalizeWidgetOrder(mixed $value): array
    {
        $requested = collect(is_array($value) ? $value : [])
            ->map(fn ($widget): string => (string) $widget)
            ->filter(fn (string $widget): bool => in_array($widget, $this->allowedWidgets(), true))
            ->unique()
            ->values();

        return $requested
            ->concat(collect($this->allowedWidgets())->reject(fn (string $widget): bool => $requested->contains($widget)))
            ->values()
            ->all();
    }

    /**
     * @return array<int, string>
     */
    private function allowedWidgets(): array
    {
        return [
            'quick_stats',
            'continue_working',
            'scheduled_items',
            'recent_activity',
            'top_performers',
            'draft_reminders',
            'module_summaries',
            'growth_hints',
            'active_challenges',
            'creator_health',
            'featured_status',
            'comments_snapshot',
            'stale_drafts',
        ];
    }
}