<?php

declare(strict_types=1);

namespace App\Services\Studio;

use App\Models\User;
use Illuminate\Support\Facades\DB;
use function collect;

final class CreatorStudioGrowthService
{
    public function __construct(
        private readonly CreatorStudioAnalyticsService $analytics,
        private readonly CreatorStudioContentService $content,
        private readonly CreatorStudioPreferenceService $preferences,
    ) {
    }

    public function build(User $user, int $days = 30): array
    {
        $analytics = $this->analytics->overview($user, $days);
        $preferences = $this->preferences->forUser($user);
        $user->loadMissing(['profile', 'statistics']);

        $socialLinksCount = (int) DB::table('user_social_links')->where('user_id', $user->id)->count();
        $publishedInRange = (int) collect($analytics['comparison'])->sum('published_count');
        $challengeEntries = (int) DB::table('nova_cards')
            ->where('user_id', $user->id)
            ->whereNull('deleted_at')
            ->sum('challenge_entries_count');
        $profileScore = $this->profileScore($user, $socialLinksCount);
        $cadenceScore = $this->ratioScore($publishedInRange, 6);
        $engagementScore = $this->ratioScore(
            (int) ($analytics['totals']['appreciation'] ?? 0)
            + (int) ($analytics['totals']['comments'] ?? 0)
            + (int) ($analytics['totals']['shares'] ?? 0)
            + (int) ($analytics['totals']['saves'] ?? 0),
            max(3, (int) ($analytics['totals']['content_count'] ?? 0) * 12)
        );
        $curationScore = $this->ratioScore(count($preferences['featured_modules']), 4);

        return [
            'summary' => [
                'followers' => (int) ($analytics['totals']['followers'] ?? 0),
                'published_in_range' => $publishedInRange,
                'engagement_actions' => (int) ($analytics['totals']['appreciation'] ?? 0)
                    + (int) ($analytics['totals']['comments'] ?? 0)
                    + (int) ($analytics['totals']['shares'] ?? 0)
                    + (int) ($analytics['totals']['saves'] ?? 0),
                'profile_completion' => $profileScore,
                'challenge_entries' => $challengeEntries,
                'featured_modules' => count($preferences['featured_modules']),
            ],
            'module_focus' => $this->moduleFocus($analytics),
            'checkpoints' => [
                $this->checkpoint('profile', 'Profile presentation', $profileScore, 'Profile, cover, and social details shape how new visitors read your work.', route('studio.profile'), 'Update profile'),
                $this->checkpoint('cadence', 'Publishing cadence', $cadenceScore, sprintf('You published %d items in the last %d days.', $publishedInRange, $days), route('studio.calendar'), 'Open calendar'),
                $this->checkpoint('engagement', 'Audience response', $engagementScore, 'Comments, reactions, saves, and shares show whether your output is creating momentum.', route('studio.inbox'), 'Open inbox'),
                $this->checkpoint('curation', 'Featured curation', $curationScore, 'Featured modules make your strongest work easier to discover across the profile surface.', route('studio.featured'), 'Manage featured'),
                $this->checkpoint('challenges', 'Challenge participation', $this->ratioScore($challengeEntries, 5), 'Challenge submissions create discoverable surfaces beyond your core publishing flow.', route('studio.challenges'), 'Open challenges'),
            ],
            'opportunities' => $this->opportunities($profileScore, $publishedInRange, $challengeEntries, $preferences),
            'milestones' => [
                $this->milestone('followers', 'Follower milestone', (int) ($analytics['totals']['followers'] ?? 0), $this->nextMilestone((int) ($analytics['totals']['followers'] ?? 0), [10, 25, 50, 100, 250, 500, 1000, 2500, 5000])),
                $this->milestone('publishing', sprintf('Published in %d days', $days), $publishedInRange, $this->nextMilestone($publishedInRange, [3, 5, 8, 12, 20, 30])),
                $this->milestone('challenges', 'Challenge submissions', $challengeEntries, $this->nextMilestone($challengeEntries, [1, 3, 5, 10, 25, 50])),
            ],
            'momentum' => [
                'views_trend' => $analytics['views_trend'],
                'engagement_trend' => $analytics['engagement_trend'],
                'publishing_timeline' => $analytics['publishing_timeline'],
            ],
            'top_content' => collect($analytics['top_content'])->take(5)->values()->all(),
            'range_days' => $days,
        ];
    }

