<?php

namespace App\Http\Controllers\SoftwareLicense;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Services\SoftwareLicense\LicenseService;
use App\Models\SoftwareLicense\SoftwareLicenseCategory;
use App\Models\SoftwareLicense\SoftwareLicenseManufacturer;
use App\Http\Requests\SoftwareLicense\LicenseRequest;
use App\Http\Responses\DataTableJsonResponse;
use App\Models\SoftwareLicense\SoftwareLicenseSubscription;
use App\Models\Vendor;
use App\Services\SoftwareLicense\LicenseDocumentService;
use App\Services\SoftwareLicense\LicenseKeyService;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Services\SoftwareLicense\NonTeqUserService;

/**
 * Software License Controller
 */
class SoftwareLicenseController extends Controller
{

    /**
     * Initialize the controller with the necessary services and models.
     *
     * @param \App\Services\LicenseService            $licenseService         The service to manage licenses
     * @param \App\Services\LicenseKeyService         $licenseKeyService      The service to manage license keys
     * @param \App\Models\SoftwareLicenseCategory     $categoryModel          The model to manage software license categories
     * @param \App\Models\SoftwareLicenseManufacturer $manufacturerModel      The model to manage software license manufacturers
     * @param \App\Services\LicenseDocumentService    $licenseDocumentService The service to manage license documents
     * @param \App\Models\SoftwareLicenseSubscription $subscriptionModel      The model to manage software license subscriptions
     * @param \App\Services\NonTeqUserService         $nonTeqUserService      The service to manage non-Teq users
     */
    public function __construct(
        protected LicenseService $licenseService,
        protected LicenseKeyService $licenseKeyService,
        protected SoftwareLicenseCategory $categoryModel,
        protected SoftwareLicenseManufacturer $manufacturerModel,
        protected LicenseDocumentService $licenseDocumentService,
        protected SoftwareLicenseSubscription $subscriptionModel,
        protected NonTeqUserService $nonTeqUserService
    ) {
    }

    /**
     * Display the index view for software licenses.
     *
     * @return \Illuminate\View\View The view for the software license index
     */
    public function index()
    {
        session(['count_add' => 0]);

        return view('software-license.license.index');
    }

    /**
     * Display the create view for a new software license.
     *
     * @return \Illuminate\View\View The view for creating a new software license
     */
    public function create()
    {
        $categories = $this->categoryModel->orderBy('name')->get();
        $softwareLicenceManufacturers = $this->manufacturerModel->orderBy('name')->get();
        $paymentMethods = $this->licenseService->getAllPaymentMethods();
        $subscriptionLengths = $this->subscriptionModel->orderBy('duration')->orderBy('duration_type')->get();
        $vendors = Vendor::orderBy('name')->get();

        session(['count_add' => 0]);

        return view('software-license.license.create', compact('categories', 'softwareLicenceManufacturers', 'paymentMethods', 'vendors', 'subscriptionLengths'));
    }

    /**
     * Retrieve and format the data for the software licenses.
     *
     * @param \Illuminate\Http\Request $request The incoming request instance
     *
     * @return \Illuminate\Http\JsonResponse The JSON response containing the formatted license data
     */
    public function data(Request $request)
    {
        $filteredData = $this->licenseService->filter();
        $licenses =  $filteredData['licenses'];
        $totalData = $filteredData['count'];

        $start = request('start');
        $data = [];

        if (!empty($licenses)) {
            $data = $this->licenseService->getLicensesData($licenses, $start, $data);
        }

        return new DataTableJsonResponse($request->input('draw'), $data, $totalData);
    }

