<?php

namespace App\Services\Moderation;

use App\Enums\ModerationContentType;
use App\Models\Collection;
use App\Models\NovaCard;
use App\Models\Story;
use App\Models\Artwork;
use App\Models\ArtworkComment;
use App\Models\ContentModerationFinding;
use App\Models\UserProfile;
use App\Models\UserSocialLink;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;

class ContentModerationSourceService
{
    public function queryForType(ModerationContentType $type): EloquentBuilder
    {
        return match ($type) {
            ModerationContentType::ArtworkComment => ArtworkComment::query()
                ->with('artwork:id,title,slug,user_id')
                ->whereNull('deleted_at')
                ->where(function (EloquentBuilder $query): void {
                    $query->whereNotNull('raw_content')->where('raw_content', '!=', '')
                        ->orWhere(function (EloquentBuilder $fallback): void {
                            $fallback->whereNotNull('content')->where('content', '!=', '');
                        });
                })
                ->orderBy('id'),
            ModerationContentType::ArtworkDescription => Artwork::query()
                ->whereNotNull('description')
                ->where('description', '!=', '')
                ->orderBy('id'),
            ModerationContentType::ArtworkTitle => Artwork::query()
                ->whereNotNull('title')
                ->where('title', '!=', '')
                ->orderBy('id'),
            ModerationContentType::UserBio => UserProfile::query()
                ->with('user:id,username,name')
                ->where(function (EloquentBuilder $query): void {
                    $query->whereNotNull('about')->where('about', '!=', '')
                        ->orWhere(function (EloquentBuilder $fallback): void {
                            $fallback->whereNotNull('description')->where('description', '!=', '');
                        });
                })
                ->orderBy('user_id'),
            ModerationContentType::UserProfileLink => UserSocialLink::query()
                ->with('user:id,username,name')
                ->whereNotNull('url')
                ->where('url', '!=', '')
                ->orderBy('id'),
            ModerationContentType::CollectionTitle => Collection::query()
                ->with('user:id,username,name')
                ->whereNotNull('title')
                ->where('title', '!=', '')
                ->orderBy('id'),
            ModerationContentType::CollectionDescription => Collection::query()
                ->with('user:id,username,name')
                ->whereNotNull('description')
                ->where('description', '!=', '')
                ->orderBy('id'),
            ModerationContentType::StoryTitle => Story::query()
                ->with('creator:id,username,name')
                ->whereNotNull('title')
                ->where('title', '!=', '')
                ->orderBy('id'),
            ModerationContentType::StoryContent => Story::query()
                ->with('creator:id,username,name')
                ->whereNotNull('content')
                ->where('content', '!=', '')
                ->orderBy('id'),
            ModerationContentType::CardTitle => NovaCard::query()
                ->with('user:id,username,name')
                ->whereNotNull('title')
                ->where('title', '!=', '')
                ->orderBy('id'),
            ModerationContentType::CardText => NovaCard::query()
                ->with('user:id,username,name')
                ->where(function (EloquentBuilder $query): void {
                    $query->whereNotNull('quote_text')->where('quote_text', '!=', '')
                        ->orWhere(function (EloquentBuilder $description): void {
                            $description->whereNotNull('description')->where('description', '!=', '');
                        });
                })
                ->orderBy('id'),
            default => throw new \InvalidArgumentException('Unsupported moderation content type: ' . $type->value),
        };
    }

