<?php

declare(strict_types=1);

namespace App\Services\Studio\Providers;

use App\Models\Story;
use App\Models\User;
use App\Services\Studio\Contracts\CreatorStudioProvider;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

final class StoryStudioProvider implements CreatorStudioProvider
{
    public function key(): string
    {
        return 'stories';
    }

    public function label(): string
    {
        return 'Stories';
    }

    public function icon(): string
    {
        return 'fa-solid fa-feather-pointed';
    }

    public function createUrl(): string
    {
        return route('creator.stories.create');
    }

    public function indexUrl(): string
    {
        return route('studio.stories');
    }

    public function summary(User $user): array
    {
        $baseQuery = Story::query()->where('creator_id', $user->id);

        $count = (clone $baseQuery)
            ->whereNotIn('status', ['archived'])
            ->count();

        $draftCount = (clone $baseQuery)
            ->whereIn('status', ['draft', 'pending_review', 'rejected'])
            ->count();

        $publishedCount = (clone $baseQuery)
            ->whereIn('status', ['published', 'scheduled'])
            ->count();

        $recentPublishedCount = (clone $baseQuery)
            ->whereIn('status', ['published', 'scheduled'])
            ->where('published_at', '>=', now()->subDays(30))
            ->count();

        $archivedCount = (clone $baseQuery)
            ->where('status', 'archived')
            ->count();

        return [
            'key' => $this->key(),
            'label' => $this->label(),
            'icon' => $this->icon(),
            'count' => $count,
            'draft_count' => $draftCount,
            'published_count' => $publishedCount,
            'archived_count' => $archivedCount,
            'trend_value' => $recentPublishedCount,
            'trend_label' => 'published in 30d',
            'quick_action_label' => 'Create story',
            'index_url' => $this->indexUrl(),
            'create_url' => $this->createUrl(),
        ];
    }

    public function items(User $user, string $bucket = 'all', int $limit = 200): Collection
    {
        $query = Story::query()
            ->where('creator_id', $user->id)
            ->with(['tags'])
            ->orderByDesc('updated_at');

        if ($limit > 0) {
            $query->limit($limit);
        }

        if ($bucket === 'drafts') {
            $query->whereIn('status', ['draft', 'pending_review', 'rejected']);
        } elseif ($bucket === 'scheduled') {
            $query->where('status', 'scheduled');
        } elseif ($bucket === 'archived') {
            $query->where('status', 'archived');
        } elseif ($bucket === 'published') {
            $query->whereIn('status', ['published', 'scheduled']);
        } else {
            $query->where('status', '!=', 'archived');
        }

        return $query->get()->map(fn (Story $story): array => $this->mapItem($story));
    }

    public function topItems(User $user, int $limit = 5): Collection
    {
        return Story::query()
            ->where('creator_id', $user->id)
            ->whereIn('status', ['published', 'scheduled'])
            ->orderByDesc('views')
            ->orderByDesc('likes_count')
            ->limit($limit)
            ->get()
            ->map(fn (Story $story): array => $this->mapItem($story));
    }

    public function analytics(User $user): array
    {
        $totals = Story::query()
            ->where('creator_id', $user->id)
            ->where('status', '!=', 'archived')
            ->selectRaw('COALESCE(SUM(views), 0) as views')
            ->selectRaw('COALESCE(SUM(likes_count), 0) as appreciation')
            ->selectRaw('0 as shares')
            ->selectRaw('COALESCE(SUM(comments_count), 0) as comments')
            ->selectRaw('0 as saves')
            ->first();

        return [
            'views' => (int) ($totals->views ?? 0),
            'appreciation' => (int) ($totals->appreciation ?? 0),
            'shares' => 0,
            'comments' => (int) ($totals->comments ?? 0),
            'saves' => 0,
        ];
    }

    public function scheduledItems(User $user, int $limit = 50): Collection
    {
        return $this->items($user, 'scheduled', $limit);
    }

