<?php

namespace App\Http\Traits;

use App\Events\BulkUpdates;
use App\Models\Asset;
use App\Models\AssetType;
use App\Models\MakeAndModel;
use App\Models\TechnicalSpecs;
use Carbon\Carbon;

trait AutoHardwareUpdateTrait
{
    /**
     * Updates the hardware of an asset based on discovery data and technical specifications.
     *
     * @param array $discoveryData An array containing the discovery data for the asset.
     *                             It must contain the keys 'asset_type_id' and 'serial_no'.
     * @param array $techSpec An array containing the technical specifications for the asset.
     *                        It must contain the key 'technicalSpecs' with an object that has the keys 'id' and 'make_and_model_id'.
     * @param mixed|null $discoveryTool The tool used for the discovery, or null if not applicable.
     * @return bool Returns true if the asset was successfully updated, false otherwise.
     */
    public function autoHardwareUpdate(array $discoveryData, array $techSpec, $discoveryTool = null): bool
    {
        $assetData = [
            'asset_type_id'     => $discoveryData['asset_type_id'],
            'technical_spec_id' => $techSpec['technicalSpecs']->id,
            'make_and_model_id' => $techSpec['technicalSpecs']->make_and_model_id ?? '',
        ];


        $asset = Asset::with('assetType:id,name', 'makeAndModel:id,name', 'technicalSpec:id,details')->select('assets.*')->where('serial_no', $discoveryData['serial_no'])->first();

        if (!$asset) {
            return false;
        }
        if (
            $asset->asset_type_id == $assetData['asset_type_id']  &&
            $asset->technical_spec_id == $assetData['technical_spec_id'] &&
            $asset->make_and_model_id == $assetData['make_and_model_id']
        ) {

            return false;
        }
        $this->createHardwareUpdateHistory($asset, $assetData, $discoveryTool);
        $asset->update($assetData);

        return true;
    }


    /**
     * Creates a hardware update history for the given asset with the provided data.
     *
     * @param Asset $asset The asset to create the history for.
     * @param array $data An array containing the data for the hardware update.
     *                    It must contain the keys 'asset_type_id' and 'serial_no'.
     * @param mixed|null $discoveryTool The tool used for the discovery, or null if not applicable.
     * @return void
     */
    public function createHardwareUpdateHistory(Asset $asset, array $data, $discoveryTool = null): void
    {
        $description = $this->generateHardwareUpdateDescription($asset, $data);

        $historyDescription = __('history.UpdateAssetAttributes', [
            'asset_name' => $asset->serial_no,
            'asset_id' => $asset->id,
            'attributes' => $description,
        ]);

        $assetHistory = [
            'asset_id' => $asset->id,
            'action' => 'assetAttribute_updated',
            'description' => $historyDescription,
            'created_by' => $discoveryTool,
            'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
            'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
        ];

        event(new BulkUpdates($assetHistory));
    }

    /**
     * Generates a hardware update description based on the differences between the given asset and the provided data.
     *
     * @param Asset $asset The asset to compare against.
     * @param array $data An array containing the data to compare against the asset.
     *                    It must contain the keys 'asset_type_id', 'make_and_model_id', and 'technical_spec_id'.
     * @return string The generated hardware update description.
     */
    private function generateHardwareUpdateDescription($asset, array $data): string
    {
        $changes = [];

        if ($asset->asset_type_id != $data['asset_type_id']) {
            $newAssetType = AssetType::find($data['asset_type_id'])->name ?? '-';
            $oldAssetType = optional($asset->assetType)->name ?? '-';
            $changes[] = __('history.AttributeUpdated', [
                'attributeName' => 'Asset Type',
                'oldValue' => $oldAssetType,
                'newValue' => $newAssetType,
            ]);
        }

        if ($asset->make_and_model_id != $data['make_and_model_id']) {
            $newMakeAndModel = MakeAndModel::find($data['make_and_model_id'])->name ?? '-';
            $oldMakeAndModel = optional($asset->makeAndModel)->makeModelName ?? '-';
            $changes[] = __('history.AttributeUpdated', [
                'attributeName' => 'Hardware Standard',
                'oldValue' => $oldMakeAndModel,
                'newValue' => $newMakeAndModel,
            ]);
        }

        if ($asset->technical_spec_id != $data['technical_spec_id']) {
            $newTechSpecs = TechnicalSpecs::find($data['technical_spec_id'])->details ?? '-';
            $oldTechSpecs = optional($asset->technicalSpec)->details ?? '-';
            $changes[] = __('history.AttributeUpdated', [
                'attributeName' => 'Technical Specs',
                'oldValue' => $oldTechSpecs,
                'newValue' => $newTechSpecs,
            ]);
        }

        return implode(', ', $changes);
    }
}
