<?php

namespace App\Services\DiscoveryTools\Chromebook;

use App\Models\Asset;
use App\User;

abstract class AbstractChromebookService
{
    abstract public function data();
    abstract public function exportData();


    /**
     * Taking the input data
     * @return Array
     */
    public function getInputData()
    {
        return [

            'serial_no'             => isset(request('form')['serial_no']) ? request('form')['serial_no'] : '',
            'host_name'             => isset(request('form')['host_name']) ? request('form')['host_name'] : '',
            'mac_address'           => isset(request('form')['mac_address']) ? request('form')['mac_address'] : '',
            'model'                => isset(request('form')['model']) ? request('form')['model'] : '',
            'asset_type'            => isset(request('form')['asset_type']) ? request('form')['asset_type'] : '',
            'asset_status'            => isset(request('form')['asset_status']) ? request('form')['asset_status'] : '',
            'manufacturer'         => isset(request('form')['manufacturer']) ? request('form')['manufacturer'] : '',
            'make_and_model'         => isset(request('form')['make_and_model']) ? request('form')['make_and_model'] : '',
            'teqtivity_asset'       => isset(request('form')['teqtivity_asset']) ? request('form')['teqtivity_asset'] : '',
            'location_id'          => isset(request('form')['room_name']) ? request('form')['room_name'] : '',
            'asset_status_id'      => isset(request('form')['asset_status']) ? request('form')['asset_status'] : '',

            'chromebook_user'      => isset(request('form')['chromebook_user']) ? request('form')['chromebook_user'] : '',
            'userStatus_c'         => isset(request('form')['user_status_c']) ? request('form')['user_status_c'] : '',
            'userDepartment_c'     => isset(request('form')['user_department_c']) ? request('form')['user_department_c'] : '',
            'workLocation_c'       => isset(request('form')['work_location_c']) ? request('form')['work_location_c'] : '',

            'user'                 => isset(request('form')['user']) ? request('form')['user'] : '',
            'user_status'           => isset(request('form')['user_status']) ? request('form')['user_status'] : '',
            'user_department'       => isset(request('form')['user_department']) ? request('form')['user_department'] : '',
            'work_location'         => isset(request('form')['work_location']) ? request('form')['work_location'] : '',

            'last_seen_from'         => isset(request('form')['last_seen_from']) ? request('form')['last_seen_from'] : '',
            'last_seen_to'           => isset(request('form')['last_seen_to']) ? request('form')['last_seen_to'] : '',


            'platform'             => isset(request('form')['platform']) ? request('form')['platform'] : '',
            'phone_number'          => isset(request('form')['phone_number']) ? request('form')['phone_number'] : '',

            'imei'      => isset(request('form')['imei']) ? request('form')['imei'] : '',
            'carrier'   => isset(request('form')['carrier']) ? request('form')['carrier'] : '',
            'carrier_country'   => isset(request('form')['carrier_country']) ? request('form')['carrier_country'] : '',

        ];
    }

    /**
     * Taking the filters for  export
     *
     * @return Array
     */
    public function getExportInputData()
    {
        return [
            'serial_no'             => request('serial_no') ??  '',
            'host_name'             => request('host_name') ??  '',
            'mac_address'           => request('mac_address') ??  '',
            'model'                => request('model') ??  '',
            'asset_type'            => request('asset_type') ??  '',
            'asset_status'          => request('asset_status') ?? '',
            'manufacturer'         => request('manufacturer') ??  '',
            'make_and_model'         => request('make_and_model') ??  '',
            'teqtivity_asset'       => request('teqtivity_asset') ??  '',
            'location_id'          => request('room_name') ??  '',
            'asset_status_id'      => request('asset_status') ??  '',

            'chromebook_user'      => request('chromebook_user') ??  '',
            'userStatus_c'         => request('user_status_c') ??  '',
            'userDepartment_c'     => request('user_department_c') ??  '',
            'workLocation_c'       => request('work_location_c') ??  '',

            'user'                 => request('user') ??  '',
            'user_status'           => request('user_status') ??  '',
            'user_department'       => request('user_department') ??  '',
            'work_location'         => request('work_location') ??  '',

            'last_seen_from'         => request('last_seen_from') ??  '',
            'last_seen_to'           => request('last_seen_to') ??  '',


            'platform'             => request('platform') ??  '',
            'phone_number'          => request('phone_number') ??  '',

            'imei'          => request('imei') ??  '',
            'carrier'   => request('carrier') ?? '',
            'carrier_country'   => request('carrier_country') ?? '',
        ];
    }

