<?php

namespace Beike\Admin\Services;

use Beike\Models\Product;
use Illuminate\Support\Facades\DB;

class ProductService
{
    public function create(array $data): Product
    {
        $product = new Product;

        return $this->createOrUpdate($product, $data);
    }

    public function update(Product $product, array $data): Product
    {
        return $this->createOrUpdate($product, $data);
    }

    public function copy(Product $oldProduct): Product
    {
        $product = new Product;
        $data = $oldProduct->toArray();
        $data['id'] = 0;
        $data['created_at'] = now();
        $data['variables'] = json_encode($data['variables'],JSON_UNESCAPED_UNICODE);
        $data['descriptions'] = $oldProduct->descriptions()->get()->toArray();
        foreach ($data['descriptions'] as $locale => $description) {
            $data['descriptions'][$description['locale']] = $description;
            unset($data['descriptions'][$locale]);
        }
        $data['attributes'] = $oldProduct->attributes()->get()->toArray();
        $data['skus'] = $oldProduct->skus()->get()->toArray();
        $data['numPrices'] = $oldProduct->numPrices()->get()->toArray();
        $data['categories'] = $oldProduct->categories()->get()->toArray();
        $data['relations'] = $oldProduct->relations()->get()->toArray();
        $data['categories'] = array_column($data['categories'],'id');
        $data['relations'] = array_column($data['relations'],'id');
        return $this->createOrUpdate($product, $data);
    }

    protected function createOrUpdate(Product $product, array $data): Product
    {
        $isUpdating = $product->id > 0;

        try {
            DB::beginTransaction();

            $data['brand_id']  = (int) ($data['brand_id'] ?? 0);
            $data['position']  = (int) ($data['position'] ?? 0);
            $data['weight']    = (float) ($data['weight'] ?? 0);
            $data['variables'] = json_decode($data['variables'] ?? '[]');
            $product->fill($data);
            $product->updated_at = now();
            $product->save();

            if ($isUpdating) {
                $product->skus()->delete();
                $product->descriptions()->delete();
                $product->attributes()->delete();
                $product->numPrices()->delete();
            }

            $descriptions = [];
            foreach ($data['descriptions'] as $locale => $description) {
                $description['locale']  = $locale;
                $description['content'] = $description['content'] ?? '';

                $descriptions[] = $description;
            }
            $product->descriptions()->createMany($descriptions);

            $product->attributes()->createMany($data['attributes'] ?? []);

            $skus = [];
            foreach ($data['skus'] as $index => $sku) {
                $sku['position']     = $index;
                $sku['origin_price'] = (float) $sku['origin_price'];
                $sku['cost_price']   = (float) $sku['cost_price'];
                $sku['quantity']     = (int) $sku['quantity'];
                $skus[]              = $sku;
            }
            $product->skus()->createMany($skus);

            if($data['price_setting'] == 'num' && !empty($data['numPrices'])){
                $product->numPrices()->createMany(list_sort_by($data['numPrices'],'num') ?? []);
            }

            $product->categories()->sync($data['categories'] ?? []);
            $product->relations()->sync($data['relations'] ?? []);

            DB::commit();

            return $product;
        } catch (\Exception $e) {
            DB::rollBack();

            throw $e;
        }
    }
}
