<?php

namespace App\Repositories\DiscoveryTools;

use App\Models\Asset;
use App\Models\AssetStatus;
use App\Models\AssetType;
use App\Models\Location;
use App\Models\ZoomDevice;
use Illuminate\Support\Facades\DB;

class ZoomRepository extends AbstractRepository
{
    /**
     * Constructs a new instance of the ZoomRepository class.
     *
     * @param ZoomDevice $model The ZoomDevice model instance.
     * @param Location $locationModel The Location model instance.
     * @param AssetStatus $assetStatusModel The AssetStatus model instance.
     * @param Asset $assetModel The Asset model instance.
     * @param AssetType $assetTypeModel The AssetType model instance.
     */
    public function __construct(
        protected ZoomDevice $model,
        protected Location $locationModel,
        protected AssetStatus $assetStatusModel,
        protected Asset $assetModel,
        protected AssetType $assetTypeModel
    ) {}

    /**
     * Making query for All Zoom report.
     */
    public function getAllDevices()
    {
        return $this->model->with(
            'location:id,room_name',
            'asset:id,serial_no,asset_status_id,make_and_model_id,location_id',
            'asset.assetStatus:id,name',
            'asset.latestAssetHistory:id,asset_id,created_at',
            'asset.location:id,room_name'
        );
    }

    /**
     * Devices not created.
     */
    public function getAssetsNotCreated()
    {
        return $this->model->with('location:id,room_name')
            ->where(function ($query) {
                $query->where('asset_id', 0)->orWhereNull('asset_id');
            });
    }

    /**
     * Making query for DevicesNotActive report.
     */
    public function getDevicesNotActive()
    {
        $statusId = $this->assetStatusModel->whereIn('slug', ['assigned', 'loaned', 'installed'])->get()->pluck('id');

        return $this->model->with('asset:id,serial_no,asset_status_id,make_and_model_id,location_id', 'asset.location:id,room_name', 'asset.assetStatus:id,name', 'location:id,room_name')
            ->where('last_start_time', '<', \Carbon\Carbon::now()->subDays(30))
            ->whereHas('asset', function ($query) use ($statusId) {
                $query->whereIn('asset_status_id', $statusId);
            });
    }

    /**
     * Making query for  'Deployed - Active, not Managed' In report.
     */
    public function getNotManaged()
    {
        $statusId = $this->assetStatusModel->whereIn('slug', ['loan_or_test', 'assigned'])->get()->pluck('id');
        $assetTypeId = $this->assetTypeModel->whereIn('slug', ['laptop', 'mobile_device', 'tablet', 'desktop'])->get()->pluck('id');

        return $this->assetModel->select('assets.*')
            ->with('assetStatus:id,name', 'makeAndModel:id,name', 'location:id,room_name')
            ->whereIn('asset_status_id', $statusId)
            ->whereIn('asset_type_id', $assetTypeId)
            ->doesntHave('zoom');
    }

    /**
     * Making query for  'Location Discrepancy'  In report.
     */
    public function getLocationDiscrepancy()
    {
        $statusId   = $this->assetStatusModel->where('has_location', 1)->get()->pluck('id');
        $query = $this->model->select('zoom_devices.*')->with('asset:id,serial_no,asset_status_id,make_and_model_id,location_id', 'asset.assetStatus:id,name', 'asset.location:id,room_name', 'location:id,room_name')
            ->join("assets", function ($join) use ($statusId) {
                $join->on('assets.id', '=', 'zoom_devices.asset_id')
                    ->on('assets.location_id', '<>', 'zoom_devices.location_id')
                    ->whereIn('assets.asset_status_id', $statusId);
            });

        return $query;
    }

    /**
     * Making query for Devices On Hand Checked In report.
     */
    public function getDevicesOnHandCheckedIn()
    {
        $statusId = $this->assetStatusModel->where('has_user', 1)->get()->pluck('id');
        $query = $this->model->select('zoom_devices.*')->with('asset:id,serial_no,asset_status_id,make_and_model_id,location_id', 'asset.assetStatus:id,name', 'asset.location:id,room_name', 'location:id,room_name')
            ->whereHas('asset', function ($query) use ($statusId) {
                $query->whereIn('asset_status_id', $statusId)->doesNotHaveAssetStatus(['installed']);
            })
            ->leftJoin('assets', 'zoom_devices.asset_id', '=', 'assets.id')
            ->where(function ($query) {
                $query->where('zoom_devices.last_start_time', '>', DB::raw('assets.last_status_update'))
                    ->orWhereNull('assets.last_status_update');
            });

        return $query;
    }

    /**
     * Filters the query based on the given value and field.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query The query builder instance.
     * @param string $field The field to filter on.
     * @param mixed $value The value to filter.
     *
     * @return \Illuminate\Database\Eloquent\Builder The modified query builder instance.
     */
    public function filterRelation($query, $field, $value)
    {
        if (is_array($value)) {
            return $query->whereIn('zoom_devices.' . $field, $value);
        }

        return $query->where('zoom_devices.' . $field, $value);
    }

    /**
     * Filter and retrieve distinct field values based on search criteria.
     *
     * @param string $search The search term to filter the field values.
     * @param string $type The field type to be selected and filtered.
     *
     * @return \Illuminate\Database\Eloquent\Builder The query builder instance with the applied filter.
     */
    public function filterField($search, $type)
    {
        return $this->model->distinct()->select("$type")->where("$type", 'like', '%' . $search . '%');
    }

    /**
     * Get asset id by serial number.
     *
     * @param string $serialNo
     * @return int|null
     */
    public function getAssetIdBySerialNo($serialNo)
    {
        if (empty($serialNo)) {
            return null;
        }

        return $this->assetModel->where('serial_no', trim($serialNo))->value('id');
    }

    /**
     * Get location by room name.
     *
     * @param string $roomName
     * @return \Illuminate\Database\Eloquent\Model|null
     */
    public function getTeqtivityLocationByRoomName($roomName)
    {
        if (empty($roomName)) {
            return null;
        }

        return $this->locationModel->where('room_name', trim($roomName))->first();
    }

    /**
     * Update or create zoom data.
     *
     * @param array $data
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function updateOrCreateZoomData($data)
    {
        return $this->model->updateOrCreate(['device_id' => $data['device_id']], $data);
    }

    public function getUserMismatchDevices() {}
}
