<?php

namespace App\Services\DiscoveryTools\WorkspaceOne;

use App\User;

/**
 * Abstract class for all WorkspaceOne Services
 */
abstract class AbstractWorkspaceOneService
{
    abstract public function data();
    abstract public function exportData();

    /**
     * Executing the query
     * @param $devices Query
     * @return Query Result
     */
    public function getOutputData($devices, $order = 'created_at')
    {
        $start = request('start');
        $limit = request('length');
        if ($limit != -1) {
            $devices = $devices->offset($start)->limit($limit);
        }
        $devices->orderBy($order, 'DESC');

        return $devices->get();
    }

    /**
     * Generating data table data from qurey result
     * @param $users Query Result
     * @param $start Starting index
     * @param $data Collection valriable that will return
     *
     * @return array
     */
    public function getReportData($assets, $start, $data = [])
    {
        $parentIndex = $start;

        foreach ($assets as $key => $asset) {
            $parentIndex++;
            $userLink = $asset->user_id ? route('users.show', $asset->user_id) : '#';
            $nestedData = $this->getNestedData($asset, $parentIndex, $userLink);
            $data[] = $nestedData;
        }

        return $data;
    }

    /**
     * Taking the input data
     * @return Array
     */
    public function getInputData()
    {
        return [
            'serial_no'      => isset(request('form')['serial_no']) ? request('form')['serial_no'] : '',
            'asset_type'     => isset(request('form')['asset_type']) ? request('form')['asset_type'] : '',
            'manufacturer'  => isset(request('form')['manufacturer']) ? request('form')['manufacturer'] : '',
            'make_and_model'  => isset(request('form')['make_and_model']) ? request('form')['make_and_model'] : '',
            'model'         => isset(request('form')['model']) ? request('form')['model'] : '',
            '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'] : '',
            'wokspace_one_user' => isset(request('form')['wokspace_one_user']) ? request('form')['wokspace_one_user'] : '',
            'userStatusW'     => isset(request('form')['user_status_w']) ? request('form')['user_status_w'] : '',
            'userDepartmentW'     => isset(request('form')['user_department_w']) ? request('form')['user_department_w'] : '',
            'workLocationW'   => isset(request('form')['work_location_w']) ? request('form')['work_location_w'] : '',
            'ownership'     => isset(request('form')['ownership']) ? request('form')['ownership'] : '',
            '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'] : '',
            'city'          => isset(request('form')['work_location']) ? request('form')['work_location'] : '',
            'startDateFrom' => isset(request('form')['start_date_from']) ? request('form')['start_date_from'] : '',
            'startDateTo'   => isset(request('form')['start_date_to']) ? request('form')['start_date_to'] : '',
            'location'      => isset(request('form')['location']) ? request('form')['location'] : '',
            'platform'      => isset(request('form')['platform']) ? request('form')['platform'] : '',
            'workspace_one_model' => isset(request('form')['workspace_one_model']) ? request('form')['workspace_one_model'] : '',
            'host_name'      => isset(request('form')['host_name']) ? request('form')['host_name'] : '',
            'mac_address'    => isset(request('form')['mac_address']) ? request('form')['mac_address'] : '',
            'status'        => isset(request('form')['status']) ? request('form')['status'] : '',
            'teqtivity_asset'   => isset(request('form')['teqtivity_asset']) ? request('form')['teqtivity_asset'] : '',
            'phone_number'   => isset(request('form')['phone_number']) ? request('form')['phone_number'] : '',
            'carrier'   => isset(request('form')['carrier']) ? request('form')['carrier'] : '',
            'carrier_country'   => isset(request('form')['carrier_country']) ? request('form')['carrier_country'] : '',
            'lockDateFrom'  => isset(request('form')['lock_date_from']) ? request('form')['lock_date_from'] : '',
            'lockDateTo'    => isset(request('form')['lock_date_to']) ? request('form')['lock_date_to'] : '',
            'isLocked'      => isset(request('form')['is_locked']) ? request('form')['is_locked'] : '',
            'imei'      => isset(request('form')['imei']) ? request('form')['imei'] : '',
        ];
    }

    /**
     * Taking the filters for Report generator Export
     *
     * @return Array
     */
    public function getExportInputdata()
    {
        return [

            'serial_no'      => request('serial_no') ??  '',
            'asset_type'     => request('asset_type') ??  '',
            'manufacturer'  => request('manufacturer') ??  '',
            'make_and_model'  => request('make_and_model') ??  '',
            'model'         => request('model') ??  '',
            'user'          => request('user') ??  '',
            'user_status'     => request('user_status') ??  '',
            'work_location'   => request('work_location') ??  '',
            'user_department'     => request('user_department') ?? '',
            'wokspace_one_user' => request('wokspace_one_user') ??  '',
            'userStatusW'     => request('user_status_w') ??  '',
            'workLocationW'   => request('work_location_w') ??  '',
            'userDepartmentW'     => request('user_department_w') ?? '',
            'ownership'     => request('ownership') ??  '',
            'last_seen_from'   => request('last_seen_from') ??  '',
            'last_seen_to'     => request('last_seen_to') ??  '',
            'city'          => request('work_location') ??  '',
            'startDateFrom' => request('start_date_from') ??  '',
            'startDateTo'   => request('start_date_to') ??  '',
            'location'      => request('location') ??  '',
            'platform'      => request('platform') ??  '',
            'workspace_one_model' => request('workspace_one_model') ??  '',
            'host_name'      => request('host_name') ??  '',
            'mac_address'    => request('mac_address') ??  '',
            'status'        => request('status') ?? '',
            'teqtivity_asset'   => request('teqtivity_asset') ?? '',
            'phone_number'   => request('phone_number') ?? '',
            'carrier'   => request('carrier') ?? '',
            'carrier_country'   => request('carrier_country') ?? '',
            'lockDateFrom'  => request('lock_date_from') ?? '',
            'lockDateTo'    => request('lock_date_to') ?? '',
            'isLocked'      => request('is_locked') ??  '',
            'imei'      => request('imei') ??  '',
        ];
    }

    /**
     * making array for display in table
     * @param mixed $asset
     * @param mixed $index
     * @param mixed $userLink
     * 
     * @return [type]
     */
    public function getNestedData($asset, $index, $userLink)
    {

        $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)';
        $serialNo  = $asset->asset ? ("<a href=$assetLink>" . $asset->serial_no . "</a>") : $asset->serial_no;

        $workspaceOneUserLink   = $asset->user_id ? route('users.show', $asset->user_id) : 'javascript:void(0)';
        $workspaceOneUser = $asset->user ? ("<a href=$workspaceOneUserLink>" . $asset->first_name . ' - ' . $asset->email . "</a>") : $asset->first_name . ' - ' . $asset->email;

        $nestedData['id']               = $index;
        $nestedData['serial_no']        = $serialNo;
        $nestedData['asset_type_teqtivity']     = 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['ownership']  = $asset->ownership;
        $nestedData['location_teqtivity']     = optional(optional($asset->asset)->location)->room_name;
        $nestedData['asset_status_teqtivity']     = $asset->asset ? optional($asset->asset->assetStatus)->name : '';

        $nestedData['workspaceone_user_name']  = $asset->first_name . ' ' . $asset->last_name;
        $nestedData['workspaceone_user']  = $workspaceOneUser;
        $nestedData['workspaceone_user_status']  = isset($asset->user) ? (optional($asset->user)->status == 1 ? 'Active' : 'Terminated') : '';
        $nestedData['workspaceone_user_department']  = optional(optional($asset->user)->department)->name;
        $nestedData['workspaceone_user_work_location']  = optional($asset->user)->city;

        $nestedData['teqtivity_user'] = $teqtivityUser ? $teqtivityUser->first_name . ' ' . $teqtivityUser->last_name : '';
        $nestedData['teqtivity_user']   = $teqtivityUser ? ("<a href=$teqtivityUserLink>" . $teqtivityUser->first_name . ' - ' . $teqtivityUser->email . "</a>") : '';
        $nestedData['teqtivity_user_status']  = 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['host_name_workspaceone']        = $asset->host_name;
        $nestedData['mac_address_workspaceone']      = $asset->mac_address;
        $nestedData['imei_workspaceone']             = $asset->imei;

        $nestedData['hardware']            = $asset->model;
        $nestedData['phone_number']     = $asset->asset ? ("<a href=$assetLink>" . $asset->phone_number . "</a>") : $asset->phone_number;
        $nestedData['workspaceone_status'] = $asset->status == 1 ? 'Active' : 'Inactive';
        $nestedData['carrier']      = $asset->carrier;
        $nestedData['carrier_country']  = optional(optional($asset->mobileCarrier)->country)->name;

        $nestedData['lock_date']       = $asset->locked_date ? parse_datetime_from_db_datetime($asset->locked_date) : '';
        $nestedData['is_locked']       = $asset->locked_date ? 'Yes' : 'No';
        $nestedData['last_seen']        = $asset->last_seen ?? '';

        $nestedData['platform']            = $asset->platform;
        $nestedData['create_asset']     = $this->getCreateAssetButton($asset);
        $nestedData['update_asset']     = $this->getUpdateDiscoveryAssetButton($asset->asset, optional($asset->asset)->assetStatus);
        $nestedData['last_modified_date']   = optional($asset->asset)->latestAssetHistory ? optional(optional($asset->asset)->latestAssetHistory)->updated_at : '';
        $nestedData['user_hire_date']       = optional($asset->user)->hire_date;


        return $nestedData;
    }

    /**
     * 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 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 = null)
    {
        setUnlimitedExecutionTimeAndMemoryLimit();

        $teqtivityUser  = optional($asset->asset)->user;


        $nestedData['OS Platform']                      = disableCSVInjection($asset->platform);

        $nestedData['Last Modified Date']   = optional($asset->asset)->latestAssetHistory ? optional(optional($asset->asset)->latestAssetHistory)->updated_at : '';

        $nestedData['Serial # (Workspace One)'] = disableCSVInjection($asset->serial_no);
        $nestedData['Asset Type (Teqtivity)'] = disableCSVInjection(optional(optional($asset->asset)->AssetType)->name);
        $nestedData['Manufacturer (Teqtivity)'] = disableCSVInjection(optional(optional(optional($asset->asset)->makeAndModel)->manufacturer)->name);
        $nestedData['Hardware Standard (Teqtivity)'] = disableCSVInjection(optional(optional($asset->asset)->makeAndModel)->name);

        $nestedData['Ownership (Workspace ONE)'] = disableCSVInjection($asset->ownership);
        $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 (Workspace ONE)'] = disableCSVInjection($asset->first_name . ' - ' . $asset->email);
        $nestedData['User Status (Workspace One)'] = isset($asset->user) ? (disableCSVInjection(optional($asset->user)->status == 1 ? 'Active' : 'Terminated')) : '';
        $nestedData['User Department (Workspace One)'] = disableCSVInjection(optional(optional($asset->user)->department)->name);
        $nestedData['User Work Location (Workspace One)'] = disableCSVInjection(optional($asset->user)->city);

        $nestedData['User (Teqtivity)'] = disableCSVInjection(optional($teqtivityUser)->first_name . ' - ' . optional($teqtivityUser)->email);
        $nestedData['User Status (Teqtivity)'] = isset($asset->asset->user) ? (disableCSVInjection(optional(optional($asset->asset)->user)->status == 1 ? 'Active' : 'Terminated')) : '';
        $nestedData['User Department (Teqtivity)'] = disableCSVInjection(optional(optional(optional($asset->asset)->user)->department)->name);
        $nestedData['User Work Location (Teqtivity)'] = disableCSVInjection(optional(optional($asset->asset)->user)->city);

        $nestedData['Hardware Standard (Workspace ONE)']     = disableCSVInjection($asset->model);
        $nestedData['Host Name (Workspace One)'] = disableCSVInjection($asset->host_name);
        $nestedData['MAC Address (Workspace One)'] = disableCSVInjection($asset->mac_address);
        $nestedData['IMEI (Workspace One)'] = disableCSVInjection($asset->imei);
        $nestedData['Phone Number (Workspace One)'] = disableCSVInjection($asset->phone_number);
        $nestedData['Carrier (Workspace One)'] = disableCSVInjection($asset->carrier);
        $nestedData['Carrier Country (Workspace One)'] = disableCSVInjection(optional(optional($asset->mobileCarrier)->country)->name);
        $nestedData['Lock Date'] = disableCSVInjection($asset->locked_date ? parse_datetime_from_db_datetime($asset->locked_date) : '');
        $nestedData['Is Locked'] = disableCSVInjection($asset->locked_date ? 'Yes' : 'No');
        $nestedData['Last Seen'] = disableCSVInjection($asset->last_seen ?? '');



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

    /**
     * Filer the results based on filters
     *
     * @param $assets DB Query
     * @param Array $inputData   Filter data
     *
     * @return Query
     */
    public function filterDevices($assets, $inputData)
    {

        $assets     = $this->repository->filterRelation($assets, 'air_watches.serial_no', $inputData['serial_no']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.model', $inputData['model']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.email', $inputData['wokspace_one_user']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.ownership', $inputData['ownership']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.platform', $inputData['platform']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.model', $inputData['workspace_one_model']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.host_name', $inputData['host_name']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.mac_address', $inputData['mac_address']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.phone_number', $inputData['phone_number']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.carrier', $inputData['carrier']);
        $assets     = $this->repository->filterRelation($assets, 'air_watches.imei', $inputData['imei']);

        $assets     = $this->repository->filterWithUserFields($assets, 'status', $inputData['userStatusW']);
        $assets     = $this->repository->filterWithUserFields($assets, 'city', $inputData['workLocationW']);
        $assets     = $this->repository->filterWithUserFields($assets, 'department_id', $inputData['userDepartmentW']);

        $assets     = $this->repository->filterWithUserFields($assets, 'hire_date', $inputData['startDateFrom']);
        $assets     = $this->repository->filterWithUserFields($assets, 'hire_date', $inputData['startDateTo']);

        $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->filterWithAssetMakeAndModelFields($assets, 'manufacturer_id', $inputData['manufacturer']);

        $assets     = $this->repository->filterWithAssetFields($assets, 'user_id', $inputData['user']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_status_id', $inputData['status']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_type_id', $inputData['asset_type']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'make_and_model_id', $inputData['make_and_model']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'location_id', $inputData['location']);
        $assets     = $this->repository->filterWithLastModifiedDate($assets, $inputData['last_seen_from'], $inputData['last_seen_to'], 'asset.latestAssetHistory');
        $assets     = $this->repository->filterWithLastSeen($assets, $inputData['last_seen_from'], $inputData['last_seen_to']);

        $assets     = $this->repository->filterWithLockDate($assets, $inputData['lockDateFrom'], $inputData['lockDateTo']);
        $assets     = $this->repository->filterWithLockedStatus($assets, $inputData['isLocked']);

        $assets     = $this->repository->filterWithCarrierCountry($assets, $inputData['carrier_country']);

        $assets     = $this->repository->filterTeqtivityAssetOrNot($assets, $inputData['teqtivity_asset']);

        return $assets;
    }

    /**
     * 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 '';
    }

    /**
     * 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 '';
    }
}
