<?php

namespace App\Services\BulkUpload;

use App\Events\BulkUpdates;
use App\Http\Traits\AssetStatusTrait;
use App\Models\Asset;
use App\Models\AssetStatus;
use App\Models\AssetType;
use App\Models\MakeAndModel;
use App\Services\Asset\UpdateStatusService;
use App\Services\Integrations\Tickets\TicketManagementService;
use App\User;
use Carbon\Carbon;
use Facades\App\Repositories\BulkUpload;
use Facades\App\Services\AssetHistory as AssetHistoryService;
use Facades\App\Services\Asset\AssetStatusService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class BulkCreateLinkMobileService extends BulkAbstract
{
    use AssetStatusTrait;

    public function __construct(protected UpdateStatusService $updateStatusService, protected TicketManagementService $ticketManagementService) {}

    /**
     * Renders the CSV data into a view and returns the rendered content.
     *
     * @param array $csvData The CSV data to be rendered.
     * @param string $path The path of the file.
     * @param string $fileName The name of the file.
     * @return string The rendered content of the view.
     */
    public function renderCsvData($csvData, $path, $fileName)
    {
        return view('settings.partials.upload-create-link-mobiles', compact('csvData', 'path', 'fileName'))->render();
    }

    /**
     * Check if the asset can be updated to the status.
     *
     * @return array
     */
    public function checkCanBeUpdatedToStatus($csvDatas)
    {
        $errors = [];
        return ['errors' => $errors, 'csvData' => $csvDatas];
    }
    /**
     * Get Headers of CSV.
     *
     * @return array
     */
    public function getHeaderMap()
    {
        return Config('bulk-upload.createLinkMobileData');
    }

    /**
     * Get Default Ticket #.
     *
     * @return String
     */
    public function getDefaultTicket()
    {
        return Config('tickets.bulk_status_update');
    }

    /**
     * Get Status Slug.
     *
     * @return string
     */
    public function getStatusSlug()
    {
        return '';
    }

    /**
     * Get Status Name.
     *
     * @return string
     */
    public function getStatusName()
    {
        return '';
    }

    /**
     * Generate asset data from the csv array.
     *
     * @param array $item
     *
     * @return array
     */
    public function generateCSVData(array $item, int $count, $path = null, $fileName = null)
    {
        $assetData = [];
        foreach ($this->getHeaderMap() as $dbField => $fileHeader) {
            $result = $this->getRelationalValues($item, $dbField, $fileHeader);
            if ($dbField == 'po_id') {
                $assetData['po_id'] = $item[$fileHeader];
            }
            if ($dbField == 'make_and_model_id') {
                $assetData['hardware'] = $item[$fileHeader];
            }
            if ($dbField == 'technical_spec_id') {
                $assetData['tech_spech'] = $item[$fileHeader];
            }
            if ($dbField == 'location_id') {
                $assetData['location'] = $item[$fileHeader];
            }
            if ($dbField == 'carrier_id') {
                $assetData['carrier'] = $item[$fileHeader];
            }
            if ($result !== false) {
                $item[$fileHeader] = $result;
            }
            $assetData[$dbField] = !empty($item[$fileHeader]) ? $item[$fileHeader] : null;

            if ($dbField == 'make_and_model_id') {
                if (!empty($item[$fileHeader])) {
                    $makeModel = MakeAndModel::where('slug', trim(str_slug($item[$fileHeader], '_')))->first();
                    if ($makeModel) {
                        $assetData['asset_type_id'] = $makeModel->asset_type_id;
                        $assetData['manufacturer_id'] = $makeModel->manufacturer_id;
                        $assetData['make_and_model_id'] = $makeModel->id;
                    }
                    if (!$makeModel) {
                        $assetData['asset_type_id'] = null;
                        $assetData['manufacturer_id'] = null;
                        $assetData['make_and_model_id'] = null;
                    }

                    $mobile = AssetType::where('slug', 'mobile_phone')->first();
                    if ($makeModel) {
                        $assetData['asset_type_id'] = $makeModel->asset_type_id;
                        $assetData['manufacturer_id'] = $makeModel->manufacturer_id;
                        $assetData['make_and_model_id'] = $makeModel->id;
                    }
                    if (!$makeModel) {
                        $assetData['asset_type_id'] = null;
                        $assetData['manufacturer_id'] = null;
                        $assetData['make_and_model_id'] = null;
                    }
                    if ($assetData['asset_type_id'] != $mobile?->id) {
                        $assetData['asset_type_id'] = null;
                        $assetData['manufacturer_id'] = null;
                        $assetData['make_and_model_id'] = null;
                    }
                }
            }
            if ($fileName && $path) {
                $assetData['filePath'] = $path;
                $assetData['fileName'] = $fileName;
            }
        }

        $assetData['asset_count'] = $count++;
        session(['asset_count' => $assetData['asset_count']]);
        return compact('assetData');
    }

    /**
     * Get Related Values for ids.
     * @param  array $item
     * @param  string $dbField
     * @param  string $fileHeader
     *
     * @return mixed
     */
    public function getRelationalValues($item,  $dbField,  $fileHeader)
    {
        if ($dbField == 'location_id') {
            return BulkUpload::getLocationId($item, $dbField, $fileHeader);
        }

        if ($dbField == 'ticket_no') {
            return !empty($item[$fileHeader]) ? $item[$fileHeader] : null;
        }

        if ($dbField == 'technical_spec_id') {
            return BulkUpload::getTechnicalSpecId($item, $dbField, $fileHeader);
        }

        if ($dbField == 'carrier_id') {
            return BulkUpload::getCarrierId($item, $dbField, $fileHeader);
        }

        // if ($dbField == 'po_id') {
        //     return BulkUpload::getPurchaseOrderId($item, $dbField, $fileHeader);
        // }

        return false;
    }

    /**
     * Get Additonal Asset Data.
     *
     * @return array
     */
    public function getAdditionalAssetData(array $assetData, string $item = '')
    {
        $assetData['asset_id'] = null;
        $assetData['current_asset_status_id'] = null;

        $asset = Asset::where('serial_no', trim($item))->first();
        if ($asset) {
            $assetData['asset_id'] = $asset->id;
            $assetData['current_asset_status_id'] = $asset->asset_status_id;
        }

        return $assetData;
    }

    /**
     * Check csv file difference from the template file.
     *
     * @return string
     */
    public function checkFileDifference(array $csvKeys, array $headerKeys)
    {
        $result = array_diff($csvKeys, $headerKeys);
        $messageString = 'Uploaded file is not match with template file. Please change columns - ';

        $messages = '';

        if (!empty($result)) {
            foreach ($result as $key => $value) {
                $messageString .= $value . ', ';
            }
            $messages = rtrim($messageString, ', ');
        }

        return $messages;
    }

    /**
     * Validate each row.
     *
     * @param array $data
     * @param int   $count
     *
     * @return object
     */
    public function csvValidator($data, $count)
    {
        $validator = Validator::make(
            $data,
            [
                // 'ticket_no' => 'required',
                'po_id' => 'required',
                'location_id' => 'required|exists:locations,id',
                'asset_tag' => 'required|distinct|unique:assets,asset_tag',
                'make_and_model_id' => 'required|exists:make_and_models,id',
                'technical_spec_id' => 'required|exists:technical_specs,id',
                'serial_no' => 'required|unique:assets,serial_no',
                'mobile_number' => 'required|unique:assets,asset_tag',
                'mobile_number' => 'required|unique:assets,serial_no',
                'lease_start_date' => ['required_if:asset_type_id,4', 'nullable', 'date_format:' . config('date.formats.read_date_format')],
                'lease_end_date' => ['required_if:asset_type_id,4', 'nullable', 'date_format:' . config('date.formats.read_date_format')]
            ],
            [
                'ticket_no.required' => 'Line no ' . $count . ' : The ticket # is required.',
                'po_id.required' => 'Line no ' . $count . ' : The PO # is invalid.',
                'location_id.required' => 'Line no ' . $count . ' : The location is required.',
                'location_id.exists' => 'Line no ' . $count . ' : The location does not exist.',
                'asset_tag.required' => 'Line no ' . $count . ' : The asset tag # is required.',
                'mobile_number.required' => 'Line no ' . $count . ' : The mobile number is required.',
                'asset_tag.distinct' => 'Line no ' . $count . ' : The asset tag # has already been taken.',
                'asset_tag.unique' => 'Line no ' . $count . ' : The asset tag # has already been taken.',
                'mobile_number.unique' => 'Line no ' . $count . ' : The mobile number has already been taken.',
                'make_and_model_id.required' => 'Line no ' . $count . ' : The hardware standard is required.',
                'technical_spec_id.required' => 'Line no ' . $count . ' : The technical specs is required.',
                'make_and_model_id.exists' => 'Line no ' . $count . ' : The hardware standard does not exist.',
                'technical_spec_id.exists' => 'Line no ' . $count . ' : The technical specs does not exist.',
                'serial_no.required' => 'Line no ' . $count . ' : The serial # is required.',
                'serial_no.unique' => 'Line no ' . $count . ' : The serial # has already been taken.',
                'lease_start_date.required_if' => 'Line no ' . $count . ' : The lease start date is required for printer.',
                'lease_end_date.required_if' => 'Line no ' . $count . ' : The lease end date is required for printer.',
                'lease_start_date.date_format' => 'Line no ' . $count . ' : The lease start date is incorrect. Use ' . config('date.formats.read_date_format') . ' format.',
                'lease_end_date.date_format' => 'Line no ' . $count . ' : The lease end date is incorrect. Use ' . config('date.formats.read_date_format') . ' format.',

            ]
        );

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

    /**
     * Saves the data to the database and creates a jira ticket for it
     * 
     * @param array $inputData The data to be saved
     * @param int $count The count of the data
     * 
     * @return array The data to be sent to jira
     */
    public function saveData(array $inputData, int $count)
    {
        try {
            $assetStatus = AssetStatusService::whenCreatingAsset();
            $assetStatusId = AssetStatus::where('slug', $assetStatus)->first()->id;

            $jiraData = [];
            $user = User::find(Auth::id());
            if (!$user) {
                $user = User::where('email', 'support@teqube.com')->first();
            }
            // dd($inputData['asset_id'.$count]);
            $data = $this->getData($inputData, $count);
            $mobileData = $this->getMobileNumberData($inputData, $count);
            $data['asset_status_id'] = $assetStatusId;
            $mobileData['asset_status_id'] = $assetStatusId;

            $assetId = Asset::updateorCreate(['asset_tag' => $data['asset_tag']], $data)->id;
            $mobileNumberId = Asset::updateorCreate(['asset_tag' => $mobileData['asset_tag']], $mobileData)->id;

            AssetHistoryService::createAssetCreationHistory($data, $user, $assetId, $count);
            $jiraData[] = AssetHistoryService::getJiraDescription($data, $user, $assetId, $count);

            AssetHistoryService::createAssetCreationHistory($mobileData, $user, $mobileNumberId, $count);
            $jiraData[] = AssetHistoryService::getJiraDescription($mobileData, $user, $mobileNumberId, $count);
            $linked = $this->assetLink($assetId, $mobileNumberId);

            return $jiraData;
        } catch (\Exception) {
            return false;
        }
    }
    /**
     *Create mobile device data array.
     *
     * @return array
     */

    public function getData($inputData, $count)
    {
        $data = json_decode($inputData['asset_id' . $count]);
        $assetData['location_id'] = $data->location_id;
        $assetData['asset_type_id'] = $data->asset_type_id;
        $assetData['asset_tag'] = $data->asset_tag;
        // $assetData['po_id'] = $data->po_id;
        $assetData['po_id'] = $data->po_id;
        $assetData['technical_spec_id'] = $data->technical_spec_id;
        $assetData['serial_no'] = $data->serial_no;
        $assetData['ticket_no'] = $data->ticket_no ?? null;
        $assetData['make_and_model_id'] = $data->make_and_model_id;
        // $assetData['carrier_id'] = $data->carrier_id;
        $assetData['imei'] = $data->imei;
        $assetData['lease_start_date'] = $data->lease_start_date;
        $assetData['lease_end_date'] = $data->lease_end_date;

        if ($data->po_id) {
            $assetData['po_id'] = $data->po_id;
        }

        if ($data->imei == '') {
            $assetData['imei'] = null;
        }
        if ($data->lease_start_date == '') {
            $assetData['lease_start_date'] = null;
        }
        if ($data->lease_end_date == '') {
            $assetData['lease_end_date'] = null;
        }

        $serialNo = $assetData['serial_no'];
        if (($serialNo[0] == 'S') || ($serialNo[0] == 's')) {
            $assetData['serial_no'] = substr($serialNo, 1);
        }

        if ($assetData['imei']) {
            if (substr($assetData['imei'], -3) == '.00') {
                $assetData['imei'] = substr($assetData['imei'], 0, -3);
            }
        }

        return $assetData;
    }

    /**
     *Create mobile number data array.
     *
     * @return array
     */


    public function getMobileNumberData($inputData, $count)
    {
        $data = json_decode($inputData['asset_id' . $count]);
        $mobile_number = AssetType::where('slug', 'mobile_phone_number')->first();
        $assetData['location_id'] = $data->location_id;
        $assetData['asset_type_id'] = $mobile_number->id;
        $assetData['asset_tag'] = $data->mobile_number;
        // $assetData['po_id'] = $data->po_id;
        $assetData['serial_no'] = $data->mobile_number;
        $assetData['ticket_no'] = $data->ticket_no ?? null;
        $assetData['carrier_id'] = $data->carrier_id;
        $assetData['imei'] = $data->imei;
        $assetData['lease_start_date'] = $data->lease_start_date;
        $assetData['lease_end_date'] = $data->lease_end_date;

        if ($data->po_id) {
            $assetData['po_id'] = $data->po_id;
        }

        if ($data->imei == '') {
            $assetData['imei'] = null;
        }
        if ($data->lease_start_date == '') {
            $assetData['lease_start_date'] = null;
        }
        if ($data->lease_end_date == '') {
            $assetData['lease_end_date'] = null;
        }

        $serialNo = $assetData['serial_no'];
        if (($serialNo[0] == 'S') || ($serialNo[0] == 's')) {
            $assetData['serial_no'] = substr($serialNo, 1);
        }

        if ($assetData['imei']) {
            if (substr($assetData['imei'], -3) == '.00') {
                $assetData['imei'] = substr($assetData['imei'], 0, -3);
            }
        }

        return $assetData;
    }

    /**
     *Link mobile and mobile number together.
     *
     * @return array
     */
    public function assetLink($assetId, $mobileId)
    {
        $asset = Asset::find($mobileId);
        $parentAsset = Asset::find($assetId);

        $user = User::find(Auth::id());
        if (!$user) {
            $user = User::where('email', 'support@teqube.com')->first();
        }

        $description = __('history.Linked', [
            'parentAssetId' => $parentAsset->id,
            'childAssetId' => $asset->id,
            'parentAssetname' => $parentAsset->serial_no,
            'childAssetname' => $asset->serial_no,
            'commenttext' => '',
        ]);

        $jiraDescription = __('jira.Linked', [
            'parentAssetId' => $parentAsset->id,
            'childAssetId' => $asset->id,
            'parentAssetname' => $parentAsset->serial_no,
            'childAssetname' => $asset->serial_no,
            'commenttext' => '',
            'username' => $user->first_name . ' ' . $user->last_name,
            'useremail' => $user->email,
        ]);
        if ($parentAsset->ticket_no) {
            $this->ticketManagementService->addComment(Auth::id(), $parentAsset->ticket_no, $jiraDescription, 'Asset Linked');
        }

        $assetParent = Asset::find($assetId);

        $assetHistory = [
            'user_id' => Auth::id(),
            'asset_id' => $asset->id,
            'ticket_no' => $parentAsset->ticket_no,
            'ticket_service_provider' => config('ticket-integration.service'),
            'action' => 'linked',
            'comments' => '',
            'old_parent_asset_id' => $asset->parent_asset_id,
            'new_parent_asset_id' => $assetParent->id,
            'old_location_id' => $asset->location_id,
            'new_location_id' => $assetParent->location_id,
            'old_user_id' => $asset->user_id,
            'new_user_id' => $assetParent->user_id,
            'old_asset_status_id' => $asset->asset_status_id,
            'new_asset_status_id' => $assetParent->asset_status_id,
            'old_value' => $parentAsset->asset_tag,
            'new_value' => $asset->asset_tag,
            'description' => $description,
            '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));

        $asset->update([
            'parent_asset_id' => $assetParent->id,
            'user_id' => $assetParent->user_id,
            'location_id' => $assetParent->location_id,
            'asset_status_id' => $assetParent->asset_status_id,
            'linked_date' => Carbon::now(),
        ]);

        return true;
    }

    /**
     * Create Comments to ticket on crete link
     * @param mixed $ticketData
     * 
     * @return [type]
     */
    public function bulkSendComments($ticketData)
    {
        $this->ticketManagementService->bulkAddComment($ticketData);
    }


    /**
     * After bulk upload attach the uploaded file to the ticket as comment
     * @param mixed $ticketid
     * @param mixed $filePath
     * @param mixed $fileName
     * 
     * @return [type]
     */
    public function attachFiletoTicket($ticketid, $filePath, $fileName)
    {
        if (!$ticketid || !$filePath || !$fileName) {
            return false;
        }
        $this->ticketManagementService->attachActionHistorytoTicket($ticketid, 'Bulk create link mobile number', Auth::user()->id, $filePath, $fileName);
        return true;
    }
}
