<?php

namespace App\Services\SoftwareLicense;

use app\User;
use Illuminate\Support\Facades\Auth;
use App\Models\SoftwareLicense\SoftwareLicenseCategory;
use App\Models\SoftwareLicense\SoftwareLicenseManufacturer;
use App\Models\SoftwareLicense\PaymentMethod;
use App\Models\SoftwareLicense\SoftwareLicenseSubscription;
use App\Models\Vendor;

class LicenseHistoryService
{
    protected $categoryModel;
    protected $manufacturerModel;
    protected $paymentMethodModel;
    protected $subscriptionModel;
    protected $vendorModel;
    protected $actions = [
        'created'                   =>  'warning',
        'updated'                   =>  'update',
        'document_added'            =>  'success',
        'document_removed'          =>  'danger',
        'user_added'                =>  'success',
        'user_removed'              =>  'danger',
        'license_key_updated'       =>  'update',
        'license_key_added'         =>  'success',
        'license_key_upload'        =>  'success',
        'license_key_removed'       =>  'danger',
    ];

    /**
     * Class constructor.
     *
     * @param SoftwareLicenseCategory     $categoryModel      The model instance for software license categories.
     * @param SoftwareLicenseManufacturer $manufacturerModel  The model instance for software license manufacturers.
     * @param PaymentMethod               $paymentMethodModel The model instance for payment methods.
     * @param SoftwareLicenseSubscription $subscriptionModel  The model instance for software license subscriptions.
     * @param Vendor                      $vendorModel        The model instance for vendors.
     */
    public function __construct(
        SoftwareLicenseCategory $categoryModel,
        SoftwareLicenseManufacturer $manufacturerModel,
        PaymentMethod $paymentMethodModel,
        SoftwareLicenseSubscription $subscriptionModel,
        Vendor $vendorModel
    ) {
        $this->categoryModel = $categoryModel;
        $this->manufacturerModel = $manufacturerModel;
        $this->paymentMethodModel = $paymentMethodModel;
        $this->subscriptionModel = $subscriptionModel;
        $this->vendorModel = $vendorModel;
    }

    /**
     * Get actions related with software assets.
     *
     * @return array
     */
    public function getActions()
    {
        return $this->actions;
    }

    /**
     * Generates a status description for a newly created license.
     *
     * @param SoftwareLicense $license The license for which the status description is generated.
     *
     * @return string The status description for the newly created license.
     */
    public function getStatusDescriptionForCreated($license)
    {
        $name = $license->name;
        $assetId = $license->id;

        return  __('license-history.Created', [
            'name' => $name,
            'assetId' => $assetId
        ]);
    }

    /**
     * Generates a status description for an edited asset.
     *
     * This method returns a localized string describing the changes made to the asset,
     * including details about the old and new values of changed fields.
     *
     * @param Asset $asset       The asset that was edited.
     * @param array $changedData An array of changed data, with keys as field names and values as arrays with 'old' and 'new' values.
     *
     * @return string The status description for the edited asset.
     */
    public function getStatusDescriptionForEdited($asset, $changedData)
    {
        $comments = '';

        $i = 1;

        foreach ($changedData as $key => $data) {
            if ($key == 'software_license_category_id') {
                $data['old'] = optional($this->categoryModel->find($data['old']))->name;
                $data['new'] = optional($this->categoryModel->find($data['new']))->name;
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'software_license_manufacturer_id') {
                $data['old'] = optional($this->manufacturerModel->find($data['old']))->name;
                $data['new'] = optional($this->manufacturerModel->find($data['new']))->name;
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'payment_method_id') {
                $data['old'] = optional($this->paymentMethodModel->find($data['old']))->name;
                $data['new'] = optional($this->paymentMethodModel->find($data['new']))->name;
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'software_license_subscription_id') {
                $data['old'] = $data['old'] ? optional($this->subscriptionModel->find($data['old']))->name : '';
                $data['new'] = $data['new'] ? optional($this->subscriptionModel->find($data['new']))->name : '';
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'vendor_id') {
                $data['old'] = $data['old'] ? optional($this->vendorModel->find($data['old']))->name : '';
                $data['new'] = $data['new'] ? optional($this->vendorModel->find($data['new']))->name : '';
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'owner_id') {
                $data['old'] = $data['old'] ? optional(User::find($data['old']))->user_name : '';
                $data['new'] = $data['new'] ? optional(User::find($data['new']))->user_name : '';
                $key = str_replace("_id", "", $key);
            }

            if ($key == 'status') {
                $data['old'] = config('software-license.licence_status')[$data['old']] ?? '';
                $data['new'] = config('software-license.licence_status')[$data['new']] ?? '';
            }

            if ($key == 'start_date' || $key == 'renewal_date') {
                $data['old'] = $data['old'] ? parse_date_from_db_date($data['old']) : '';
                $data['new'] = $data['old'] ? parse_date_from_db_date($data['new']) : '';
            }

            if ($key == 'license_key_type') {
                $data['old'] = config('software-license.license_key_types')[$data['old']] ?? '';
                $data['new'] = config('software-license.license_key_types')[$data['new']] ?? '';
            }

            if ($key == 'key_usage_type') {
                $data['old'] = $data['old'] ? config('software-license.key_usage_types')[$data['old']] : '';
                $data['new'] = $data['new'] ? config('software-license.key_usage_types')[$data['new']] : '';
            }

            $comments .=  str_replace("_", " ", $key) . " changed " . ($data['old'] ? ("from " . $data['old']) : '') . " to " . $data['new'];

            if ($i != count($changedData)) {
                $comments .= ' , ';
            }

            $i++;
        }

        return  __('license-history.Updated', [
            'comments' => $comments,
            'name' => $asset->name,
            'assetId' => $asset->id
        ]);
    }

