<?php

namespace App\Services;

use App\Models\Asset;
use App\User;
use App\Models\Location;
use App\Models\Chromebook;
use App\Models\AirWatch;
use App\Models\AirWatchPhoneNumber;
use App\Models\Department;
use App\Models\IntuneComputer;
use DB;

class SearchAsset
{

    public function getAssetFilterFields($search, $type)
    {
        if (in_array($type, ['po_id', 'ticket_no'])) {
            $res = Asset::distinct()->select("$type")->where("$type", 'like', $search . '%')->limit(15)->get();
            $result = $res->mapWithKeys(function ($item, $key) use ($type) {
                return [
                    $key => [
                        'id' => $item[$type],
                        'text' => $item[$type],
                    ]
                ];
            });

            return $result;
        }

        if ($type == 'employee_id') {
            $res = User::distinct()->select('employee_id')->where('employee_id', 'like', $search . '%')->limit(15)->get();
            $result = $res->mapWithKeys(function ($item, $key) {
                return [
                    $key => [
                        'id' => $item['employee_id'],
                        'text' => $item['employee_id'],
                    ],
                ];
            });

            return $result;
        }

        if (in_array($type, array('asset_value', 'asset_original_value'))) {
            return $this->filterAssetValue($search);
        }

        if (in_array($type, array('depreciated_value', 'asset_deprecated_value'))) {
            return $this->filterAssetDepreciatedValue($search);
        }

        if ($type == 'email') {
            $res = User::distinct()->select('email')->where('email', 'like', $search . '%')->limit(15)->get();
            $result = $res->mapWithKeys(function ($item, $key) {
                return [
                    $key => [
                        'id' => $item['email'],
                        'text' => $item['email'],
                    ],
                ];
            });

            return $result;
        }

        $res = Asset::select("$type")->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    /**
     * Filter asset value based on search criteria.
     *
     * @param mixed $search search criteria
     * @return \Illuminate\Support\Collection
     */
    private function filterAssetValue($search)
    {
        $res = Asset::select(DB::raw('(CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END) AS asset_value'))
            ->leftJoin('technical_specs', 'assets.technical_spec_id', '=', 'technical_specs.id')
            ->whereNotNull(DB::raw('(CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END)')) // Exclude null values
            ->where(DB::raw('(CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END)'), '<>', 0) // Exclude zeros
            ->where(DB::raw('(CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END)'), 'like', $search . '%')
            ->orderBy('asset_value')
            ->groupBy('asset_value')
            ->limit(15)
            ->get();
        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['asset_value'],
                    'text' => round($item['asset_value']),
                ],
            ];
        });

        return $result;
    }

    /**
     * Filter the asset's depreciated value based on the search parameter.
     *
     * @param string $search The search parameter
     * @return \Illuminate\Support\Collection
     */
    private function filterAssetDepreciatedValue($search)
    {
        $res = Asset::select(DB::raw('DISTINCT ROUND((CASE
                WHEN (FLOOR((DATEDIFF(NOW(), assets.created_at)) / 365)) > 0 THEN
                    ROUND((COALESCE(assets.asset_original_value, technical_specs.original_value)) -
                        (((COALESCE(assets.asset_original_value, technical_specs.original_value)) * 20) / 100) *
                        (FLOOR((DATEDIFF(NOW(), assets.created_at)) / 365)), 2)
                ELSE
                    (CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END)
                END)) AS asset_depreciated_value'))
            ->leftJoin('technical_specs', 'assets.technical_spec_id', '=', 'technical_specs.id')
            ->where(DB::raw('(CASE
                WHEN (FLOOR((DATEDIFF(NOW(), assets.created_at)) / 365)) > 0 THEN
                    ROUND((COALESCE(assets.asset_original_value, technical_specs.original_value)) -
                    (((COALESCE(assets.asset_original_value, technical_specs.original_value)) * 20) / 100) *
                    (FLOOR((DATEDIFF(NOW(), assets.created_at)) / 365)), 2)
                ELSE
                    (CASE WHEN assets.asset_original_value IS NULL THEN technical_specs.original_value ELSE assets.asset_original_value END)
                END)'), 'like', $search . '%')
            ->groupBy('asset_depreciated_value')
            ->orderBy('asset_depreciated_value')
            ->limit(15);
        $res = $res->get();
        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['asset_depreciated_value'],
                    'text' => $item['asset_depreciated_value'],
                ],
            ];
        });

        return $result;
    }

    /**
     * A description of the entire PHP function.
     *
     * @param datatype $search description
     * @param datatype $type description
     * @return Some_Return_Value
     */
    public function getFilterUserDepartmentFields($search, $type = 'name')
    {
        $res = Department::select("id", "$type")->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    public function getFilterUserFields($search)
    {
        $res = User::superAdmin()->active()
            ->select('id', 'first_name', 'last_name', 'email')
            ->orderBy('first_name', 'asc')
            ->where(function ($query) use ($search) {
                $query->where('first_name', 'like', $search . '%')
                    ->orWhere('last_name', 'like', $search . '%')
                    ->orWhereRaw("CONCAT(`first_name`, ' ', `last_name`) like ?", [$search . '%'])
                    ->orWhere('email', 'like', $search . '%')
                    ->orWhere('employee_id', 'like', $search . '%');
            })
            ->limit(15)->get();
        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item['first_name'] . ' ' . $item['last_name'] . ' - ' . $item['email'],
                ]
            ];
        });

        return $result;
    }

    public function getFilterAllUserFields($search)
    {
        $res = User::superAdmin()
            ->select('id', 'first_name', 'last_name', 'email')
            ->orderBy('first_name', 'asc')
            ->where(function ($query) use ($search) {
                $query->where('first_name', 'like', $search . '%')
                    ->orWhere('last_name', 'like', $search . '%')
                    ->orWhereRaw("CONCAT(`first_name`, ' ', `last_name`) like ?", [$search . '%'])
                    ->orWhere('email', 'like', $search . '%');
            })
            ->limit(15)->get();
        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item['first_name'] . ' ' . $item['last_name'] . ' - ' . $item['email'],
                ]
            ];
        });

        return $result;
    }

    public function getFilterAssignedUserFields($search)
    {
        $res = User::superAdmin()->active()
            ->select('id', 'first_name', 'last_name', 'email')
            ->orderBy('first_name', 'asc')
            ->where(function ($query) use ($search) {
                $query->where('first_name', 'like', $search . '%')
                    ->orWhere('last_name', 'like', $search . '%')
                    ->orWhereRaw("CONCAT(`first_name`, ' ', `last_name`) like ?", [$search . '%'])
                    ->orWhere('email', 'like', $search . '%');
            })
            ->limit(15)->get();
        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item['first_name'] . ' ' . $item['last_name'] . ' - ' . $item['email'],
                ]
            ];
        });

        return $result;
    }

    public function getFilterLocationFields($search, $type)
    {
        if ($type == 'building') {
            $res = Location::distinct()->select($type)->where("$type", 'like', '%' . $search . '%')->active()->orderBy("$type")->get();
            $result = $res->mapWithKeys(function ($item, $key) use ($type) {
                return [
                    $key => [
                        'id' => $item[$type],
                        'text' => $item[$type],
                    ]
                ];
            });

            return $result;
        }

        if ($type == 'city') {
            $res = User::distinct()->select("$type")->where("$type", 'like', '%' . $search . '%')->orderBy("$type")->get();
            $result = $res->mapWithKeys(function ($item, $key) use ($type) {
                return [
                    $key => [
                        'id' => $item[$type],
                        'text' => $item[$type],
                    ]
                ];
            });

            return $result;
        }

        $res = Location::where("$type", 'like', '%' . $search . '%')->active()->orderBy("$type")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    /** Get the locations based on relation
     * @param Request $request
     *
     * @return [type]
     */
    public function getFilterLocationFieldsWithRelation($search, $field = 'room_name', $relation = 'installLocations')
    {
        $res = Location::$relation()->where("$field", 'like', '%' . $search . '%')->active()->orderBy("$field")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($field) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$field],
                ]
            ];
        });

        return $result;
    }

    /** Get the storage locations based on relation
     * @param Request $request
     *
     * @return [type]
     */
    public function getFilterStorageLocation($search, $field = 'room_name')
    {
        $res = Location::Warehouses()->where("$field", 'like', '%' . $search . '%')->active()->orderBy("$field")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($field) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$field] . ($item['is_freeze'] == 1 ? ' (Room is frozen for cycle count)' : ''),
                    'disabled' => $item['is_freeze'] == 1 ? 'disabled' : '',
                ]
            ];
        });

        return $result;
    }

    /** Get the install locations based on relation
     * @param Request $request
     *
     * @return [type]
     */
    public function getFilterInstallLocation($search, $field = 'room_name')
    {
        $res = Location::withoutwarehouse()->where("$field", 'like', '%' . $search . '%')->active()->orderBy("$field")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($field) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$field] . ($item['is_freeze'] == 1 ? ' (Room is frozen for cycle count)' : ''),
                    'disabled' => $item['is_freeze'] == 1 ? 'disabled' : '',
                ]
            ];
        });

        return $result;
    }

    /** Get the install and building locations based on relation
     * @param Request $request
     *
     * @return [type]
     */
    public function getFilterInstallAndBuildingLocations($search, $field = 'room_name')
    {
        $res = Location::InstallBuildings()->where("$field", 'like', '%' . $search . '%')->active()->orderBy("$field")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($field) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$field] . ($item['is_freeze'] == 1 ? ' (Room is frozen for cycle count)' : ''),
                    'disabled' => $item['is_freeze'] == 1 ? 'disabled' : '',
                ]
            ];
        });

        return $result;
    }

    /** Get the installed locations based on relation
     * @param Request $request
     *
     * @return [type]
     */
    public function getFilterInstalledLocations($search, $field = 'room_name')
    {
        $res = Location::installLocations()->where("$field", 'like', '%' . $search . '%')->active()->orderBy("$field")->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($field) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item[$field] . ($item['is_freeze'] == 1 ? ' (Room is frozen for cycle count)' : ''),
                    'disabled' => $item['is_freeze'] == 1 ? 'disabled' : '',
                ]
            ];
        });

        return $result;
    }

    public function getFilterTicketServerFields($search, $type)
    {
        $res = Asset::select("$type")->serverAsset()->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    public function getFilterTicketNetworkFields($search, $type)
    {
        $res = Asset::select("$type")->networkAsset()->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    public function getFilterWorkspaceOneFields($search, $type)
    {
        if ($type == 'userName') {
            $res = AirWatch::distinct('email')->select('email', 'first_name', 'last_name')
                ->where(function ($query) use ($search) {
                    $query->where('first_name', 'like', $search . '%')
                        ->orWhere('last_name', 'like', $search . '%')
                        ->orWhereRaw("CONCAT(`first_name`, ' ', `last_name`) like ?", [$search . '%'])
                        ->orWhere('email', 'like', $search . '%')
                        ->orWhere('user_name', 'like', $search . '%');
                })
                ->limit(15)->get();

            $result = $res->mapWithKeys(function ($item, $key) {
                return [
                    $key => [

                        'id' => $item->email,
                        'text' => $item->first_name . ' ' . $item->last_name . ' - ' . $item->email,
                    ]
                ];
            });
            return $result;
        }
        if ($type == 'airwatch_phone_number') {

            $res = AirWatchPhoneNumber::distinct()->select("phone_number")->where("phone_number", 'like', '%' . $search . '%')->get();
            $result = $res->mapWithKeys(function ($item, $key) {
                return [
                    $key => [
                        'id' => $item['phone_number'],
                        'text' => $item['phone_number'],
                    ]
                ];
            });

            return $result;
        }

        $res = AirWatch::distinct()->select("$type")->where("$type", 'like', '%' . $search . '%')->orderBy($type)->limit(15)->get();

        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    public function getFilterChromebookFields($search, $type)
    {

        $res = Chromebook::distinct()->select("$type")->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    /**
     * Makes key value data array for populating filter dropdowns for Intune reports
     * @param mixed $search
     * @param mixed $type
     *
     * @return [type]
     */
    public function getFilterIntuneFields($search, $type)
    {

        $res = IntuneComputer::distinct()->select("$type")->where("$type", 'like', '%' . $search . '%')->get();
        $result = $res->mapWithKeys(function ($item, $key) use ($type) {
            return [
                $key => [
                    'id' => $item[$type],
                    'text' => $item[$type],
                ]
            ];
        });

        return $result;
    }

    /**
     * Search the for assignable assets
     *
     * @param string $search  search value
     *
     * @return Array
     */
    public function getSearchAssetForAssignFields($search)
    {
        $canBeAssigned = getCanBeUpdatedToStatus('assigned');
        $res = Asset::select('id', 'serial_no')
            ->where('serial_no', 'like', '%' . $search . '%')
            ->whereHas('assetStatus', function ($query) use ($canBeAssigned) {
                $query->whereIn('slug', $canBeAssigned);
                //})->whereHas('assetType', function ($query) use ($assetTypeSlug) {
                //    $query->where('slug', $assetTypeSlug);
            })->limit(15)->get();

        $result = $res->mapWithKeys(function ($item, $key) {
            return [
                $key => [
                    'id' => $item['id'],
                    'text' => $item['serial_no'],
                ],
            ];
        });

        return $result;
    }
}
