<?php

namespace App\Http\Controllers\Assets\Settings;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Dropbox\DropboxStoreRequest;
use Illuminate\Support\Facades\Artisan;
use App\Services\SoftwareLicense\ImportedAssets\DropboxService;

class DropboxCredentialsController extends Controller
{
    private $service;

    /**
     * Constructor of DropboxCredentialsController
     *
     * @param DropboxService $service
     */
    public function __construct(DropboxService $service)
    {
        $this->service = $service;
    }

    /**
     * If the user has already created the Software asset API credential, show the user the settings page.
     * Otherwise, redirect the user to the create page
     *
     * @return object View is being returned.
     */
    public function index()
    {
        $credentialsData =  $this->service->getCredentials();

        if (!$credentialsData) {
            return redirect()->route('dropbox.create');
        }

        $status = $this->service->checkConnection($credentialsData);

        return view('settings.dropbox.index', ['credentials' => $credentialsData, 'status' => $status]);
    }

    /**
     * create the new software asset API credential
     *
     * @return object View is being returned
     */
    public function create()
    {
        if ($this->service->getCredentials()) {
            return redirect()->route('dropbox.index');
        }

        return view('settings.dropbox.create');
    }

    /**
     * Store the software asset Credentials in the API Credential table
     *
     * @param DropboxStoreRequest $request
     *
     * @return object Redirecting to the proper page
     */
    public function store(DropboxStoreRequest $request)
    {
        if ($this->service->getCredentials()) {
            return redirect()->route('dropbox.index')->with('error', 'Credentials already exist. ');
        }

        $response = $this->service->addCredentials($request);

        return $response ? redirect()->route('dropbox.index')->with('message', __('message.created'))
            : redirect()->route('dropbox.create')->with('error', 'Opertaion Failed');
    }

    /**
     * It takes the id of the credential, finds it in the database, and returns a view with the
     * credential
     *
     * @return object View is being returned.
     */
    public function edit()
    {
        $credentialsData = $this->service->getCredentials();

        if (!$credentialsData) {
            return redirect()->route('dropbox.create');
        }

        return view('settings.dropbox.edit', ['credential' => $credentialsData]);
    }

    /**
     * It updates the credentials of the software asset account.
     *
     * @param object Request $request
     *
     * @return object Redirecting to the proper page
     */
    public function update(Request $request)
    {
        $response = $this->service->updateCredentials($request);

        return $response ? redirect(route('dropbox.index'))->with('message', 'Credentials updated successfully') :
            redirect(route('dropbox.index'))->with('error', 'Something went wrong. Try again later');
    }

    /**
     * Establishing the connection with the added software asset account
     *
     * @return object Redirect to the proper page after connection
     */
    public function connect()
    {
        $connectWithExistingData = $this->service->setConnection();

        if ($connectWithExistingData) {
            return redirect(route('dropbox.index'))->with('message', 'Connected successfully.');
        }

        $authenticationURL = $this->service->getAuthenticationURL();

        return redirect($authenticationURL);
    }

    /**
     * A callback function which is called when the user is redirected from software asset after
     * authentication.
     *
     * @return object Redirect to the proper page after connection
     */
    public function callback()
    {
        $code = request('code') ?? '';
        $credentialsData = $this->service->getCredentials();

        if (!$credentialsData) {
            return redirect(route('dropbox.index'))->with('error', 'Credentials not available.');
        }

        $authorizationResponse = $this->service->generateAccessToken($code, $credentialsData);

        if (!$authorizationResponse) {
            return redirect(route('dropbox.index'))->with('error', 'Authorization failed');
        }
        $checkRequiredScopes = $this->service->checkRequiredScopes($authorizationResponse);

        if ($checkRequiredScopes['error'] != '') {
            return redirect(route('dropbox.index'))->with('error', 'Connected app does not have team permissions('.implode(", ", $checkRequiredScopes['nonExistigScopes']).')');
        }

        $updateAccessToken = $this->service->updateAccessToken($authorizationResponse);

        return $updateAccessToken ? redirect(route('dropbox.index'))->with('message', 'Authorization successfully completed and token updated successfully')
             : redirect(route('dropbox.index'))->with('error', 'Something went wrong. Try again later');

    }

    /**
     * A function to sync the data from software asset to our database.
     *
     * @return object Redirect to the proper page after connection
     */
    public function manualSync()
    {
        Artisan::call('Dropbox:sync');
        $softwareAssetSyncStatus = Artisan::output();
        $response = json_decode($softwareAssetSyncStatus, true);

        if ($response['status'] == 'success') {
            return redirect(route('dropbox.index'))->with( 'message', $response['message']);
        }

        return redirect(route('dropbox.index'))->with('error', $response['message']);
    }

    /**
     * This function changes the integration status of software asset and enables/disables the software asset accordingly
     *
     * @return bool
     */
    public function integrationStatusChange()
    {
        return $this->service->integrationStatusChange();
    }
}