    /**
     * Filer the results based on filters
     * 
     * @param $assets DB Query
     * @param Array $inputData   Filter data
     * 
     * @return Query
     */
    public function filter($assets, $inputData)
    {
        $assets     = $assets->RelationData($inputData['serial_no'], 'chromebooks.serial_no');
        $assets     = $assets->RelationData($inputData['model'], 'chromebooks.model');
        $assets     = $assets->RelationData($inputData['chromebook_user'], 'chromebooks.email');
        $assets     = $assets->RelationData($inputData['model'], 'chromebooks.model');
        $assets     = $assets->RelationData($inputData['chromebook_user'], 'chromebooks.email');
        $assets     = $assets->RelationData($inputData['host_name'], 'chromebooks.host_name');
        $assets     = $assets->RelationData($inputData['mac_address'], 'chromebooks.mac_address');
        $assets     = $assets->RelationData($inputData['platform'], 'chromebooks.platform');


        $assets     = $this->repository->filterWithAssetMakeAndModelFields($assets, 'manufacturer_id', $inputData['manufacturer']);
        $assets     = $this->repository->filterWithLastSync($assets, $inputData['last_seen_from'], $inputData['last_seen_to']);

        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_status_id', $inputData['asset_status']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'make_and_model_id', $inputData['make_and_model']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'location_id', $inputData['location_id']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'user_id', $inputData['user']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_type_id', $inputData['asset_type']);

        $assets     = $this->repository->filterWithUserFields($assets, 'status', $inputData['userStatus_c']);
        $assets     = $this->repository->filterWithUserFields($assets, 'city', $inputData['workLocation_c']);
        $assets     = $this->repository->filterWithUserFields($assets, 'department_id', $inputData['userDepartment_c']);

        $assets     = $this->repository->filterWithTeqtivityUserFields($assets, 'department_id', $inputData['user_department']);
        $assets     = $this->repository->filterWithTeqtivityUserFields($assets, 'status', $inputData['user_status']);
        $assets     = $this->repository->filterWithTeqtivityUserFields($assets, 'city', $inputData['work_location']);
        $assets     = $this->repository->filterTeqtivityAssetOrNot($assets, $inputData['teqtivity_asset']);


