<?php

namespace App\Services\Asn\Cdw;

use App\Events\BulkUpdates;
use App\Models\Asset;
use App\Models\AssetHistory;
use App\Models\AssetStatus;
use App\Models\AssetTracking;
use App\Models\AsnAccessoriesMapping;
use App\Models\AsnHardwareMapping;
use App\Models\AsnUnwantedPart;
use App\Models\MakeAndModel;
use Carbon\Carbon;
use Illuminate\Support\Facades\Validator;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;

class CdwUploadService
{

    /**
     * updateTrackingNumber
     *
     * @param  mixed $item
     * @return void
     */
    public function updateTrackingNumber($item)
    {
        $trackingNumber = $item['Tracking Number'] ?? '';
        $serial_no      = $item['Serial Number'] ?? '';
        $asset_tag      = $item['Asset Tag'] ?? '';

        if (!$trackingNumber || !($serial_no || $asset_tag)) {
            return;
        }

        $asset = new Asset;
        if ($serial_no) {
            $asset = $asset->where('serial_no', stripS($serial_no));
        }
        if ($asset_tag) {
            $asset = $asset->where('asset_tag', stripS($asset_tag));
        }
        $asset = $asset->first();

        if (!$asset) {
            return;
        }

        $tracking = AssetTracking::firstOrCreate(['tracking_number' => $trackingNumber]);
        $asset->update(['asset_tracking_id' => $tracking->id]);

        return true;
    }

    /**
     * updateShipmentStatus
     *
     * @return void
     */
    public function updateShipmentStatus()
    {
        $assets = Asset::whereNotNull('asset_tracking_id')->with('assetTracking')
            ->whereHas('assetTracking', function ($query) {
                $query->whereNotNull('active');
            })->get();

        foreach ($assets as $asset) {
            try {
                $shipmentStatusRes = $this->upsTracking->shipmentStatus($asset->assetTracking->tracking_number);
                if ($shipmentStatusRes['status'] == "No tracking information available") {
                    $asset->assettracking()->update(['active' => 0]);
                    continue;
                }
                $asset->assettracking()->update(['shipment_status' => $shipmentStatusRes['status'], 'status_updated_on' => $shipmentStatusRes['updated_on']]);
            } catch (\Throwable $e) {
                continue;
            }
        }
        return true;
    }

    public function getLatestFileNames($path)
    {
        $files = scandir($path, SCANDIR_SORT_DESCENDING);

        if (!$files) {
            return false;
        }

        return $files;
    }

    /**
     * getLatestFileName
     *
     * @param  mixed $path
     * @return void
     */
    public function getLatestFileName($path)
    {
        $files = scandir($path, SCANDIR_SORT_DESCENDING);
        if (!$files) {
            return false;
        }

        return $files[0];
    }

    /**
     * getItems
     *
     * @param  mixed $path
     * @return void
     */
    public function getItems($path)
    {
        if (!file_exists($path)) {
            return false;
        }
        $extension = getFileExtension($path);
        if ($extension == 'csv') {
            $items = csv_to_array($path);
        } elseif ($extension == 'xlsx') {
            $items = excel_to_array($path);
        }
        if (empty($items)) {
            return false;
        }

        return $items;
    }
    /**
     * Trim the po number
     */
    public function createCdwData($item, $count)
    {
        $createdData = ['assetData' => [], 'error' => []];
        $assetData = [];
        if ($this->isAccessories($item)) {
            $createdData = ['assetData' => $assetData, 'error' => ['cdwdata' => ['Line No ' . $count . ': The item is mapped as accessory.']]];
            return $createdData;
        }
        if ($this->isServicese($item['Item Type'])) {
            $createdData = ['assetData' => $assetData, 'error' => ['cdwdata' => ['Line No ' . $count . ': The item type is services.']]];
            return $createdData;
        }
        if ($this->isMobileNumber($item['Manufacturer Part Number'])) {
            $createdData = ['assetData' => $assetData, 'error' => ['cdwdata' => ['Line No ' . $count . ': The item is mobile number.']]];
            return $createdData;
        }
        if ($this->isUnwantedPart($item)) {
            $createdData = ['assetData' => $assetData, 'error' => ['cdwdata' => ['Line No ' . $count . ': The manufacturer part is marked as unwanted.']]];
            return $createdData;
        }

        $assetData = $this->setAssetArray($item);
        $existing = Asset::where('serial_no', $assetData['serial_no'])->orWhere('asset_tag', $assetData['asset_tag'])->first();
        if ($existing) {
            $createdData = ['assetData' => $assetData, 'error' => ['cdwdata' => ['Line No ' . $count . ': Asset already exists']]];
            $createdData;
        }
        $createdData = ['assetData' => $assetData, 'error' => []];
        return $createdData;
    }