    /**
     * @param Artwork|ArtworkComment|Collection|Story|NovaCard|UserProfile|UserSocialLink $row
     * @return array<string, mixed>
     */
    public function buildContext(ModerationContentType $type, object $row): array
    {
        return match ($type) {
            ModerationContentType::ArtworkComment => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'artwork_comment',
                'content_target_id' => (int) $row->id,
                'artwork_id' => (int) $row->artwork_id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->raw_content ?: $row->content),
                'is_publicly_exposed' => true,
            ],
            ModerationContentType::ArtworkDescription => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'artwork',
                'content_target_id' => (int) $row->id,
                'artwork_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->description ?? ''),
                'is_publicly_exposed' => (bool) ($row->is_public ?? false),
            ],
            ModerationContentType::ArtworkTitle => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'artwork',
                'content_target_id' => (int) $row->id,
                'artwork_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->title ?? ''),
                'is_publicly_exposed' => (bool) ($row->is_public ?? false),
            ],
            ModerationContentType::UserBio => [
                'content_type' => $type->value,
                'content_id' => (int) $row->user_id,
                'content_target_type' => 'user_profile',
                'content_target_id' => (int) $row->user_id,
                'user_id' => (int) $row->user_id,
                'content_snapshot' => trim((string) ($row->about ?: $row->description ?: '')),
                'is_publicly_exposed' => true,
            ],
            ModerationContentType::UserProfileLink => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'user_social_link',
                'content_target_id' => (int) $row->id,
                'user_id' => (int) $row->user_id,
                'content_snapshot' => trim((string) ($row->url ?? '')),
                'is_publicly_exposed' => true,
            ],
            ModerationContentType::CollectionTitle => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'collection',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->title ?? ''),
                'is_publicly_exposed' => in_array((string) ($row->visibility ?? ''), ['public', 'unlisted'], true),
            ],
            ModerationContentType::CollectionDescription => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'collection',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->description ?? ''),
                'is_publicly_exposed' => in_array((string) ($row->visibility ?? ''), ['public', 'unlisted'], true),
            ],
            ModerationContentType::StoryTitle => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'story',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->creator_id ? (int) $row->creator_id : null,
                'content_snapshot' => (string) ($row->title ?? ''),
                'is_publicly_exposed' => in_array((string) ($row->status ?? ''), ['published', 'scheduled'], true),
            ],
            ModerationContentType::StoryContent => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'story',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->creator_id ? (int) $row->creator_id : null,
                'content_snapshot' => (string) ($row->content ?? ''),
                'is_publicly_exposed' => in_array((string) ($row->status ?? ''), ['published', 'scheduled'], true),
            ],
            ModerationContentType::CardTitle => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'nova_card',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => (string) ($row->title ?? ''),
                'is_publicly_exposed' => in_array((string) ($row->visibility ?? ''), ['public', 'unlisted'], true),
            ],
            ModerationContentType::CardText => [
                'content_type' => $type->value,
                'content_id' => (int) $row->id,
                'content_target_type' => 'nova_card',
                'content_target_id' => (int) $row->id,
                'user_id' => $row->user_id ? (int) $row->user_id : null,
                'content_snapshot' => trim(implode("\n", array_filter([
                    (string) ($row->quote_text ?? ''),
                    (string) ($row->description ?? ''),
                    (string) ($row->quote_author ?? ''),
                    (string) ($row->quote_source ?? ''),
                ]))),
                'is_publicly_exposed' => in_array((string) ($row->visibility ?? ''), ['public', 'unlisted'], true),
            ],
            default => throw new \InvalidArgumentException('Unsupported moderation content type: ' . $type->value),
        };
    }

    /**
     * @return array{context:array<string, mixed>|null, type:ModerationContentType|null}
     */
    public function contextForFinding(ContentModerationFinding $finding): array
    {
        return match ($finding->content_type) {
            ModerationContentType::ArtworkComment => $this->commentContextForFinding($finding),
            ModerationContentType::ArtworkDescription => $this->descriptionContextForFinding($finding),
            ModerationContentType::ArtworkTitle => $this->artworkTitleContextForFinding($finding),
            ModerationContentType::UserBio => $this->userBioContextForFinding($finding),
            ModerationContentType::UserProfileLink => $this->userProfileLinkContextForFinding($finding),
            ModerationContentType::CollectionTitle => $this->collectionTitleContextForFinding($finding),
            ModerationContentType::CollectionDescription => $this->collectionDescriptionContextForFinding($finding),
            ModerationContentType::StoryTitle => $this->storyTitleContextForFinding($finding),
            ModerationContentType::StoryContent => $this->storyContentContextForFinding($finding),
            ModerationContentType::CardTitle => $this->cardTitleContextForFinding($finding),
            ModerationContentType::CardText => $this->cardTextContextForFinding($finding),
            default => ['context' => null, 'type' => null],
        };
    }

    /**
     * @return array{context:array<string, mixed>|null, type:ModerationContentType|null}
     */
    private function commentContextForFinding(ContentModerationFinding $finding): array
    {
        $comment = ArtworkComment::query()->find($finding->content_id);
        if (! $comment) {
            return ['context' => null, 'type' => null];
        }

        return [
            'context' => $this->buildContext(ModerationContentType::ArtworkComment, $comment),
            'type' => ModerationContentType::ArtworkComment,
        ];
    }

    /**
     * @return array{context:array<string, mixed>|null, type:ModerationContentType|null}
     */
    private function descriptionContextForFinding(ContentModerationFinding $finding): array
    {
        $artworkId = (int) ($finding->artwork_id ?? $finding->content_id);
        $artwork = Artwork::query()->find($artworkId);
        if (! $artwork) {
            return ['context' => null, 'type' => null];
        }

        return [
            'context' => $this->buildContext(ModerationContentType::ArtworkDescription, $artwork),
            'type' => ModerationContentType::ArtworkDescription,
        ];
    }

    private function artworkTitleContextForFinding(ContentModerationFinding $finding): array
    {
        $artwork = Artwork::query()->find((int) ($finding->artwork_id ?? $finding->content_id));
        if (! $artwork) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::ArtworkTitle, $artwork), 'type' => ModerationContentType::ArtworkTitle];
    }

    private function userBioContextForFinding(ContentModerationFinding $finding): array
    {
        $profile = UserProfile::query()->find($finding->content_id);
        if (! $profile) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::UserBio, $profile), 'type' => ModerationContentType::UserBio];
    }

    private function userProfileLinkContextForFinding(ContentModerationFinding $finding): array
    {
        $link = UserSocialLink::query()->find($finding->content_id);
        if (! $link) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::UserProfileLink, $link), 'type' => ModerationContentType::UserProfileLink];
    }

    private function collectionTitleContextForFinding(ContentModerationFinding $finding): array
    {
        $collection = Collection::query()->find($finding->content_id);
        if (! $collection) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::CollectionTitle, $collection), 'type' => ModerationContentType::CollectionTitle];
    }

    private function collectionDescriptionContextForFinding(ContentModerationFinding $finding): array
    {
        $collection = Collection::query()->find($finding->content_id);
        if (! $collection) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::CollectionDescription, $collection), 'type' => ModerationContentType::CollectionDescription];
    }

    private function storyTitleContextForFinding(ContentModerationFinding $finding): array
    {
        $story = Story::query()->find($finding->content_id);
        if (! $story) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::StoryTitle, $story), 'type' => ModerationContentType::StoryTitle];
    }

    private function storyContentContextForFinding(ContentModerationFinding $finding): array
    {
        $story = Story::query()->find($finding->content_id);
        if (! $story) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::StoryContent, $story), 'type' => ModerationContentType::StoryContent];
    }

    private function cardTitleContextForFinding(ContentModerationFinding $finding): array
    {
        $card = NovaCard::query()->find($finding->content_id);
        if (! $card) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::CardTitle, $card), 'type' => ModerationContentType::CardTitle];
    }

    private function cardTextContextForFinding(ContentModerationFinding $finding): array
    {
        $card = NovaCard::query()->find($finding->content_id);
        if (! $card) {
            return ['context' => null, 'type' => null];
        }

        return ['context' => $this->buildContext(ModerationContentType::CardText, $card), 'type' => ModerationContentType::CardText];
    }
}