<?php

namespace App\Services\Manage;

use App\Enums\PriceType;
use App\Models\CuttingResultPrice;
use App\Models\ProductPrice;
use Illuminate\Support\Collection;

class CuttingResultPriceResolver
{
    public function resolve(int $productVariantId, PriceType $priceType): ?CuttingResultPrice
    {
        $price = CuttingResultPrice::query()
            ->where('product_variant_id', $productVariantId)
            ->where('price_type', $priceType)
            ->whereHas('cutting', fn ($query) => $query->verified())
            ->join('cuttings', 'cutting_result_prices.cutting_id', '=', 'cuttings.id')
            ->orderByDesc('cuttings.created_at')
            ->select('cutting_result_prices.*')
            ->first();

        if ($price !== null) {
            return $price;
        }

        $productPrice = ProductPrice::query()
            ->where('variant_id', $productVariantId)
            ->where('type', $priceType)
            ->first();

        if ($productPrice !== null) {
            $cp = new CuttingResultPrice;
            $cp->product_variant_id = $productVariantId;
            $cp->price_type = $priceType;
            $cp->price = $productPrice->price;

            return $cp;
        }

        return null;
    }

    public function latestPricesForVariant(int $productVariantId): array
    {
        $prices = [];

        foreach (PriceType::cases() as $priceType) {
            $price = $this->resolve($productVariantId, $priceType);

            if ($price !== null) {
                $prices[] = $price;
            }
        }

        return $prices;
    }

    public function latestPricesForVariants(array $variantIds): Collection
    {
        if (empty($variantIds)) {
            return collect();
        }

        $cuttingPrices = CuttingResultPrice::query()
            ->whereIn('product_variant_id', $variantIds)
            ->whereHas('cutting', fn ($query) => $query->verified())
            ->join('cuttings', 'cutting_result_prices.cutting_id', '=', 'cuttings.id')
            ->orderByDesc('cuttings.created_at')
            ->select('cutting_result_prices.*')
            ->get()
            ->groupBy(fn (CuttingResultPrice $price) => $price->product_variant_id.'-'.$price->price_type->value)
            ->map(fn (Collection $group) => $group->first());

        $productPrices = ProductPrice::query()
            ->whereIn('variant_id', $variantIds)
            ->get()
            ->groupBy(fn (ProductPrice $price) => $price->variant_id.'-'.$price->type->value);

        $results = collect();
        foreach ($variantIds as $variantId) {
            foreach (PriceType::cases() as $priceType) {
                $key = $variantId.'-'.$priceType->value;
                if ($cuttingPrices->has($key)) {
                    $results->push($cuttingPrices->get($key));
                } elseif ($productPrices->has($key)) {
                    $pp = $productPrices->get($key)->first();
                    $cp = new CuttingResultPrice;
                    $cp->product_variant_id = $variantId;
                    $cp->price_type = $priceType;
                    $cp->price = $pp->price;
                    $results->push($cp);
                }
            }
        }

        return $results->groupBy('product_variant_id');
    }
}