    /**
     * Generates a status description for user-related actions on a license.
     *
     * This method returns a localized string describing the action performed on the license,
     * including details about the user and optional license key.
     *
     * @param string          $action      The action performed, either 'user_added' or 'user_removed'.
     * @param int             $userId      The ID of the user involved in the action.
     * @param SoftwareLicense $licenseData The license on which the action was performed.
     * @param string|null     $key         An optional license key related to the action.
     *
     * @return string The status description for the user-related action on the license.
     */
    public function getStatusDescriptionForUserActions($action, $userId, $licenseData, $key = null)
    {
        $user = User::find($userId);
        $userName = $user->first_name . ' ' . $user->last_name;

        $key = ($key ? ('with license key ' . $key) : '');
        $actionType = ($action === 'user_added' ? 'license-history.UserAdded' : 'license-history.UserRemoved');

        return  __($actionType, [
            'userName' => $userName,
            'userId' => $userId,
            'assetId' => $licenseData->id,
            'asset' => $licenseData->name,
            'key' => $key
        ]);
    }

    /**
     * Generates historical data for actions related to license keys.
     *
     * This method compares the current license key data with the updated data,
     * logs the changes, and creates a description for the action performed.
     *
     * @param string     $action     The action performed on the license key.
     * @param LicenseKey $licenseKey The current license key data.
     * @param array|null $update     The updated license key data.
     *
     * @return array An array containing historical data about the license key changes.
     */
    public function getHistoryDataForKeyActions($action, $licenseKey, $update = null)
    {
        $historyData = [];
        foreach ($licenseKey->toArray() as $key => $value) {
            if (isset($update[$key]) && $value != $update[$key]) {
                $historyData['old_' . $key] = $value;
                $historyData['new_' . $key] = $update[$key];
            }
        }

        $changes = '';
        $changes .= isset($historyData['old_license_key']) ? (' Updated to ' . $historyData['new_license_key'] . '.') : '';
        $changes .= isset($historyData['old_users_allowed_for_key']) ? (' Updated users allowed for key from ' . $historyData['old_users_allowed_for_key'] . ' to ' . $historyData['new_users_allowed_for_key'] . '.') : '';
        $actionType = 'license-history.licenseKeyUpdated';

        $description = __($actionType, [
            'key' => $licenseKey->license_key,
            'changes' => $changes
        ]);

        $historyData['software_license_id'] = $licenseKey->software_license_id;
        $historyData['action'] = 'license_key_updated';
        $historyData['description'] = $description;
        $historyData['software_license_key_id'] = $licenseKey->id;
        $historyData['user_id'] = Auth::id();

        return $historyData;
    }


    /**
     * Generates historical data for adding license keys.
     *
     * This method returns an array of historical data describing the addition of a new license key,
     * including details about the key usage type and the number of users allowed for the key.
     *
     * @param string     $action     The action performed, either 'license_key_added' or 'license_key_bulk_upload'.
     * @param LicenseKey $licenseKey The license key data that was added.
     *
     * @return array An array containing historical data about the license key addition.
     */
    public function getHistoryDataForKeyAdded($action, $licenseKey)
    {
        $historyAction = ($action == 'license_key_added' ? 'licenseKeyAdded' : 'licenseKeyBulkUpload');

        $description = __('license-history.' . $historyAction, [
            'key' => $licenseKey->license_key,
            'key_usage_type' => $licenseKey->key_usage_type ? ('with key usage type as ' . config('software-license.key_usage_types.' . $licenseKey->key_usage_type)) : '',
            'users_allowed_for_key' => ($licenseKey->users_allowed_for_key && $licenseKey->users_allowed_for_key != 'U') ? ('with # of users allowed for key as ' . $licenseKey->users_allowed_for_key) : '',
        ]);

        return [
            'action' => $action,
            'software_license_id' => $licenseKey->software_license_id,
            'new_license_key' => $licenseKey->license_key,
            'new_key_usage_type' => $licenseKey->key_usage_type,
            'new_users_allowed_for_key' => $licenseKey->users_allowed_for_key,
            'software_license_key_id' => $licenseKey->id,
            'description' => $description,
            'user_id' => Auth::id()
        ];
    }

    /**
     * Generates historical data for the removal of license keys.
     *
     * This method returns an array of historical data describing the removal of a license key,
     * including details about the key, its usage type, and the number of users allowed for the key.
     *
     * @param string     $action     The action performed, typically 'license_key_removed'.
     * @param LicenseKey $licenseKey The license key data that was removed.
     *
     * @return array An array containing historical data about the license key removal.
     */
    public function getHistoryDataForKeyRemoved($action, $licenseKey)
    {
        $description = __('license-history.licenseKeyRemoved', [
            'key' => $licenseKey->license_key,
        ]);

        return [
            'action' =>  $action,
            'software_license_id' => $licenseKey->software_license_id,
            'old_license_key' => $licenseKey->license_key,
            'old_key_usage_type' => $licenseKey->key_usage_type,
            'old_users_allowed_for_key' => $licenseKey->users_allowed_for_key,
            'software_license_key_id' => $licenseKey->id,
            'description' => $description,
            'user_id' =>  Auth::id()
        ];
    }
}