    public function setAssetArray($item)
    {
        $assetData = $this->getTechDetails($item);
        $inTransit = AssetStatus::where('slug', 'cdw_in_transit')->first();
        $assetData['po_id']             = $item['Customer Purchase Order'] ?? '';
        $assetData['serial_no']         = $item['Serial Number'] ?? '';
        $assetData['serial_no']         = stripS($assetData['serial_no']);
        $assetData['asset_tag']         = $item['Asset Tag'] ?? ($item['Serial Number'] ?? '');
        $assetData['asset_tag']         = stripS($assetData['asset_tag']);
        if ($assetData['asset_tag'] == '') {
            $assetData['asset_tag']         = $assetData['serial_no'];
        }
        $assetData['asset_status_id']   = $inTransit ? $inTransit->id : '';
        $assetData['ticket_no']         = $item['Ticket Number'] ?? '';
        $assetData['description']       = $item['Manufacturer Part Number'] ?? '';
        $assetData['asset_original_value']  = $item['Cost'] ?? '';

        return $assetData;
    }

    /**
     * isAccessories
     *
     * @param  mixed $item
     * @return void
     */
    public function isAccessories($item)
    {
        if (isset($item['Manufacturer Part Number'])) {
            $accessories = AsnAccessoriesMapping::where(
                'description',
                $item['Manufacturer Part Number']
            )->first();
            return $accessories ? true : false;
        }

        return false;
    }

    /**
     * isUnwantedPart
     *
     * @param  mixed $item
     * @return void
     */
    public function isUnwantedPart($item)
    {
        if (isset($item['Manufacturer Part Number'])) {
            $accessories = AsnUnwantedPart::where(
                'description',
                $item['Manufacturer Part Number']
            )->first();
            return $accessories ? true : false;
        }

        return false;
    }

    /**
     * isServicese
     *
     * @param  mixed $itemType
     * @return void
     */
    public function isServicese($itemType)
    {
        if (strpos(strtolower($itemType), 'services') !== false) {
            return true;
        }

        return false;
    }

    /**
     * isMobileNumber
     *
     * @param  mixed $itemType
     * @return void
     */
    public function isMobileNumber($itemType)
    {
        /*    if (strpos($itemType, 'ZZZ260R060-UBER') !== false) {
               return true;
           }
            */
        return false;
    }

    /**
     * getTechDetails
     *
     * @param  mixed $item
     * @return void
     */
    public function getTechDetails($item)
    {
        $assetData['make_and_model_id'] = '';
        $assetData['technical_spec_id'] = '';
        $assetData['asset_type_id'] = '';
        if (isset($item['Manufacturer Part Number'])) {
            $hardware = AsnHardwareMapping::where('description', $item['Manufacturer Part Number'])->first();
            if ($hardware) {
                $makeAndModel = MakeAndModel::find($hardware->make_and_model_id);
                $assetData['make_and_model_id'] = $hardware->make_and_model_id;
                $assetData['technical_spec_id'] = $hardware->technical_spec_id;
                $assetData['asset_type_id']     = $makeAndModel->asset_type_id;
            }
        }
        return $assetData;
    }

    /**
     * validateItem
     *
     * @param  mixed $cdwData
     * @return void
     */
    public function validateItem($cdwData, $count = null)
    {
        $validationError = [];
        if (empty($cdwData)) {
            $validationError['cdwdata'] = ['Line No ' . $count . ': No CDW Data Found'];
            return $validationError;
        }

        $validator = Validator::make(
            $cdwData,
            [
                'po_id' => 'required|alpha_dash',
                'serial_no' => 'required|unique:assets,serial_no|alpha_dash',
                'asset_tag' => 'required|unique:assets,asset_tag|alpha_dash',
                'ticket_no' => 'nullable|alpha_dash',
                'asset_status_id' => 'required|integer',
                'description' => 'required',
            ],
            $messages = [
                'po_id.required' => 'Line no ' . $count . ' : The PO ID is required.',
                'po_id.alpha_dash' => 'Line no ' . $count . ' : The PO ID contains disallowed characters / invalid.',
                'serial_no.required' => 'Line no ' . $count . ' : The serial # is required.',
                'serial_no.unique' => 'Line no ' . $count . ' : The serial # already exists.',
                'serial_no.alpha_dash' => 'Line no ' . $count . ' : The serial # contains disallowed characters / invalid.',
                'asset_tag.alpha_dash' => 'Line no ' . $count . ' : The asset Tag # contains disallowed characters / invalid.',
                'asset_tag.unique' => 'Line no ' . $count . ' : The asset Tag # already exists',
                'ticket_no.alpha_dash' => 'Line no ' . $count . ' : The ticket # contains disallowed characters / invalid.',
                'ticket_no.required' => 'Line no ' . $count . ' : The ticket # is required.',
                'asset_status_id.required' => 'Line no ' . $count . ' : The asset status is required.',
                'description.required' => 'Line no ' . $count . ' : Please add a description.',
            ]
        );

        if ($validator->fails()) {
            return $validator->errors()->toArray();
        }
    }

    /**
     * createAssetHistory
     *
     * @param  mixed $asset
     * @return void
     */
    public function createAssetHistory($asset)
    {
        $comments = '';

        $assetHistory = [
            'asset_id' => $asset->id,
            'action' => 'imported_by_vendor',
            'description' =>  __('history.ImportedByVendor', [
                'asset_name' => $asset->serial_no,
                'asset_id' => $asset->id
            ]),
            '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));
    }
}