        return $assets;
    }

    /**
     * Executing the query
     * @param $users Query
     * @return Query Result
     */
    public function getOutputData($assets)
    {
        $start = request('start');
        $limit = request('length');
        if ($limit != -1) {
            $assets = $assets->skip($start)
                ->take($limit);
        }

        $assets = $assets->orderBy('id', 'desc');
        return $assets->get();
    }

    /**
     * Generating data to export
     * @param $assets Query Result
     * @param $start Starting index
     * @param $data Collection valriable that will return
     * @param $requiredColumns colums to be shown in export file

     * @return array
     */
    public function getReportData($users, $start, $data)
    {
        $parentIndex = $start;

        foreach ($users as $key => $user) {
            $parentIndex++;

            $nestedData = $this->getNestedData($user, $parentIndex);
            $data[] = $nestedData;
        }

        return $data;
    }

    /**
     * Creating array for Data table data
     * @param $asset Query Result
     * @param $index Starting index
     *
     * @return array
     */
    public function getNestedData($asset, $index)
    {
        $chromebookUserLink   = $asset->user_id ? route('users.show', $asset->user_id) : 'javascript:void(0)';
        $assetLink  = $asset->asset ? route('assets.show', $asset->asset->id) : 'javascript:void(0)';
        $teqtivityUser     = optional($asset->asset)->user;

        $teqtivityUserLink  = $teqtivityUser ? route('users.show', $teqtivityUser->id) : 'javascript:void(0)';

        if (!empty($asset->last_sync) && $asset->last_sync != '0000-00-00' && $asset->last_sync != '11/30/-0001 12:00:00 AM' && $asset->last_sync != '11/30/-0001 00:00:00') {
            $last_sync = $asset->last_sync;
        } else {
            $last_sync = '';
        }

        $nestedData['id']               = $index;
        $nestedData['serial_no']        = "<a href=$assetLink>$asset->serial_no</a>";
        $nestedData['asset_type'] = optional(optional($asset->asset)->assetType)->name;
        $nestedData['manufacturer_teqtivity']     = optional(optional(optional($asset->asset)->makeAndModel)->manufacturer)->name;
        $nestedData['hardware_teqtivity']            = optional(optional($asset->asset)->makeAndModel)->name;
        $nestedData['teqtivity_asset'] = $asset->asset_id ? 'Yes' : 'No';
        $nestedData['location_teqtivity']     = optional(optional($asset->asset)->location)->room_name;
        $nestedData['asset_status_teqtivity']     = $asset->asset ? optional($asset->asset->assetStatus)->name : '';

        $nestedData['chromebook_user']  = "<a href=$chromebookUserLink>" . $asset->email . "</a>";
        $nestedData['chromebook_user_status']  = isset($asset->user) ? (optional($asset->user)->status == 1 ? 'Active' : 'Terminated') : '';
        $nestedData['chromebook_user_department']  = optional(optional($asset->user)->department)->name;
        $nestedData['chromebook_user_work_location']  = optional($asset->user)->city;

        $nestedData['teqtivity_user']   = $teqtivityUser ? "<a href=$teqtivityUserLink>" . $teqtivityUser->first_name . ' - ' . $teqtivityUser->email . "</a>" : '';
        $nestedData['teqtivity_user_status']  = isset($asset->asset->user) ? (optional(optional($asset->asset)->user)->status == 1 ? 'Active' : 'Terminated') : '';
        $nestedData['teqtivity_user_department']  = optional(optional(optional($asset->asset)->user)->department)->name;
        $nestedData['teqtivity_user_work_location']  = optional(optional($asset->asset)->user)->city;

        $nestedData['hardware_chromebook']            = $asset->model;

        $nestedData['host_name_chromebook']        = $asset->host_name;
        $nestedData['mac_address_chromebook']      = $asset->mac_address;
        $nestedData['last_sync']        = $last_sync ?? '';
        $nestedData['platform']           = $asset->platform;

        $nestedData['last_modified_date']   = optional(optional($asset->asset)->latestAssetHistory)->updated_at;

        $nestedData['create_asset']     = $this->getCreateAssetButton($asset);
        $nestedData['update_asset']     = $this->getUpdateDiscoveryAssetButton($asset->asset, optional($asset->asset)->assetStatus);

        return $nestedData;
    }

    /**
     * Generating data to export
     * @param $assets Query Result
     * @param $start Starting index
     * @param $data Collection valriable that will return
     *
     * @return array
     */
    public function getReportExportData($assets, $start, $data, $requiredColumns)
    {
        $parentIndex = $start;

        foreach ($assets as $key => $asset) {
            $parentIndex++;
            $nestedData = $this->getExportNestedData($asset, $requiredColumns);
            $data[] = $nestedData;
        }
        return $data;
    }

    /**
     * Creating array for export data
     * @param $asset Query Result
     * @param $requiredColumns columns to be added in export file
     *
     * @return array
     */
    public function getExportNestedData($asset,  $requiredColumns)
    {
        $teqtivityUser  = optional($asset->asset)->user;

        if (!empty($asset->last_sync) && $asset->last_sync != '0000-00-00' && $asset->last_sync != '11/30/-0001 12:00:00 AM' && $asset->last_sync != '11/30/-0001 00:00:00') {
            $last_sync = $asset->last_sync;
        } else {
            $last_sync = '';
        }

        $nestedData['Serial # (Chrome Devices)'] = disableCSVInjection($asset->serial_no);
        $nestedData['Asset Type (Teqtivity)'] = optional(optional($asset->asset)->assetType)->name;
        $nestedData['Manufacturer (Teqtivity)'] = optional(optional(optional($asset->asset)->makeAndModel)->manufacturer)->name;
        $nestedData['Hardware Standard (Teqtivity)'] = disableCSVInjection(optional(optional($asset->asset)->makeAndModel)->name);
        $nestedData['Asset Location (Teqtivity)'] = disableCSVInjection(optional(optional($asset->asset)->location)->room_name);
        $nestedData['Asset Status (Teqtivity)'] = disableCSVInjection($asset->asset ? optional($asset->asset->AssetStatus)->name : '');
        $nestedData['User (Chrome Devices)'] = disableCSVInjection($asset->email);
        $nestedData['User Status (Chrome Devices)'] = disableCSVInjection(isset($asset->user) ? (optional($asset->user)->status == 1 ? 'Active' : 'Terminated') : '');
        $nestedData['User Department (Chrome Devices)'] = disableCSVInjection(optional(optional($asset->user)->department)->name);
        $nestedData['User Work Location (Chrome Devices)'] = disableCSVInjection(optional($asset->user)->city);
        $nestedData['User (Teqtivity)'] = disableCSVInjection($teqtivityUser ? $teqtivityUser->first_name . ' - ' . $asset->email : '');
        $nestedData['User Status (Teqtivity)'] = disableCSVInjection(isset($asset->asset->user) ? (optional(optional($asset->asset)->user)->status == 1 ? 'Active' : 'Terminated') : '');
        $nestedData['User Department (Chrome Devices)'] = disableCSVInjection(optional(optional(optional($asset->asset)->user)->department)->name);
        $nestedData['User Work Location (Chrome Devices)'] = disableCSVInjection(optional(optional($asset->asset)->user)->city);
        $nestedData['Hardware Standard (Chrome Devices)'] = disableCSVInjection($asset->model);
        $nestedData['Host Name (Chrome Devices)'] = disableCSVInjection($asset->host_name);
        $nestedData['MAC Address (Chrome Devices)'] = disableCSVInjection($asset->mac_address);
        $nestedData['Last Seen'] = disableCSVInjection($last_sync ?? '');


        foreach ($requiredColumns as $key => $column) {
            $data[$column] =  $nestedData[$column];
        }
        return $data;
    }

    /**
     * Set up Create Asset Button
     * @param mixed $asset
     */
    public function getCreateAssetButton($asset)
    {
        if (auth()->user()->can('IT Assets Edit') && $asset) {
            return '<a href="javascript:;" data-asset="' . $asset->id . '" data-asset-serial="' . $asset->serial_no . '" class="btn btn-primary btn-sm create-asset">Create Asset</a>';
        }
        return '';
    }

    /**
     * Update asset button for the user Discrepancy Report
     *
     * @param $asset App\Models\Asset
     */
    public function getUpdateDiscoveryAssetButton($asset, $assetStatus)
    {
        if (auth()->user()->can('IT Assets Edit') && $asset) {
            return '<a href="javascript:;" data-asset="' . $asset->id . '" data-asset-serial="' . $asset->serial_no . '" data-asset-current-status="' . optional($assetStatus)->slug . '" data-parent-asset="' . $asset->parent_asset_id . '" class="btn btn-primary btn-sm update-discrepancy-asset">Update Asset</a>';
        }
        return '';
    }
}
