<?php

declare(strict_types=1);

namespace App\Business\Sales;

use App\Business\Sales\Enums\CustomerPriceRuleStatus;
use App\Business\Sales\Enums\CustomerPriceRuleType;
use App\Business\Sales\Enums\PriceSourceType;
use App\Models\DberpCustomer;
use App\Models\DberpCustomerPriceRule;
use App\Models\DberpProduct;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Builder;

final class CustomerPriceResolverService
{
    /**
     * @return array<string, mixed>
     */
    public function resolvePrice(DberpCustomer $customer, DberpProduct $product, ?string $externalSku = null, CarbonInterface|string|null $onDate = null): array
    {
        $date = $onDate instanceof CarbonInterface ? $onDate->toDateString() : ($onDate ?: now()->toDateString());
        $customer->refresh();

        $baseQuery = DberpCustomerPriceRule::query()
            ->where('product_id', $product->getKey())
            ->where('status', CustomerPriceRuleStatus::Active->value)
            ->whereDate('valid_from', '<=', $date)
            ->where(function (Builder $query) use ($date): void {
                $query->whereNull('valid_until')->orWhereDate('valid_until', '>=', $date);
            })
            ->where(function (Builder $query) use ($externalSku): void {
                if ($externalSku !== null && $externalSku !== '') {
                    $query->where(function (Builder $subQuery) use ($externalSku): void {
                        $subQuery->whereNull('external_sku')->orWhere('external_sku', $externalSku);
                    });
                }
            })
            ->orderBy('sort_order')
            ->orderByDesc('valid_from')
            ->orderByDesc('id');

        $exclusiveRule = (clone $baseQuery)
            ->where('rule_type', CustomerPriceRuleType::Exclusive->value)
            ->where('customer_id', $customer->getKey())
            ->first();

        if ($exclusiveRule !== null) {
            return [
                'unit_price' => (string) $exclusiveRule->unit_price,
                'price_source_type' => PriceSourceType::ExclusivePrice->value,
                'price_source_label' => PriceSourceType::ExclusivePrice->label(),
                'price_rule_id' => $exclusiveRule->getKey(),
                'reference_unit_price' => (string) $product->sales_price,
            ];
        }

        if ($customer->price_level_code !== null && $customer->price_level_code !== '') {
            $levelRule = (clone $baseQuery)
                ->where('rule_type', CustomerPriceRuleType::Level->value)
                ->where('price_level_code', $customer->price_level_code)
                ->first();

            if ($levelRule !== null) {
                return [
                    'unit_price' => (string) $levelRule->unit_price,
                    'price_source_type' => PriceSourceType::LevelPrice->value,
                    'price_source_label' => PriceSourceType::LevelPrice->label(),
                    'price_rule_id' => $levelRule->getKey(),
                    'reference_unit_price' => (string) $product->sales_price,
                ];
            }
        }

        $defaultRule = (clone $baseQuery)
            ->where('rule_type', CustomerPriceRuleType::Default->value)
            ->whereNull('customer_id')
            ->whereNull('price_level_code')
            ->first();

        if ($defaultRule !== null) {
            return [
                'unit_price' => (string) $defaultRule->unit_price,
                'price_source_type' => PriceSourceType::DefaultSalesPrice->value,
                'price_source_label' => PriceSourceType::DefaultSalesPrice->label(),
                'price_rule_id' => $defaultRule->getKey(),
                'reference_unit_price' => (string) $product->sales_price,
            ];
        }

        return [
            'unit_price' => (string) $product->sales_price,
            'price_source_type' => PriceSourceType::DefaultSalesPrice->value,
            'price_source_label' => PriceSourceType::DefaultSalesPrice->label(),
            'price_rule_id' => null,
            'reference_unit_price' => (string) $product->sales_price,
        ];
    }
}