    private function mapItem(Story $story): array
    {
        $subtitle = $story->story_type ? ucfirst(str_replace('_', ' ', (string) $story->story_type)) : null;
        $viewUrl = in_array($story->status, ['published', 'scheduled'], true)
            ? route('stories.show', ['slug' => $story->slug])
            : route('creator.stories.preview', ['story' => $story->id]);

        return [
            'id' => sprintf('%s:%d', $this->key(), (int) $story->id),
            'numeric_id' => (int) $story->id,
            'module' => $this->key(),
            'module_label' => $this->label(),
            'module_icon' => $this->icon(),
            'title' => $story->title,
            'subtitle' => $subtitle,
            'description' => $story->excerpt,
            'status' => $story->status,
            'visibility' => $story->status === 'published' ? 'public' : 'private',
            'image_url' => $story->cover_url,
            'preview_url' => route('creator.stories.preview', ['story' => $story->id]),
            'view_url' => $viewUrl,
            'edit_url' => route('creator.stories.edit', ['story' => $story->id]),
            'manage_url' => route('creator.stories.edit', ['story' => $story->id]),
            'analytics_url' => route('creator.stories.analytics', ['story' => $story->id]),
            'create_url' => $this->createUrl(),
            'actions' => $this->actionsFor($story, $story->status),
            'created_at' => $story->created_at?->toIso8601String(),
            'updated_at' => $story->updated_at?->toIso8601String(),
            'published_at' => $story->published_at?->toIso8601String(),
            'scheduled_at' => $story->scheduled_for?->toIso8601String(),
            'featured' => (bool) $story->featured,
            'activity_state' => in_array($story->status, ['published', 'scheduled'], true)
                ? 'active'
                : ($story->status === 'archived' ? 'archived' : 'inactive'),
            'metrics' => [
                'views' => (int) $story->views,
                'appreciation' => (int) $story->likes_count,
                'shares' => 0,
                'comments' => (int) $story->comments_count,
                'saves' => 0,
            ],
            'engagement_score' => (int) $story->views
                + ((int) $story->likes_count * 2)
                + ((int) $story->comments_count * 3),
            'taxonomies' => [
                'categories' => [],
                'tags' => $story->tags->map(fn ($entry): array => [
                    'id' => (int) $entry->id,
                    'name' => (string) $entry->name,
                    'slug' => (string) $entry->slug,
                ])->values()->all(),
            ],
        ];
    }

    private function actionsFor(Story $story, string $status): array
    {
        $actions = [];

        if (in_array($status, ['draft', 'pending_review', 'rejected'], true)) {
            $actions[] = $this->requestAction(
                'publish',
                'Publish',
                'fa-solid fa-rocket',
                route('api.stories.update'),
                [
                    'story_id' => (int) $story->id,
                    'status' => 'published',
                ],
                null,
                'put'
            );
        }

        if (in_array($status, ['draft', 'pending_review', 'rejected', 'published', 'scheduled'], true)) {
            $actions[] = $this->requestAction(
                'archive',
                'Archive',
                'fa-solid fa-box-archive',
                route('api.stories.update'),
                [
                    'story_id' => (int) $story->id,
                    'status' => 'archived',
                ],
                null,
                'put'
            );
        }

        if ($status === 'scheduled') {
            $actions[] = $this->requestAction('publish_now', 'Publish now', 'fa-solid fa-bolt', route('api.studio.schedule.publishNow', ['module' => 'stories', 'id' => $story->id]), []);
            $actions[] = $this->requestAction('unschedule', 'Unschedule', 'fa-solid fa-calendar-xmark', route('api.studio.schedule.unschedule', ['module' => 'stories', 'id' => $story->id]), []);
        }

        if ($status === 'archived') {
            $actions[] = $this->requestAction(
                'restore',
                'Restore',
                'fa-solid fa-rotate-left',
                route('api.stories.update'),
                [
                    'story_id' => (int) $story->id,
                    'status' => 'draft',
                ],
                null,
                'put'
            );
        }

        $actions[] = $this->requestAction(
            'delete',
            'Delete',
            'fa-solid fa-trash',
            route('creator.stories.destroy', ['story' => $story->id]),
            [],
            'Delete this story permanently?',
            'delete'
        );

        return $actions;
    }

    private function requestAction(string $key, string $label, string $icon, string $url, array $payload = [], ?string $confirm = null, string $method = 'post'): array
    {
        return [
            'key' => $key,
            'label' => $label,
            'icon' => $icon,
            'type' => 'request',
            'method' => $method,
            'url' => $url,
            'payload' => $payload,
            'confirm' => $confirm,
        ];
    }
}