<?php

namespace App\Repositories\NewHire;

use App\Models\Asset;
use App\Models\AssetHistory;
use App\Models\AssetStatus;
use App\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class AverageDeploymentTimeRepository
{
    protected $assetModel;
    protected $assetStatusModel;
    protected $assetHistoryModel;
    protected $userModel;

    public function __construct(Asset $assetModel, AssetStatus $assetStatusModel, AssetHistory $assetHistoryModel, User $userModel)
    {
        $this->assetModel = $assetModel;
        $this->assetStatusModel = $assetStatusModel;
        $this->assetHistoryModel = $assetHistoryModel;
        $this->userModel = $userModel;
    }
    /**
     * Retrieves data from the database.
     *
     * @return mixed
     */
    public function getData()
    {
        $assignedStatusId = $this->assetStatusModel::where('slug', 'assigned')->first()->id;

        return $this->assetModel::with([
            'user:id,first_name,last_name,hire_date,department_id,location_id,business_title,city',
            'user.department:id,name',
            'location:id,room_name'
            ])
            ->select('assets.id', 'assets.user_id', 'assets.asset_tag', 'assets.serial_no', 'assets.ticket_no', 'asset_histories.updated_at as assigned_date')
            ->join('users', 'users.id', '=', 'assets.user_id')
            ->leftJoin('asset_histories', function ($join) {
                $join->on('asset_histories.asset_id', '=', 'assets.id');
                $join->on('asset_histories.new_user_id', '=', 'assets.user_id');
            })
            ->where('asset_histories.new_asset_status_id', '=', $assignedStatusId);
    }

    /**
     * Searches for users using general queries.
     *
     * @param object $users The users to search through.
     * @param string $searchText The text to search for.
     * @return object The filtered users.
     */
    public function searchUserWithGeneralQueries($query, $searchText)
    {
        if ($searchText) {
            $query->where(function ($query) use ($searchText) {
                $query->where('first_name', 'like', $searchText . '%')
                    ->orWhere('last_name', 'like', $searchText . '%')
                    ->orWhere('employee_id', $searchText)
                    ->orWhereRaw("CONCAT(`first_name`, ' ', `last_name`) like ?", [$searchText . '%'])
                    ->orWhere('email', 'like', $searchText . '%');
            });
        }

        return $query;
    }

    /**
     * Searches for an asset with the given search text.
     *
     * @param QueryBuilder $query The query builder object.
     * @param string $searchText The search text to match against the serial # or asset tag.
     * @return QueryBuilder The modified query builder object.
     */
    public function searchAssetWithSearchText($query, $searchText)
    {
        if ($searchText) {
            $query->where(function ($query) use ($searchText) {
                $query->where(function ($query) use ($searchText) {
                    $query->where('serial_no', 'like', $searchText . '%')
                        ->orWhere('asset_tag', 'like', $searchText . '%');
                });
            });
        }

        return $query;
    }

    /**
     * Retrieves the assignment history of a specific asset for a given user.
     *
     * @param int $assetId The ID of the asset.
     * @param int $userId The ID of the user.
     * @return AssetHistory|null The assigned asset history for the given user and asset, or null if not found.
     */
    public function getAssignedAssetsHistory(int $assetId, int $userId)
    {
        $assignedStatusId = Cache::remember('assignedStatusId', now()->addMinutes(10), function () {
            return $this->assetStatusModel::where('slug', 'assigned')->first()->id;
        });

        return $this->assetHistoryModel::with('user')
            ->where('asset_id', $assetId)
            ->where('new_user_id', $userId)
            ->where('new_asset_status_id', $assignedStatusId)
            ->orderBy('created_at', 'desc')
            ->first();
    }

    /**
     * Retrieves a list of new hires.
     */
    public function newHires()
    {
        return $this->userModel::superAdmin();
    }

    /**
     * Retrieves the assets that were assigned on a specific date.
     *
     * @param Builder $query The query builder instance.
     * @return Builder The modified query builder instance.
     */
    public function assetsAssignedOnDate($query)
    {
        return $query->whereDate('asset_histories.updated_at', '=', DB::raw('users.hire_date'));
    }

    /**
     * Filters the query to only include assets assigned after the user's hire date.
     *
     * @param Builder $query The query to be filtered.
     * @return Builder The filtered query.
     */
    public function assetsAssignedAfterStartDate($query)
    {
        return $query->whereDate('asset_histories.updated_at', '>', DB::raw('users.hire_date'));
    }
}