    private function moduleFocus(array $analytics): array
    {
        $totalViews = max(1, (int) ($analytics['totals']['views'] ?? 0));
        $totalEngagement = max(1,
            (int) ($analytics['totals']['appreciation'] ?? 0)
            + (int) ($analytics['totals']['comments'] ?? 0)
            + (int) ($analytics['totals']['shares'] ?? 0)
            + (int) ($analytics['totals']['saves'] ?? 0)
        );
        $comparison = collect($analytics['comparison'] ?? [])->keyBy('key');

        return collect($analytics['module_breakdown'] ?? [])
            ->map(function (array $item) use ($comparison, $totalViews, $totalEngagement): array {
                $engagementValue = (int) ($item['appreciation'] ?? 0)
                    + (int) ($item['comments'] ?? 0)
                    + (int) ($item['shares'] ?? 0)
                    + (int) ($item['saves'] ?? 0);
                $publishedCount = (int) ($comparison->get($item['key'])['published_count'] ?? 0);

                return [
                    'key' => $item['key'],
                    'label' => $item['label'],
                    'icon' => $item['icon'],
                    'views' => (int) ($item['views'] ?? 0),
                    'engagement' => $engagementValue,
                    'published_count' => $publishedCount,
                    'draft_count' => (int) ($item['draft_count'] ?? 0),
                    'view_share' => (int) round(((int) ($item['views'] ?? 0) / $totalViews) * 100),
                    'engagement_share' => (int) round(($engagementValue / $totalEngagement) * 100),
                    'href' => $item['index_url'],
                ];
            })
            ->values()
            ->all();
    }

    private function opportunities(int $profileScore, int $publishedInRange, int $challengeEntries, array $preferences): array
    {
        $items = [];

        if ($profileScore < 80) {
            $items[] = [
                'title' => 'Tighten creator presentation',
                'body' => 'A more complete profile helps new followers understand the work behind the metrics.',
                'href' => route('studio.profile'),
                'cta' => 'Update profile',
            ];
        }

        if ($publishedInRange < 3) {
            $items[] = [
                'title' => 'Increase publishing cadence',
                'body' => 'The calendar is still the clearest place to turn draft backlog into visible output.',
                'href' => route('studio.calendar'),
                'cta' => 'Plan schedule',
            ];
        }

        if (count($preferences['featured_modules'] ?? []) < 3) {
            $items[] = [
                'title' => 'Expand featured module coverage',
                'body' => 'Featured content gives your strongest modules a cleaner discovery path from the public profile.',
                'href' => route('studio.featured'),
                'cta' => 'Manage featured',
            ];
        }

        if ($challengeEntries === 0) {
            $items[] = [
                'title' => 'Use challenges as a growth surface',
                'body' => 'Challenge runs create another discovery path for cards beyond your normal publishing feed.',
                'href' => route('studio.challenges'),
                'cta' => 'Review challenges',
            ];
        }

        $items[] = [
            'title' => 'Stay close to response signals',
            'body' => 'Inbox and comments are still the fastest route from passive reach to actual creator retention.',
            'href' => route('studio.inbox'),
            'cta' => 'Open inbox',
        ];

        return collect($items)->take(4)->values()->all();
    }

    private function checkpoint(string $key, string $label, int $score, string $detail, string $href, string $cta): array
    {
        return [
            'key' => $key,
            'label' => $label,
            'score' => $score,
            'status' => $score >= 80 ? 'strong' : ($score >= 55 ? 'building' : 'needs_attention'),
            'detail' => $detail,
            'href' => $href,
            'cta' => $cta,
        ];
    }

    private function milestone(string $key, string $label, int $current, int $target): array
    {
        return [
            'key' => $key,
            'label' => $label,
            'current' => $current,
            'target' => $target,
            'progress' => $target > 0 ? min(100, (int) round(($current / $target) * 100)) : 100,
        ];
    }

    private function ratioScore(int $current, int $target): int
    {
        if ($target <= 0) {
            return 100;
        }

        return max(0, min(100, (int) round(($current / $target) * 100)));
    }

    private function nextMilestone(int $current, array $steps): int
    {
        foreach ($steps as $step) {
            if ($current < $step) {
                return $step;
            }
        }

        return max($current, 1);
    }

    private function profileScore(User $user, int $socialLinksCount): int
    {
        $score = 0;

        if (filled($user->name)) {
            $score += 15;
        }

        if (filled($user->profile?->description)) {
            $score += 20;
        }

        if (filled($user->profile?->about)) {
            $score += 20;
        }

        if (filled($user->profile?->website)) {
            $score += 15;
        }

        if (filled($user->profile?->avatar_url)) {
            $score += 10;
        }

        if (filled($user->cover_hash) && filled($user->cover_ext)) {
            $score += 10;
        }

        if ($socialLinksCount > 0) {
            $score += 10;
        }

        return min(100, $score);
    }
}