<?php

namespace App\Services\DiscoveryTools\MobileIron;

use App\User;
use App\Repositories\DiscoveryTools\MobileIronRepository;

abstract class AbstractMobileIronService
{

    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'] : '',
            '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'] : '',
            'mobile_iron_user'    => isset(request('form')['mobile_iron_user']) ? request('form')['mobile_iron_user'] : '',
            'teq_user'              => isset(request('form')['teq_user']) ? request('form')['teq_user'] : '',
            'location'              => isset(request('form')['location']) ? request('form')['location'] : '',
            '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'] : '',
            'userStatusM'         => isset(request('form')['user_status_m']) ? request('form')['user_status_m'] : '',
            'userDepartmentM'     => isset(request('form')['user_department_m']) ? request('form')['user_department_m'] : '',
            'workLocationM'       => isset(request('form')['work_location_m']) ? request('form')['work_location_m'] : '',
            'ownership'           => isset(request('form')['ownership']) ? request('form')['ownership'] : '',
            'last_seen_from'        => isset(request('form')['last_checkin_from']) ? request('form')['last_checkin_from'] : '',
            'last_seen_to'          => isset(request('form')['last_checkin_to']) ? request('form')['last_checkin_to'] : '',
            'city'                => isset(request('form')['work_location']) ? request('form')['work_location'] : '',
            'firstCheckinFrom'    => isset(request('form')['first_checkin_from']) ? request('form')['first_checkin_from'] : '',
            'firstCheckinTo'      => isset(request('form')['first_checkin_to']) ? request('form')['first_checkin_to'] : '',
            'enrolledDateFrom'    => isset(request('form')['enrolled_date_from']) ? request('form')['enrolled_date_from'] : '',
            'enrolledDateTo'      => isset(request('form')['enrolled_date_to']) ? request('form')['enrolled_date_to'] : '',
            'platform'            => isset(request('form')['platform']) ? request('form')['platform'] : '',
            '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 Mobile number 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') ?? '',
            'mobile_iron_user'    => request('mobile_iron_user') ?? '',
            'teq_user'              => request('teq_user') ?? '',
            'location'              => request('location') ?? '',
            'user_status'          => request('user_status') ?? '',
            'user_department'      => request('user_department') ?? '',
            'work_location'        => request('work_location') ?? '',
            'userStatusM'         => request('user_status_m') ?? '',
            'userDepartmentM'     => request('user_department_m') ?? '',
            'workLocationM'       => request('work_location_m') ?? '',
            'ownership'           => request('ownership') ?? '',
            'last_seen_from'        => request('last_checkin_from') ?? '',
            'last_seen_to'          => request('last_checkin_to') ?? '',
            'city'                => request('work_location') ?? '',
            'firstCheckinFrom'    => request('first_checkin_from') ?? '',
            'firstCheckinTo'      => request('first_checkin_to') ?? '',
            'enrolledDateFrom'    => request('enrolled_date_from') ?? '',
            'enrolledDateTo'      => request('enrolled_date_to') ?? '',
            'location'            => request('location') ?? '',
            'platform'            => request('platform') ?? '',
            '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') ?? '',

        ];
    }

    /**
     * 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'], 'mobile_irons.serial_no');
        $assets     = $assets->RelationData($inputData['model'], 'model');
        $assets     = $assets->RelationData($inputData['mobile_iron_user'], 'email');
        $assets     = $assets->RelationData($inputData['mac_address'], 'mac_address');
        $assets     = $assets->RelationData($inputData['phone_number'], 'phone_number');
        $assets     = $assets->RelationData($inputData['carrier'], 'carrier');
        $assets     = $assets->RelationData($inputData['imei'], 'imei');
        $assets     = $assets->RelationData($inputData['ownership'], 'ownership');


        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_type_id', $inputData['asset_type']);
        $assets     = $this->repository->filterWithAssetMakeAndModelFields($assets, 'manufacturer_id', $inputData['manufacturer']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'make_and_model_id', $inputData['make_and_model']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'user_id', $inputData['teq_user']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'location_id', $inputData['location']);


        $assets     = $this->repository->filterWithUserFields($assets, 'status', $inputData['userStatusM']);
        $assets     = $this->repository->filterWithUserFields($assets, 'city', $inputData['workLocationM']);
        $assets     = $this->repository->filterWithUserFields($assets, 'department_id', $inputData['userDepartmentM']);

        $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->filterWithLastCheckin($assets, $inputData['last_seen_from'], $inputData['last_seen_to']);

        $assets     = $this->repository->filterWithUserFields($assets, 'status', $inputData['user_status']);
        $assets     = $this->repository->filterWithUserFields($assets, 'city', $inputData['work_location']);

        $assets     = $this->repository->filterWithAssetFields($assets, 'asset_status_id', $inputData['status']);
        $assets     = $this->repository->filterWithAssetFields($assets, 'location_id', $inputData['location']);

        $assets     = $this->repository->filterWithFirstCheckin($assets, $inputData['firstCheckinFrom'], $inputData['firstCheckinTo']);
        $assets     = $this->repository->filterWithEnrolledDate($assets, $inputData['enrolledDateFrom'], $inputData['enrolledDateTo']);


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

        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 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($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
     * @param $email route for user details
     *
     * @return array
     */
    public function getNestedData($asset, $index)
    {

        $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;

        $mobileIronUserLink   = $asset->user_id ? route('users.show', $asset->user_id) : 'javascript:void(0)';
        $mobileIronUser = $asset->user ? ("<a href=$mobileIronUserLink>" . $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['mobileIron_user_name']  = $asset->first_name . ' ' . $asset->last_name;
        $nestedData['mobileIron_user']  = $mobileIronUser;
        $nestedData['mobileIron_user_status']  = isset($asset->user) ? (optional($asset->user)->status == 1 ? 'Active' : 'Terminated') : '';
        $nestedData['mobileIron_user_department']  = optional(optional($asset->user)->department)->name;
        $nestedData['mobileIron_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['mac_address_mobileIron']      = $asset->mac_address;
        $nestedData['imei_mobileIron']             = $asset->imei;

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

        $nestedData['last_seen']        = $asset->last_checkin ?? '';

        $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, $parentIndex, $requiredColumns);
            $data[] = $nestedData;
        }
        return $data;
    }

    /**
     * Creating array for export data
     * @param $asset Query Result
     * @param $index Starting index
     * @param $requiredColumns columns to be added in export file
     *
     * @return array
     */
    public function getExportNestedData($asset, $index, $requiredColumns)
    {
        setUnlimitedExecutionTimeAndMemoryLimit();

        $teqtivityUser  = User::find($asset->asset ? $asset->asset->user_id : 0);


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

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

        $nestedData['Serial # (MobileIron)'] = 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 (MobileIron)'] = 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 (MobileIron)'] = disableCSVInjection($asset->first_name . ' - ' . $asset->email);
        $nestedData['User Status (MobileIron)'] = isset($asset->user) ? (disableCSVInjection(optional($asset->user)->status == 1 ? 'Active' : 'Terminated')) : '';
        $nestedData['User Department (MobileIron)'] = disableCSVInjection(optional(optional($asset->user)->department)->name);
        $nestedData['User Work Location (MobileIron)'] = 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 (MobileIron)']     = disableCSVInjection($asset->model);
        $nestedData['Host Name (MobileIron)'] = disableCSVInjection($asset->host_name);
        $nestedData['MAC Address (MobileIron)'] = disableCSVInjection($asset->mac_address);
        $nestedData['IMEI (MobileIron)'] = disableCSVInjection($asset->imei);
        $nestedData['Phone Number (MobileIron)'] = disableCSVInjection($asset->phone_number);
        $nestedData['Carrier (MobileIron)'] = disableCSVInjection($asset->carrier);
        $nestedData['Carrier Country (MobileIron)'] = disableCSVInjection(optional(optional($asset->mobileCarrier)->country)->name);
        $nestedData['Lock Date'] = disableCSVInjection($asset->locked_date ?? '');
        $nestedData['Is Locked'] = disableCSVInjection($asset->locked_date ? 'Yes' : 'No');
        $nestedData['Last Seen'] = disableCSVInjection($asset->last_checkin ?? '');


        foreach ($requiredColumns as $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 '';
    }

    /**
     * Retrieves the update discovery asset button.
     *
     * @param mixed $asset The asset object.
     * @param mixed $assetStatus The asset status object.
     * @return string The HTML code for the update asset button.
     */
    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 '';
    }
}