    /**
     * Store a new software license.
     *
     * @param \App\Http\Requests\LicenseRequest $request The incoming request instance
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message
     */
    public function store(LicenseRequest $request)
    {
        DB::beginTransaction();

        $keyMessage = '';

        try {
            $data = $request->except(['_token', 'software_liceneses_documents', 'software_liceneses_keys', 'license_key', 'license_keys', 'license-key-choice']);
            $response = $this->licenseService->createLicense($data);
            $countAdded = true;

            if ($response) {
                if ($request->hasfile('software_liceneses_documents')) {
                    foreach ($request->file('software_liceneses_documents') as $file) {
                        $name = $data['name'] . '-' . time() . '.' . $file->extension();
                        $file->move(storage_path() . '/app/public/software-assets', $name);
                        $this->licenseDocumentService->saveDocuments($name, $response->id);
                    }
                }

                if ($request->has('license_key') && $request->license_key) {
                    $this->licenseKeyService->storeLicenseKey([$request->license_key], $response->id, $request->key_usage_type, $request->users_allowed_for_key);
                }

                if ($request->has('license_keys')  && $request->license_keys) {
                    $countAdded = $this->licenseKeyService->storeLicenseKey(explode(PHP_EOL, $request->license_keys), $response->id, $request->key_usage_type, $request->users_allowed_for_key, $request->licenses_purchased);
                    $keyMessage = $countAdded . ' keys added.';
                }

                if ($request->hasfile('software_liceneses_keys')) {
                    $extension = strtolower(request()->file('software_liceneses_keys')->getClientOriginalExtension());
                    $path = request()->file('software_liceneses_keys')->storeAs('public/software-assets', 'software_liceneses_keys-' . time() . '.' . $extension);
                    $countAdded =  $this->licenseKeyService->saveLicenseKeyDocument(storage_path('app/' . $path), $response->id, $request->key_usage_type, $request->users_allowed_for_key);

                    if (is_bool($countAdded['licensesUsed'])) {
                        $keyMessage = 'Please check the uploaded keys file.';
                    } else {
                        $keyMessage = ($countAdded['licensesUsed'] ? ($countAdded['licensesUsed'] . ' license key(s) added successfully.') : '') . ($countAdded['rejected'] ? ($countAdded['rejected'] . ' key(s) rejected as the # of licenses purchased reached or due to invalid key format.') : '');
                    }
                }

                DB::commit();

                return redirect('software-assets')->with('message', 'New asset added successfully.' . $keyMessage);
            }
        } catch (Exception $e) {
            Log::error($e->getMessage());
            DB::rollBack();

            return redirect()->route('software-assets.create')->withInput()->withErrors('Opertaion failed.');
        }
    }

    /**
     * Display the edit view for a software license.
     *
     * @param int $id The ID of the software license to edit
     *
     * @return \Illuminate\View\View The view for editing the software license
     */
    public function edit(int $id)
    {
        $license = $this->licenseService->getLicense($id);
        $categories = $this->categoryModel->orderBy('name')->get();
        $softwareLicenceManufacturers = $this->manufacturerModel->orderBy('name')->get();
        $paymentMethods = $this->licenseService->getAllPaymentMethods();

        // Commented Unused: $licenseKeys = $this->licenseKeyService->getAllLicenseKeys($id);.
        $availableLicenseKeys = $this->licenseKeyService->getAvailableLicenseKeys($id);
        $subscriptionLengths = $this->subscriptionModel->orderBy('duration')->orderBy('duration_type')->get();
        $vendors = Vendor::orderBy('name')->get();

        return view('software-license.license.edit', compact('license', 'categories', 'softwareLicenceManufacturers', 'paymentMethods', 'vendors', 'subscriptionLengths', 'availableLicenseKeys'));
    }

    /**
     * Display the details view for a software license.
     *
     * @param int $id The ID of the software license to show
     *
     * @return \Illuminate\View\View The view for showing the software license details
     */
    public function show(int $id)
    {
        $license = $this->licenseService->getLicense($id);
        $categories = $this->categoryModel->orderBy('name')->get();
        $vendors = $this->manufacturerModel->orderBy('name')->get();
        $paymentMethods = $this->licenseService->getAllPaymentMethods();
        $graphData = $this->licenseService->getUserMonthGraphData($id);
        $nonTeqtivityUserCount = $this->nonTeqUserService->getNonTeqtivityUsersCount($id);

        return view('software-license.license.view', compact('license', 'categories', 'vendors', 'paymentMethods', 'graphData', 'nonTeqtivityUserCount'));
    }

    /**
     * Update an existing software license.
     *
     *
     * @param \App\Http\Requests\LicenseRequest $request The incoming request instance
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message
     */
    public function update(LicenseRequest $request)
    {
        $data = $request->except(['_token', 'software_liceneses_documents', '_method']);
        $response = $this->licenseService->updateLicense($data);
        if ($response) {
            // if($request->has('key_usage_type')){
            //     $this->licenseKeyService->updateLicenseKey($id,$request->key_usage_type,$request->users_allowed_for_key);
            // }

            return redirect()->route('software-assets.edit', $data['id'])->with('message', 'Asset updated successfully.');
        } else {
            return redirect()->route('software-assets.edit', $data['id'])->with('error', 'Opertaion failed. Asset update failed.');
        }
    }

    /**
     * Delete an existing software license.
     *
     * @param \Illuminate\Http\Request $request The incoming request instance
     *
     * @return \Illuminate\Http\RedirectResponse The redirect response with a success or error message
     */
    public function delete(Request $request)
    {
        $response = $this->licenseService->deleteLicense($request->id);

        if ($response) {
            return redirect('software-assets')->with('message', 'Asset deleted successfully.');
        } else {
            return redirect('software-assets')->with('error', 'Opertaion failed.');
        }
    }
}
