<?php

namespace App\Services;

use App\CentralLogics\Helpers;

class DeliveryChargeService
{
    public const STATUS_KEY = 'maximum_delivery_charge_limit_status';
    public const LIMIT_KEY = 'maximum_delivery_charge_limit';

    public function settings(): array
    {
        return [
            'maximum_delivery_charge_limit_status' => (int) (Helpers::get_business_settings(self::STATUS_KEY) ?? 0),
            'maximum_delivery_charge_limit' => max((float) (Helpers::get_business_settings(self::LIMIT_KEY) ?? 0), 0),
            'admin_free_delivery_status' => (int) (Helpers::get_business_settings('admin_free_delivery_status') ?? 0),
            'admin_free_delivery_option' => Helpers::get_business_settings('admin_free_delivery_option'),
            'free_delivery_over' => max((float) (Helpers::get_business_settings('free_delivery_over') ?? 0), 0),
        ];
    }

    public function calculateItemWise(iterable $items): float
    {
        $calculatedCharge = 0;

        foreach ($items as $item) {
            $quantity = max((float) data_get($item, 'quantity', 0), 0);
            $itemDeliveryCharge = (float) data_get(
                $item,
                'item_delivery_charge',
                data_get($item, 'item.item_delivery_charge', data_get($item, 'product.item_delivery_charge', 0))
            );

            $calculatedCharge += max($itemDeliveryCharge, 0) * $quantity;
        }

        return $calculatedCharge;
    }

    public function applyMaximumLimit(float $calculatedCharge, ?array $settings = null): float
    {
        $calculatedCharge = max($calculatedCharge, 0);
        $settings ??= $this->settings();

        $enabled = (int) ($settings['maximum_delivery_charge_limit_status'] ?? 0) === 1;
        $limit = max((float) ($settings['maximum_delivery_charge_limit'] ?? 0), 0);

        if (!$enabled || $limit <= 0) {
            return $calculatedCharge;
        }

        return min($calculatedCharge, $limit);
    }

    public function calculateFinalCharge(
        float $calculatedCharge,
        float $eligibleOrderAmount = 0,
        string $orderType = 'delivery',
        bool $storeFreeDelivery = false,
        bool $couponFreeDelivery = false,
        ?string $couponCreatedBy = null,
        ?array $settings = null
    ): array {
        $settings ??= $this->settings();
        $calculatedCharge = max($calculatedCharge, 0);
        $limitedCharge = $this->applyMaximumLimit($calculatedCharge, $settings);
        $finalCharge = $limitedCharge;
        $freeDeliveryBy = null;

        if ($orderType === 'take_away') {
            $finalCharge = 0;
        } else {
            $adminFreeDelivery = (int) ($settings['admin_free_delivery_status'] ?? 0) === 1;
            $adminFreeDeliveryOption = $settings['admin_free_delivery_option'] ?? null;
            $freeDeliveryOver = max((float) ($settings['free_delivery_over'] ?? 0), 0);
            $eligibleOrderAmount = max($eligibleOrderAmount, 0);

            if (
                $adminFreeDelivery
                && (
                    $adminFreeDeliveryOption === 'free_delivery_to_all_store'
                    || (
                        $adminFreeDeliveryOption === 'free_delivery_by_order_amount'
                        && $freeDeliveryOver > 0
                        && $eligibleOrderAmount >= $freeDeliveryOver
                    )
                )
            ) {
                $finalCharge = 0;
                $freeDeliveryBy = 'admin';
            }

            if ($storeFreeDelivery) {
                $finalCharge = 0;
                $freeDeliveryBy = 'vendor';
            }

            if ($couponFreeDelivery) {
                $finalCharge = 0;
                $freeDeliveryBy = $couponCreatedBy ?: 'admin';
            }
        }

        return [
            'calculated_delivery_charge' => (float) $calculatedCharge,
            'limited_delivery_charge' => (float) $limitedCharge,
            'final_delivery_charge' => (float) $finalCharge,
            'free_delivery_by' => $freeDeliveryBy,
            'maximum_limit_applied' => $limitedCharge < $calculatedCharge,
            'maximum_delivery_charge_limit' => max((float) ($settings['maximum_delivery_charge_limit'] ?? 0), 0),
        ];
    }
}
