<?php

declare(strict_types=1);

namespace App\Application\Analytics\ValueObject;

use App\Framework\Exception\ErrorCode;
use App\Framework\Exception\FrameworkException;

/**
 * Business metrics analytics report containing conversion and revenue data
 */
final readonly class BusinessMetricsReport
{
    /**
     * @param array<string, int> $conversions
     * @param array<string, string|int|float> $revenue
     * @param array<string, int> $goalCompletions
     * @param array<string, mixed> $funnelData
     */
    public function __construct(
        public array $conversions,
        public array $revenue,
        public array $goalCompletions,
        public array $funnelData,
    ) {
        // Validate conversions - only check business logic
        foreach ($conversions as $type => $count) {
            if ($count < 0) {
                throw FrameworkException::create(
                    ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                    'Conversion counts cannot be negative'
                )->withData(['type' => $type, 'count' => $count]);
            }
        }

        // Validate goal completions - only check business logic
        foreach ($goalCompletions as $goal => $completions) {
            if ($completions < 0) {
                throw FrameworkException::create(
                    ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                    'Goal completion counts cannot be negative'
                )->withData(['goal' => $goal, 'completions' => $completions]);
            }
        }

        // Validate required revenue fields
        $requiredRevenueFields = ['total', 'currency', 'transactions', 'average_order_value'];
        foreach ($requiredRevenueFields as $field) {
            if (! array_key_exists($field, $revenue)) {
                throw FrameworkException::create(
                    ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
                    "Revenue must contain field: {$field}"
                )->withData(['missing_field' => $field, 'available_fields' => array_keys($revenue)]);
            }
        }
    }

    public function getTotalConversions(): int
    {
        return array_sum($this->conversions);
    }

    public function getTotalRevenue(): float
    {
        return (float) $this->revenue['total'];
    }

    public function getCurrency(): string
    {
        return (string) $this->revenue['currency'];
    }

    public function getTransactionCount(): int
    {
        return (int) $this->revenue['transactions'];
    }

    public function getAverageOrderValue(): float
    {
        return (float) $this->revenue['average_order_value'];
    }

    public function getTotalGoalCompletions(): int
    {
        return array_sum($this->goalCompletions);
    }

    public function getConversionRate(): float
    {
        if (! isset($this->funnelData['overall_conversion'])) {
            return 0.0;
        }

        return (float) $this->funnelData['overall_conversion'];
    }

    public function getTopConversionType(): ?string
    {
        if (empty($this->conversions)) {
            return null;
        }

        return array_key_first(
            array_slice($this->conversions, 0, 1, true)
        );
    }

    public function getTopGoal(): ?string
    {
        if (empty($this->goalCompletions)) {
            return null;
        }

        $sortedGoals = $this->goalCompletions;
        arsort($sortedGoals);

        return array_key_first($sortedGoals);
    }

    /**
     * Calculate revenue per conversion
     */
    public function getRevenuePerConversion(): float
    {
        $totalConversions = $this->getTotalConversions();
        if ($totalConversions === 0) {
            return 0.0;
        }

        return $this->getTotalRevenue() / $totalConversions;
    }

    /**
     * Get business insights and KPIs
     * @return array<string, mixed>
     */
    public function getInsights(): array
    {
        return [
            'total_revenue' => $this->getTotalRevenue(),
            'currency' => $this->getCurrency(),
            'total_conversions' => $this->getTotalConversions(),
            'total_transactions' => $this->getTransactionCount(),
            'average_order_value' => $this->getAverageOrderValue(),
            'revenue_per_conversion' => $this->getRevenuePerConversion(),
            'overall_conversion_rate' => $this->getConversionRate() * 100, // as percentage
            'top_conversion_type' => $this->getTopConversionType(),
            'top_goal' => $this->getTopGoal(),
            'is_profitable' => $this->getTotalRevenue() > 0,
            'has_transactions' => $this->getTransactionCount() > 0,
        ];
    }

    /**
     * Legacy array format for backward compatibility
     * @return array<string, mixed>
     */
    public function toArray(): array
    {
        return [
            'conversions' => $this->conversions,
            'revenue' => $this->revenue,
            'goals' => $this->goalCompletions,
            'funnel' => $this->funnelData,
        ];
    }

    /**
     * Enhanced analytics array with insights
     * @return array<string, mixed>
     */
    public function toAnalyticsArray(): array
    {
        return [
            'conversions' => $this->conversions,
            'revenue' => $this->revenue,
            'goals' => $this->goalCompletions,
            'funnel' => $this->funnelData,
            'insights' => $this->getInsights(),
        ];
    }
}
