<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Collection;
use App\Models\User;
use App\Services\CollectionHistoryService;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class CollectionPartnerProgramService
{
    public function sync(Collection $collection, array $attributes, ?User $actor = null): Collection
    {
        $adminOnlyKeys = [
            'partner_key',
            'trust_tier',
            'sponsorship_state',
            'ownership_domain',
            'commercial_review_state',
            'legal_review_state',
        ];

        if ($actor && ! $actor->isAdmin() && collect($adminOnlyKeys)->contains(static fn (string $key): bool => array_key_exists($key, $attributes))) {
            throw ValidationException::withMessages([
                'partner_key' => 'Only admins can update partner or trust metadata.',
            ]);
        }

        $payload = [
            'partner_key' => array_key_exists('partner_key', $attributes) ? ($attributes['partner_key'] ?: null) : $collection->partner_key,
            'trust_tier' => array_key_exists('trust_tier', $attributes) ? ($attributes['trust_tier'] ?: null) : $collection->trust_tier,
            'promotion_tier' => array_key_exists('promotion_tier', $attributes) ? ($attributes['promotion_tier'] ?: null) : $collection->promotion_tier,
            'sponsorship_state' => array_key_exists('sponsorship_state', $attributes) ? ($attributes['sponsorship_state'] ?: null) : $collection->sponsorship_state,
            'ownership_domain' => array_key_exists('ownership_domain', $attributes) ? ($attributes['ownership_domain'] ?: null) : $collection->ownership_domain,
            'commercial_review_state' => array_key_exists('commercial_review_state', $attributes) ? ($attributes['commercial_review_state'] ?: null) : $collection->commercial_review_state,
            'legal_review_state' => array_key_exists('legal_review_state', $attributes) ? ($attributes['legal_review_state'] ?: null) : $collection->legal_review_state,
        ];

        $before = [
            'partner_key' => $collection->partner_key,
            'trust_tier' => $collection->trust_tier,
            'promotion_tier' => $collection->promotion_tier,
            'sponsorship_state' => $collection->sponsorship_state,
            'ownership_domain' => $collection->ownership_domain,
            'commercial_review_state' => $collection->commercial_review_state,
            'legal_review_state' => $collection->legal_review_state,
        ];

        $collection->forceFill($payload)->save();
        $fresh = $collection->fresh();

        app(CollectionHistoryService::class)->record(
            $fresh,
            $actor,
            'partner_program_metadata_updated',
            'Collection partner and governance metadata updated.',
            $before,
            $payload,
        );

        return $fresh;
    }

    public function publicLanding(string $programKey, int $limit = 18): array
    {
        $normalizedKey = trim($programKey);

        if ($normalizedKey === '') {
            return [
                'program' => null,
                'collections' => new EloquentCollection(),
                'editorial_collections' => new EloquentCollection(),
                'community_collections' => new EloquentCollection(),
                'recent_collections' => new EloquentCollection(),
            ];
        }

        $baseQuery = Collection::query()
            ->public()
            ->where('program_key', $normalizedKey)
            ->where('placement_eligibility', true)
            ->with(['user:id,username,name', 'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at']);

        $collections = (clone $baseQuery)
            ->orderByDesc('ranking_score')
            ->orderByDesc('health_score')
            ->limit(max(1, min($limit, 24)))
            ->get();

        $leadCollection = $collections->first() ?: (clone $baseQuery)->first();
        $partnerLabels = (clone $baseQuery)->whereNotNull('partner_label')->pluck('partner_label')->filter()->unique()->values()->all();
        $sponsorshipLabels = (clone $baseQuery)->whereNotNull('sponsorship_label')->pluck('sponsorship_label')->filter()->unique()->values()->all();

        return [
            'program' => $leadCollection ? [
                'key' => $normalizedKey,
                'label' => $leadCollection->banner_text ?: $leadCollection->badge_label ?: Str::headline(str_replace(['_', '-'], ' ', $normalizedKey)),
                'description' => $leadCollection->summary
                    ?: $leadCollection->description
                    ?: sprintf('Public collections grouped under the %s program, prepared for discovery, partner, and editorial surfaces.', Str::headline(str_replace(['_', '-'], ' ', $normalizedKey))),
                'promotion_tier' => $leadCollection->promotion_tier,
                'partner_labels' => $partnerLabels,
                'sponsorship_labels' => $sponsorshipLabels,
                'trust_tier' => $leadCollection->trust_tier,
                'collections_count' => (clone $baseQuery)->count(),
            ] : null,
            'collections' => $collections,
            'editorial_collections' => (clone $baseQuery)->where('type', Collection::TYPE_EDITORIAL)->orderByDesc('ranking_score')->limit(6)->get(),
            'community_collections' => (clone $baseQuery)->where('type', Collection::TYPE_COMMUNITY)->orderByDesc('ranking_score')->limit(6)->get(),
            'recent_collections' => (clone $baseQuery)->latest('published_at')->limit(6)->get(),
        ];
    }
}