<?php

namespace App\Services\Moderation;

use App\Data\Moderation\ModerationResultData;
use App\Enums\ModerationEscalationStatus;
use App\Enums\ModerationContentType;
use App\Enums\ModerationStatus;
use App\Models\ContentModerationAiSuggestion;
use App\Models\ContentModerationFinding;

class ContentModerationPersistenceService
{
    public function __construct(
        private readonly ContentModerationReviewService $review,
        private readonly ContentModerationActionLogService $actionLogs,
    ) {
    }

    public function shouldQueue(ModerationResultData $result): bool
    {
        return $result->score >= (int) \app('config')->get('content_moderation.queue_threshold', 30);
    }

    public function hasCurrentFinding(string $contentType, int $contentId, string $contentHash, string $scannerVersion): bool
    {
        return ContentModerationFinding::query()
            ->where('content_type', $contentType)
            ->where('content_id', $contentId)
            ->where('content_hash', $contentHash)
            ->where('scanner_version', $scannerVersion)
            ->exists();
    }

    /**
     * @param array<string, mixed> $context
     * @return array{finding:?ContentModerationFinding, created:bool, updated:bool}
     */
    public function persist(ModerationResultData $result, array $context): array
    {
        $contentType = (string) ($context['content_type'] ?? '');
        $contentId = (int) ($context['content_id'] ?? 0);

        if ($contentType === '' || $contentId <= 0) {
            return ['finding' => null, 'created' => false, 'updated' => false];
        }

        $existing = ContentModerationFinding::query()
            ->where('content_type', $contentType)
            ->where('content_id', $contentId)
            ->where('content_hash', $result->contentHash)
            ->where('scanner_version', $result->scannerVersion)
            ->first();

        if (! $this->shouldQueue($result) && $existing === null) {
            return ['finding' => null, 'created' => false, 'updated' => false];
        }

        $finding = $existing ?? new ContentModerationFinding();
        $isNew = ! $finding->exists;

        $finding->fill([
            'content_type' => $contentType,
            'content_id' => $contentId,
            'content_target_type' => $result->contentTargetType,
            'content_target_id' => $result->contentTargetId,
            'artwork_id' => $context['artwork_id'] ?? null,
            'user_id' => $context['user_id'] ?? null,
            'severity' => $result->severity->value,
            'score' => $result->score,
            'content_hash' => $result->contentHash,
            'scanner_version' => $result->scannerVersion,
            'reasons_json' => $result->reasons,
            'matched_links_json' => $result->matchedLinks,
            'matched_domains_json' => $result->matchedDomains,
            'matched_keywords_json' => $result->matchedKeywords,
            'rule_hits_json' => $result->ruleHits,
            'score_breakdown_json' => $result->scoreBreakdown,
            'content_hash_normalized' => $result->contentHashNormalized,
            'group_key' => $result->groupKey,
            'campaign_key' => $result->campaignKey,
            'cluster_score' => $result->clusterScore,
            'cluster_reason' => $result->clusterReason,
            'priority_score' => $result->priorityScore,
            'policy_name' => $result->policyName,
            'review_bucket' => $result->reviewBucket,
            'escalation_status' => $result->escalationStatus ?? ModerationEscalationStatus::None->value,
            'ai_provider' => $result->aiProvider,
            'ai_label' => $result->aiLabel,
            'ai_suggested_action' => $result->aiSuggestedAction,
            'ai_confidence' => $result->aiConfidence,
            'ai_explanation' => $result->aiExplanation,
            'user_risk_score' => $result->userRiskScore,
            'content_snapshot' => (string) ($context['content_snapshot'] ?? ''),
            'auto_action_taken' => $result->autoHideRecommended ? 'recommended' : null,
        ]);

        if ($isNew) {
            $finding->status = $result->status;
        } elseif (! $this->shouldQueue($result) && $finding->isPending()) {
            $finding->status = ModerationStatus::Resolved;
            $finding->action_taken = 'rescanned_clean';
            $finding->resolved_at = \now();
            $finding->resolved_by = null;
        }

        $finding->save();

        if ($result->aiProvider !== null && ($result->aiLabel !== null || $result->aiExplanation !== null || $result->aiConfidence !== null)) {
            ContentModerationAiSuggestion::query()->create([
                'finding_id' => $finding->id,
                'provider' => $result->aiProvider,
                'suggested_label' => $result->aiLabel,
                'suggested_action' => $result->aiSuggestedAction,
                'confidence' => $result->aiConfidence,
                'explanation' => $result->aiExplanation,
                'campaign_tags_json' => $result->campaignKey ? [$result->campaignKey] : [],
                'raw_response_json' => $result->aiRawResponse,
                'created_at' => now(),
            ]);
        }

        if (! $isNew && ! $this->shouldQueue($result) && $finding->action_taken === 'rescanned_clean') {
            $this->actionLogs->log(
                $finding,
                'finding',
                $finding->id,
                'rescan',
                null,
                ModerationStatus::Pending->value,
                ModerationStatus::Resolved->value,
                null,
                null,
                'Finding resolved automatically after a clean rescan.',
                ['scanner_version' => $result->scannerVersion],
            );
        }

        return [
            'finding' => $finding,
            'created' => $isNew,
            'updated' => ! $isNew,
        ];
    }

    /**
     * @param array<string, mixed> $context
     */
    public function applyAutomatedActionIfNeeded(ContentModerationFinding $finding, ModerationResultData $result, array $context): bool
    {
        if (! $result->autoHideRecommended) {
            return false;
        }

        if ($finding->is_auto_hidden) {
            return false;
        }

        $supportedTypes = (array) \app('config')->get('content_moderation.auto_hide.supported_types', []);
        if (! in_array($finding->content_type->value, $supportedTypes, true)) {
            $finding->forceFill([
                'auto_action_taken' => 'recommended_review',
            ])->save();

            return false;
        }

        if (! in_array($finding->content_type, [ModerationContentType::ArtworkComment, ModerationContentType::ArtworkDescription], true)) {
            if ($finding->content_type !== ModerationContentType::ArtworkTitle) {
                return false;
            }
        }

        if (! in_array($finding->content_type, [ModerationContentType::ArtworkComment, ModerationContentType::ArtworkDescription, ModerationContentType::ArtworkTitle], true)) {
            return false;
        }

        $this->review->autoHideContent($finding, 'Triggered by automated moderation threshold.');

        return true;
    }
}