<?php

declare(strict_types=1);

namespace App\Http\Controllers\Settings;

use App\Http\Controllers\Controller;
use App\Http\Requests\Collections\CollectionBulkActionsRequest;
use App\Http\Requests\Collections\CollectionOwnerSearchRequest;
use App\Http\Requests\Collections\CollectionTargetActionRequest;
use App\Http\Requests\Collections\UpdateCollectionWorkflowRequest;
use App\Models\Collection;
use App\Models\CollectionHistory;
use App\Services\CollectionAiOperationsService;
use App\Services\CollectionAnalyticsService;
use App\Services\CollectionBackgroundJobService;
use App\Services\CollectionBulkActionService;
use App\Services\CollectionCanonicalService;
use App\Services\CollectionDashboardService;
use App\Services\CollectionHistoryService;
use App\Services\CollectionHealthService;
use App\Services\CollectionMergeService;
use App\Services\CollectionSearchService;
use App\Services\CollectionService;
use App\Services\CollectionWorkflowService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class CollectionInsightsController extends Controller
{
    public function __construct(
        private readonly CollectionDashboardService $dashboard,
        private readonly CollectionAnalyticsService $analytics,
        private readonly CollectionHistoryService $history,
        private readonly CollectionAiOperationsService $aiOperations,
        private readonly CollectionBackgroundJobService $backgroundJobs,
        private readonly CollectionBulkActionService $bulkActions,
        private readonly CollectionService $collections,
        private readonly CollectionSearchService $search,
        private readonly CollectionHealthService $health,
        private readonly CollectionWorkflowService $workflow,
        private readonly CollectionCanonicalService $canonical,
        private readonly CollectionMergeService $merge,
    ) {
    }

    public function dashboard(Request $request): Response
    {
        $payload = $this->dashboard->build($request->user());

        return Inertia::render('Collection/CollectionDashboard', [
            'summary' => $payload['summary'],
            'topPerforming' => $this->collections->mapCollectionCardPayloads($payload['top_performing'], true),
            'needsAttention' => $this->collections->mapCollectionCardPayloads($payload['needs_attention'], true),
            'expiringCampaigns' => $this->collections->mapCollectionCardPayloads($payload['expiring_campaigns'], true),
            'healthWarnings' => $payload['health_warnings'],
            'filterOptions' => [
                'types' => [
                    Collection::TYPE_PERSONAL,
                    Collection::TYPE_COMMUNITY,
                    Collection::TYPE_EDITORIAL,
                ],
                'visibilities' => [
                    Collection::VISIBILITY_PUBLIC,
                    Collection::VISIBILITY_UNLISTED,
                    Collection::VISIBILITY_PRIVATE,
                ],
                'lifecycleStates' => [
                    Collection::LIFECYCLE_DRAFT,
                    Collection::LIFECYCLE_SCHEDULED,
                    Collection::LIFECYCLE_PUBLISHED,
                    Collection::LIFECYCLE_FEATURED,
                    Collection::LIFECYCLE_ARCHIVED,
                    Collection::LIFECYCLE_HIDDEN,
                    Collection::LIFECYCLE_RESTRICTED,
                    Collection::LIFECYCLE_UNDER_REVIEW,
                    Collection::LIFECYCLE_EXPIRED,
                ],
                'workflowStates' => [
                    Collection::WORKFLOW_DRAFT,
                    Collection::WORKFLOW_IN_REVIEW,
                    Collection::WORKFLOW_APPROVED,
                    Collection::WORKFLOW_PROGRAMMED,
                    Collection::WORKFLOW_ARCHIVED,
                ],
                'healthStates' => [
                    Collection::HEALTH_HEALTHY,
                    Collection::HEALTH_NEEDS_METADATA,
                    Collection::HEALTH_STALE,
                    Collection::HEALTH_LOW_CONTENT,
                    Collection::HEALTH_BROKEN_ITEMS,
                    Collection::HEALTH_WEAK_COVER,
                    Collection::HEALTH_LOW_ENGAGEMENT,
                    Collection::HEALTH_ATTRIBUTION_INCOMPLETE,
                    Collection::HEALTH_NEEDS_REVIEW,
                    Collection::HEALTH_DUPLICATE_RISK,
                    Collection::HEALTH_MERGE_CANDIDATE,
                ],
            ],
            'endpoints' => [
                'managePattern' => route('settings.collections.show', ['collection' => '__COLLECTION__']),
                'analyticsPattern' => route('settings.collections.analytics', ['collection' => '__COLLECTION__']),
                'historyPattern' => route('settings.collections.history', ['collection' => '__COLLECTION__']),
                'healthPattern' => route('settings.collections.health', ['collection' => '__COLLECTION__']),
                'search' => route('settings.collections.search'),
                'bulkActions' => route('settings.collections.bulk-actions'),
            ],
            'seo' => [
                'title' => 'Collections Dashboard — Skinbase',
                'description' => 'Overview of collection lifecycle, quality, activity, and upcoming collection campaigns.',
                'canonical' => route('settings.collections.dashboard'),
                'robots' => 'index,follow',
            ],
        ])->rootView('collections');
    }

    public function analytics(Request $request, Collection $collection): Response
    {
        $this->authorize('update', $collection);
        $collection->loadMissing(['user.profile', 'coverArtwork']);

        return Inertia::render('Collection/CollectionAnalytics', [
            'collection' => $this->collections->mapCollectionDetailPayload($collection, true),
            'analytics' => $this->analytics->overview($collection, (int) $request->integer('days', 30)),
            'historyUrl' => route('settings.collections.history', ['collection' => $collection->id]),
            'dashboardUrl' => route('settings.collections.dashboard'),
            'seo' => [
                'title' => sprintf('%s Analytics — Skinbase', $collection->title),
                'description' => sprintf('Analytics and performance history for the %s collection.', $collection->title),
                'canonical' => route('settings.collections.analytics', ['collection' => $collection->id]),
                'robots' => 'index,follow',
            ],
        ])->rootView('collections');
    }

    public function history(Request $request, Collection $collection): Response
    {
        $this->authorize('update', $collection);
        $collection->loadMissing(['user.profile', 'coverArtwork']);

        $history = $this->history->historyFor($collection, (int) $request->integer('per_page', 40));

        return Inertia::render('Collection/CollectionHistory', [
            'collection' => $this->collections->mapCollectionDetailPayload($collection, true),
            'history' => $this->history->mapPaginator($history),
            'canRestoreHistory' => $this->isStaff($request),
            'dashboardUrl' => route('settings.collections.dashboard'),
            'analyticsUrl' => route('settings.collections.analytics', ['collection' => $collection->id]),
            'restorePattern' => route('settings.collections.history.restore', ['collection' => $collection->id, 'history' => '__HISTORY__']),
            'seo' => [
                'title' => sprintf('%s History — Skinbase', $collection->title),
                'description' => sprintf('Audit history and lifecycle changes for the %s collection.', $collection->title),
                'canonical' => route('settings.collections.history', ['collection' => $collection->id]),
                'robots' => 'index,follow',
            ],
        ])->rootView('collections');
    }

    public function restoreHistory(Request $request, Collection $collection, CollectionHistory $history): JsonResponse
    {
        $this->authorize('update', $collection);

        abort_unless($this->isStaff($request), 403);

        $collection = $this->history->restore($collection->loadMissing('user'), $history, $request->user());

        return response()->json([
            'ok' => true,
            'collection' => $this->collections->mapCollectionDetailPayload($collection->loadMissing('user'), true),
            'health' => $this->health->summary($collection),
            'restored_history_entry_id' => (int) $history->id,
        ]);
    }

    public function qualityReview(Request $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        return response()->json([
            'ok' => true,
            'review' => $this->aiOperations->qualityReview($collection->loadMissing(['user.profile', 'coverArtwork'])),
        ]);
    }

    public function search(CollectionOwnerSearchRequest $request): JsonResponse
    {
        $filters = $request->validated();

        $results = $this->search->ownerSearch($request->user(), $filters, (int) config('collections.v5.search.owner_per_page', 20));

        return response()->json([
            'ok' => true,
            'collections' => $this->collections->mapCollectionCardPayloads($results->items(), true),
            'filters' => $filters,
            'meta' => [
                'current_page' => $results->currentPage(),
                'last_page' => $results->lastPage(),
                'per_page' => $results->perPage(),
                'total' => $results->total(),
            ],
        ]);
    }

    public function bulkActions(CollectionBulkActionsRequest $request): JsonResponse
    {
        $payload = $request->validated();

        $result = $this->bulkActions->apply($request->user(), $payload);
        $dashboard = $this->dashboard->build($request->user());

        return response()->json([
            'ok' => true,
            'action' => $result['action'],
            'count' => $result['count'],
            'message' => $result['message'],
            'collections' => $this->collections->mapCollectionCardPayloads($result['collections'], true),
            'items' => $result['items'],
            'summary' => $dashboard['summary'],
            'healthWarnings' => $dashboard['health_warnings'],
        ]);
    }

    public function health(Request $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        $collection->loadMissing(['user.profile', 'coverArtwork']);

        return response()->json([
            'ok' => true,
            'collection' => $this->collections->mapCollectionDetailPayload($collection, true),
            'health' => $this->health->summary($collection),
            'duplicate_candidates' => $this->collections->mapCollectionCardPayloads($this->merge->duplicateCandidates($collection), true),
            'history_url' => route('settings.collections.history', ['collection' => $collection->id]),
        ]);
    }

    public function workflowUpdate(UpdateCollectionWorkflowRequest $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        $payload = $request->validated();

        if (! $this->isStaff($request)) {
            unset($payload['program_key'], $payload['partner_key'], $payload['experiment_key'], $payload['placement_eligibility']);
        }

        $collection = $this->workflow->update($collection->loadMissing('user'), $payload, $request->user());

        return response()->json([
            'ok' => true,
            'collection' => $this->collections->mapCollectionDetailPayload($collection->loadMissing('user'), true),
            'health' => $this->health->summary($collection),
        ]);
    }

    public function qualityRefresh(Request $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        return response()->json([
            'ok' => true,
            'queued' => true,
            'result' => $this->backgroundJobs->dispatchQualityRefresh($collection->loadMissing('user'), $request->user()),
            'collection' => $this->collections->mapCollectionDetailPayload($collection->loadMissing('user'), true),
            'health' => $this->health->summary($collection),
        ]);
    }

    public function canonicalize(CollectionTargetActionRequest $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        $payload = $request->validated();

        $target = Collection::query()->findOrFail((int) $payload['target_collection_id']);
        $this->authorize('update', $target);

        $collection = $this->canonical->designate($collection->loadMissing('user'), $target->loadMissing('user'), $request->user());

        return response()->json([
            'ok' => true,
            'collection' => $this->collections->mapCollectionDetailPayload($collection->loadMissing('user'), true),
            'target' => $this->collections->mapCollectionCardPayloads([$target->fresh()->loadMissing('user')], true)[0],
            'canonical_target' => $this->collections->mapCollectionCardPayloads([$target->fresh()->loadMissing('user')], true)[0],
            'duplicate_candidates' => $this->merge->reviewCandidates($collection->fresh()->loadMissing('user'), true),
        ]);
    }

    public function merge(CollectionTargetActionRequest $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        $payload = $request->validated();

        $target = Collection::query()->findOrFail((int) $payload['target_collection_id']);
        $this->authorize('update', $target);

        $result = $this->merge->mergeInto($collection->loadMissing('user'), $target->loadMissing('user'), $request->user());

        return response()->json([
            'ok' => true,
            'source' => $this->collections->mapCollectionDetailPayload($result['source']->loadMissing('user'), true),
            'target' => $this->collections->mapCollectionDetailPayload($result['target']->loadMissing('user'), true),
            'attached_artwork_ids' => $result['attached_artwork_ids'],
            'canonical_target' => $this->collections->mapCollectionCardPayloads([$result['target']->loadMissing('user')], true)[0],
            'duplicate_candidates' => $this->merge->reviewCandidates($result['source']->fresh()->loadMissing('user'), true),
        ]);
    }

    public function rejectDuplicate(CollectionTargetActionRequest $request, Collection $collection): JsonResponse
    {
        $this->authorize('update', $collection);

        $payload = $request->validated();

        $target = Collection::query()->findOrFail((int) $payload['target_collection_id']);
        $this->authorize('update', $target);

        $collection = $this->merge->rejectCandidate($collection->loadMissing('user'), $target->loadMissing('user'), $request->user());

        return response()->json([
            'ok' => true,
            'collection' => $this->collections->mapCollectionDetailPayload($collection->loadMissing('user'), true),
            'duplicate_candidates' => $this->merge->reviewCandidates($collection->fresh()->loadMissing('user'), true),
            'canonical_target' => $collection->canonical_collection_id
                ? $this->collections->mapCollectionCardPayloads([
                    Collection::query()->findOrFail((int) $collection->canonical_collection_id)->loadMissing('user'),
                ], true)[0]
                : null,
        ]);
    }

    private function isStaff(Request $request): bool
    {
        $user = $request->user();

        return $user !== null && ($user->isAdmin() || $user->isModerator());
    }
}
