<?php

declare(strict_types=1);

namespace Maestro\Core\Modules\Offers\Services;

use Illuminate\Support\Facades\DB;
use Maestro\Core\Modules\Offers\Enums\OfferDiscountType;
use Maestro\Core\Modules\Offers\Enums\OfferPricingType;
use Maestro\Core\Modules\Offers\Models\Offer;
use Maestro\Core\Modules\Offers\Models\OfferRow;
use Maestro\Core\Modules\Offers\Models\OfferSection;

final class OfferStructureSync
{
    /**
     * @param  array<int, array<string, mixed>>  $sections
     */
    public static function replace(Offer $offer, array $sections): void
    {
        DB::transaction(function () use ($offer, $sections): void {
            $offer->sections()->delete();

            foreach ($sections as $sPos => $s) {
                $section = OfferSection::query()->create([
                    'offer_id' => $offer->id,
                    'title' => (string) $s['title'],
                    'description_html' => isset($s['description_html']) ? (string) $s['description_html'] : null,
                    'sort_order' => isset($s['sort_order']) ? (int) $s['sort_order'] : $sPos,
                ]);

                foreach ($s['rows'] ?? [] as $rPos => $r) {
                    $pricing = OfferPricingType::tryFrom((string) ($r['pricing_type'] ?? 'one_time')) ?? OfferPricingType::OneTime;
                    $discountT = OfferDiscountType::tryFrom((string) ($r['discount_type'] ?? 'none')) ?? OfferDiscountType::None;

                    OfferRow::query()->create([
                        'offer_section_id' => $section->id,
                        'offer_service_catalog_item_id' => $r['offer_service_catalog_item_id'] ?? null,
                        'description_html' => isset($r['description_html']) ? (string) $r['description_html'] : null,
                        'pricing_type' => $pricing->value,
                        'custom_unit_label' => isset($r['custom_unit_label']) ? (string) $r['custom_unit_label'] : null,
                        'quantity' => (float) ($r['quantity'] ?? 1),
                        'unit_price' => (float) ($r['unit_price'] ?? 0),
                        'discount_type' => $discountT->value,
                        'discount_value' => (float) ($r['discount_value'] ?? 0),
                        'vat_rate' => (float) ($r['vat_rate'] ?? 0),
                        'sort_order' => isset($r['sort_order']) ? (int) $r['sort_order'] : $rPos,
                    ]);
                }
            }

            OfferTotalsService::persistOfferVat($offer->fresh(['sections.rows']));
        });
    }

    /** Copy sections/rows from source offer onto a blank target draft. */
    public static function copyFromOffer(Offer $source, Offer $target): void
    {
        $source->loadMissing('sections.rows');
        $payload = [];

        foreach ($source->sections as $section) {
            $rows = [];
            foreach ($section->rows as $row) {
                $rows[] = [
                    'description_html' => $row->description_html,
                    'pricing_type' => $row->pricing_type?->value,
                    'custom_unit_label' => $row->custom_unit_label,
                    'quantity' => $row->quantity,
                    'unit_price' => $row->unit_price,
                    'discount_type' => $row->discount_type?->value,
                    'discount_value' => $row->discount_value,
                    'vat_rate' => $row->vat_rate,
                    'offer_service_catalog_item_id' => $row->offer_service_catalog_item_id,
                    'sort_order' => $row->sort_order,
                ];
            }

            $payload[] = [
                'title' => $section->title,
                'description_html' => $section->description_html,
                'sort_order' => $section->sort_order,
                'rows' => $rows,
            ];
        }

        self::replace($target, $payload);
    }
}
