<?php 

namespace App\Services\Api\Slackbot;

use App\Services\Api\Jira\TeqtivityAssetStatus;
use App\Services\Api\ApiService;
use Illuminate\Http\Request;
use App\Models\AssetHistory;
use App\Models\AssetStatus;
use App\Models\Location;
use App\Models\Asset;
use Exception;
use App\User;
use Cache;
use Auth;
use Log;

/**
 * Service class for install asset slash command
 */
class InstallAssetService extends SlackbotApiService
{
    public function __construct(protected TeqtivityAssetStatus $statusService, protected ApiService $responseService)
	{
	}

    /**
     * Get Asset and location details for the install asset
     *
     * @param Request $request
     *
     * @return Collection
     */
    public function getAssetDetails(Request $request)
    {
        //Check slack user email is existing or not
        $slackUser = $this->getUserByEmail($request->slack_user_email);
        if (isset($slackUser['error']) && $slackUser['error'] == true) {
            return $slackUser;
        }

        //Check the Loaner user is existing or not
        $location = $this->getLocationByName($request->location);
        if (isset($location['error']) && $location['error'] == true) {
            return $location;
        }

        //check permission
        if (!$slackUser->can('Slackbot Admin Tools')) {
            return $this->getErrorResponse('You do not have permission to update this asset');
        }

        //Log::info('Searched serial'. $request->serial_no);
        //Check the asset exists
        $asset = Asset::select('id', 'serial_no', 'asset_tag', 'asset_status_id')->with('assetStatus:id,name,slug')
                    ->where(function($query) use ($request){
                        $query->where('asset_tag', $request->serial_no)
                              ->orWhere('serial_no', $request->serial_no);
                    })
                    ->first();

        if (!$asset) {
            return $this->getErrorResponse('Asset not found in Teqtivity');
        }

        //Check the installed Status is existing on the Teqtivity
        $installedStatus = AssetStatus::select('id', 'name', 'slug')->where('slug', config('slackbot.asset_status.installed'))->first();
        if (!$installedStatus) {
            return $this->getErrorResponse('Installed status not found in Teqtivity');
        }

        //Check the asset is valid for the status update
        $currentStatusSlug = optional($asset->assetStatus)->slug;
        if (!in_array(config('slackbot.asset_status.installed'), config('asset-status.' . $currentStatusSlug))) {
            return $this->getErrorResponse('The asset cannot be installed because of status restrictions.');
        }

        //Inject the Location and installed status to the asset collection
        $asset->install_location    = $location;
        $asset->install_status      = $installedStatus;
        //Log::info('Fetched asset'. $asset);
        return $this->getSuccessReponse($asset, 'Asset');
    }

    /**
     * Get Location details by name
     * 
     * @param string $name
     * 
     * @return Collecion
     */
    public function getLocationByName($name)
    {
        $location = Location::select('id', 'location_type_id', 'room_name', 'address')
                    ->with('locationType:id,location_type_name')
                    ->where('room_name',$name)
                    ->first();

        if (!$location) {
            return $this->getErrorResponse('Location not found in Teqtivity');
        }

        return $location;
    }

    /**
     * Update the asset status.
     *
     * @param Request $request 
     */
    public function updateAssetStatus(Request $request)
    {
        $error = $this->statusService->validate($request);
		if ($error) {
			return $this->responseService->errorResponse($error);
		}
		try {
			$response = $this->statusService->update($request);

			return $this->responseService->successResponse('', $response);
		} catch (Exception $e) {
			Log::channel('single')->info('Slackbot Status Update Error : ' . $e->getMessage());
			return $this->responseService->errorResponse('Something went wrong. Try again later');
		}
    }
}