<?php

namespace App\Library\CampaignDecision;

class CampaignDecisionEngine
{
    public function __construct(
        private readonly CampaignUnifiedVerdictCombiner $combiner,
        private readonly CampaignDecisionConfidence $confidence,
        private readonly CampaignDecisionGuardrails $guardrails,
        private readonly CampaignDataQualityValidator $quality,
    ) {}

    /**
     * @return array<string, mixed>
     */
    public function evaluate(CampaignPerformanceContext $context): array
    {
        $dataQuality = $this->quality->validate($context, $context->capabilities);
        $channels = $this->channels($context);
        $combined = $this->combiner->combine(
            $context,
            $channels,
            $context->settings,
            $dataQuality,
        );

        $trends = $this->trends($context);
        $confidence = $this->confidence->score($context, $combined, $channels);
        $guarded = $this->guardrails->apply($combined, $context->settings);

        return [
            'engine_version' => (string) config('campaign-decisions.engine_version', 'v2'),
            'platform' => $context->platform,
            'account_id' => $context->accountId,
            'campaign_id' => $context->externalCampaignId,
            'campaign_name' => $context->name,
            'trigger' => $context->trigger,
            'evaluated_at' => now()->toDateTimeString(),
            'verdict' => $combined['verdict']->value,
            'confidence' => $confidence,
            'recommended_action' => $guarded['recommended_action'],
            'recommended_budget_change_percent' => $guarded['recommended_budget_change_percent'],
            'reason' => $combined['reason'],
            'reasons' => $combined['reasons'],
            'capabilities' => $context->capabilities,
            'channels' => $channels,
            'windows' => $context->windows,
            'trend' => $trends,
            'data_quality' => $dataQuality,
            'guardrail' => $guarded['guardrail'],
            'action_allowed' => $guarded['action_allowed'],
        ];
    }

    /**
     * @return array<string, mixed>
     */
    private function channels(CampaignPerformanceContext $context): array
    {
        $hour = $context->windows['7h'] ?? $context->windows['5h'] ?? $context->windows['3h'] ?? [];
        $day = $context->windows['7d'] ?? $context->windows['3d'] ?? $context->windows['1d'] ?? [];

        $outcomeKey = 'outcome_'.(int) config('campaign-decisions.monitor.primary_outcome_window_days', 7).'d';
        $outcomeWindow = $context->windows[$outcomeKey] ?? null;

        $outcome = [
            'available' => ($context->affiliate['matched'] ?? false) === true && is_array($outcomeWindow),
        ];

        if ($outcome['available']) {
            $outcome = array_merge($outcome, [
                'spend' => (float) ($outcomeWindow['platform_spend'] ?? 0),
                'platform_spend' => (float) ($outcomeWindow['platform_spend'] ?? 0),
                'orders' => (float) ($outcomeWindow['orders'] ?? 0),
                'revenue' => (float) ($outcomeWindow['revenue'] ?? 0),
                'roas' => $outcomeWindow['roas'] ?? null,
                'cpa' => $outcomeWindow['cpa'] ?? null,
                'conversions' => (float) ($outcomeWindow['conversions'] ?? 0),
                'subscriptions' => (float) ($outcomeWindow['subscriptions'] ?? 0),
                'installs' => (float) ($outcomeWindow['installs'] ?? 0),
                'bookings' => (float) ($outcomeWindow['bookings'] ?? 0),
                'leads' => (float) ($outcomeWindow['leads'] ?? 0),
                'arb_orders' => (float) ($outcomeWindow['arb_orders'] ?? 0),
                'revenue_source' => $outcomeWindow['revenue_source'] ?? ($context->affiliate['revenue_source'] ?? null),
                'from' => $outcomeWindow['from'] ?? null,
                'to' => $outcomeWindow['to'] ?? null,
            ]);
        }

        return [
            'hour' => $hour,
            'day' => $day,
            'outcome' => $outcome,
        ];
    }

    /**
     * @return array<string, mixed>
     */
    private function trends(CampaignPerformanceContext $context): array
    {
        $current = $context->windows['7d']['roas'] ?? null;
        $previousSpend = (float) ($context->windows['14d']['spend'] ?? 0) - (float) ($context->windows['7d']['spend'] ?? 0);
        $currentSpend = (float) ($context->windows['7d']['spend'] ?? 0);
        $spendChange = CampaignMetricsCalculator::percentChange($currentSpend, $previousSpend > 0 ? $previousSpend : null);

        return [
            'roas_7d' => $current,
            'spend_change_percent' => $spendChange,
            'status' => CampaignMetricsCalculator::trendStatus($spendChange),
        ];
    }
}
