<?php

namespace App\Services;

use App\Models\Attribute;
use App\Models\AttributeSiUnit;
use App\Models\AttributeValue;
use App\Models\Business;
use App\Models\BusinessCategoryAttribute;
use App\Models\User;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

trait AttributeService
{
    /**
     * Store new record
     *
     * @param array $data
     * @return Builder|Model
     */
    public static function store(array $data): Model|Builder
    {
        return Attribute::query()->create($data);
    }

    /**
     * Update existing record
     *
     * @param array $data
     * @return mixed
     */
    public function updateService(array $data): mixed
    {
        return tap($this)->update($data);
    }

    /**
     * Get business attributes
     *
     * @param Business $business
     * @return array|null
     */
    public static function getBusinessAttributes(Business $business): ?array
    {
        try {
            $businessCategoryId = $business->{"business_category_id"};
            $businessCategoryAttributes = BusinessCategoryAttribute::query()->with("attribute")->where("business_category_id", $businessCategoryId)->get();
            $businessCategoryAttributeArray = array();

            foreach ($businessCategoryAttributes as $businessCategoryAttribute) {
                $businessCategoryAttributeArray[] = Attribute::toCustomJson(
                    $businessCategoryAttribute->{"attribute"}
                );
            }

            $combinedResult = array(
                "attributes" => $businessCategoryAttributeArray,
                "custom_attributes" => self::getBusinessCustomAttributes($business->{"id"}),
            );

            $result = $combinedResult;
        } catch (Exception $exception) {
            log_debug(exception: $exception, prefix: 'AttributeService::getAllAttributes');
            $result = null;
        }

        return $result;
    }

    /**
     * Get attribute SI units
     *
     * @return array
     */
    public static function getBaseAttributes(): array
    {
        $baseAttributes = Attribute::query()->whereNull("business_id")->get();

        $baseAttributesArray = array();
        foreach ($baseAttributes as $attribute) {
            $baseAttributesArray[] = Attribute::toCustomJson($attribute);
        }

        return $baseAttributesArray;
    }


    /**
     * Get business custom attributes
     *
     * @param int $businessId
     * @return array
     */
    public static function getBusinessCustomAttributes(int $businessId): array
    {
        $attributes = Attribute::query()->where("business_id", $businessId)->get();

        $attributesArray = array();
        foreach ($attributes as $attribute) {
            $attributesArray[] = Attribute::toCustomJson($attribute);
        }

        return $attributesArray;
    }

    /**
     * Create custom attributes
     *
     * @param array $data
     * @return array|null
     */
    public static function createCustomAttribute(array $data): ?array
    {
        /** @var User $user */
        $user = auth()->user();

        DB::beginTransaction();
        try {
            $userBusiness = $user->{"business"};

            //Create Attribute
            $attribute = self::store([
                "designation" => $data["attribute_designation"],
                "can_take_value" => $data["can_take_value"],
                "business_id" => $userBusiness->{"id"},
            ]);

            //Check if attribute has SI unit(s)
            if (isset($data["si_units"]) && sizeof($data["si_units"]) !== 0) {
                foreach ($data["si_units"] as $siUnit) {
                    //Check if SI unit id was instead sent
                    if (array_key_exists("attribute_si_unit_id", $siUnit)) {
                        //Create Attribute values
                        AttributeValue::store([
                            "attribute_si_unit_id" => $siUnit["attribute_si_unit_id"],
                            "attribute_id" => $attribute->{"id"},
                        ]);
                    }

                    if (isset($siUnit["si_unit"]) && isset($siUnit["si_unit_designation"])) {
                        //Create Attribute Si units
                        $attributeSiUnit = AttributeSiUnit::store([
                            "si_unit" => $siUnit["si_unit"],
                            "si_unit_designation" => $siUnit["si_unit_designation"],
                            "attribute_id" => $attribute->{"id"},
                        ]);

                        //Create Attribute values
                        if (! array_key_exists("attribute_si_unit_id", $siUnit)) {
                            AttributeValue::store([
                                "attribute_si_unit_id" => $attributeSiUnit->{"id"},
                                "attribute_id" => $attribute->{"id"},
                            ]);
                        }
                    }
                }
            }

            DB::commit();

            $result = Attribute::toCustomJson($attribute);
        } catch (\Exception $exception) {
            log_debug(exception: $exception, prefix: 'AttributeService::createCustomAttribute');
            DB::rollBack();

            $result = null;
        }

        return $result;
    }
}
