<?php

namespace App\Services\BulkUpload;

use App\Http\Traits\AssetAttributeUpdateTrait;
use App\Models\AssetStatus;
use App\Models\Asset;
use App\Events\BulkUpdates;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use App\Services\Integrations\Tickets\TicketManagementService;

class SpecialBulkAssetAttributeService extends SpecialBulkAbstract
{
    use AssetAttributeUpdateTrait;

    /**
     * Class constructor.
     *
     * @param TicketManagementService $ticketManagementService The ticket management service instance.
     */
    public function __construct(protected TicketManagementService $ticketManagementService)
    {
    }

    /**
     * Retrieves the header map configuration for bulk uploads.
     *
     * @return array The header map configuration.
     */
    public function getHeaderMap()
    {
        return config('bulk-upload.attributeUpdateData');
    }

    /**
     * Retrieves the status slug.
     *
     * @return string The status slug.
     */
    public function getStatusSlug()
    {
        return "";
    }

    /**
     * Retrieves the default ticket.
     *
     * @return string The default ticket.
     */
    public function getDefaultTicket()
    {
        return '';
    }

    /**
     * Retrieves specific data from the given asset.
     *
     * @param Asset $asset The asset instance from which to retrieve data.
     *
     * @return string The retrieved data.
     */
    public function getData(Asset $asset)
    {
        return "";
    }

    /**
     * Imports special asset data from a given file path.
     *
     * @param string      $path     The path to the file containing asset data.
     * @param string|null $fileName The optional name of the file.
     *
     * @return array An array of error data encountered during import.
     */
    public function importAssetSpecialData($path, $fileName = null)
    {
        $data = $this->getItems($path);
        $items = $data['csvData'];
        $errorData = [];
        $ticketNo = '';
        $errorData['validationErrors'] = $this->validateFields($items);

        if (!empty($items) && empty($errorData['validationErrors'])) {
            unset($errorData['validationErrors']);

            foreach ($items as $item) {
                // Skip empty columns.
                if (!count($item)) {
                    continue;
                }

                $csvData = $this->generateSpecialCSVData($item);
                $assetData = $csvData['assetData'];

                if ($csvData['errorData']) {
                    $errorData[] = $csvData['errorData'];
                }

                if (isset($assetData['id'])) {
                    $asset = Asset::find($assetData['id']);

                    if ($asset) {
                        $dataToupdate  = $this->getAttributeData($assetData, $asset);

                        if ($dataToupdate['asset'] && !empty($dataToupdate['asset'])) {
                            $this->saveAssetHistory($asset, $dataToupdate);
                            $asset->update($dataToupdate['asset']);
                        }
                    }
                }

                $ticketNo = $ticketNo ? $ticketNo : $assetData['ticket_no'];
            }

            $this->attachFiletoTicket($ticketNo, $path, $fileName);
        }

        return $errorData;
    }

    /**
     * Generates special CSV data from the given item.
     *
     * @param array $item The item to process.
     *
     * @return array An array containing 'assetData' and 'errorData'.
     */
    public function generateSpecialCSVData($item)
    {
        if (empty($item)) {
            return false;
        }

        $assetData    = [];
        $errorData    = [];

        foreach ($this->getHeaderMap() as $dbField => $fileHeader) {
            $result = $this->getRelationalValues($item, $dbField, $fileHeader);

            if ($result !== false) {
                $item[$fileHeader] = $result;
            }

            $assetData[$dbField] = !empty($item[$fileHeader]) ? $item[$fileHeader] : null;

            if ($dbField == "serial_no") {
                if (!empty($item[$fileHeader])) {
                    $asset = Asset::where('serial_no', trim($item[$fileHeader]))->first();

                    if ($asset) {
                        $assetData['id'] = $asset->id;
                    }

                    if (!$asset) {
                        $errorData[] = 'Asset with serial # ' . $item[$fileHeader] . ' do not exist';
                    }
                }
            }
        }

        return compact('assetData', 'errorData');
    }

    /**
     * Saves the history of the given asset with the provided data.
     *
     * @param Asset $asset The asset for which the history is being saved.
     * @param array $data  The data related to the asset changes, including history details.
     *
     * @return void|null Returns null if no history is provided.
     */
    public function saveAssetHistory(Asset $asset, array $data)
    {
        $history = rtrim(trim($data['history']), ',');

        if (!$history) {
            return null;
        }

        $description = "Updated attributes of Asset <a href='" . route('assets.show', $asset->id) . "'>$asset->asset_tag</a> " . $history;

        $assetHistory = [
            'user_id' => Auth::id(),
            'asset_id' => $asset->id,
            'ticket_no' => $data['asset']['ticket_no'],
            'ticket_service_provider' => config('ticket-integration.service'),
            'action' => 'assetAttributes_changed',
            'comments' => '',
            'description' => $description,
            'created_at'  => Carbon::now()->format('Y-m-d H:i:s'),
            'updated_at'  => Carbon::now()->format('Y-m-d H:i:s'),
        ];

        $assetHistory = $this->getAdditionalHistoryData($assetHistory, $data, $asset);

        event(new BulkUpdates($assetHistory));
    }

    /**
     * Attaches a file to the specified ticket.
     *
     * @param mixed  $ticketid The ID of the ticket to which the file will be attached.
     * @param string $filePath The path to the file to be attached.
     * @param string $fileName The name of the file to be attached.
     *
     * @return bool Returns true if the file was successfully attached, false otherwise.
     */
    public function attachFiletoTicket($ticketid, $filePath, $fileName)
    {
        if (!$ticketid || !$filePath || !$fileName) {
            return false;
        }

        $this->ticketManagementService->attachActionHistorytoTicket($ticketid, 'Bulk asset attribute update (special)', Auth::user()->id, $filePath, $fileName);

        return true;
    }
}
