<?php

namespace App\Http\Livewire;

use App\Models\LicenseKey;
use App\Services\Log;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Livewire\Component;
use Livewire\WithPagination;

class LicenseKeys extends Component {
	use WithPagination;

	protected string $paginationTheme = 'bootstrap';

	public $deleteId, $importLicenseKeys, $licenseKeyId, $productId, $licenseKey, $ownerName, $ownerEmail, $quantity, $activationLimit, $validity, $status, $method, $filterLicenseKey, $filterOwnerName, $filterOwnerEmail, $filterProductId, $filterStatus, $bulkAction, $bulkItems, $bulkActionStatus, $bulkActionConfirm;

	protected $listeners = [ 'importItems', 'createItem', 'updateItem', 'filterItems', 'bulkAction', 'bulkActionConfirmed' ];

	protected function getCreateRules(): array {
		$productId = $this->productId;

		return [
			'productId'       => 'required',
			'licenseKey'      => [
				'required',
				Rule::unique( 'license_keys', 'license_key' )->where( function ( $query ) use ( $productId ) {
					return $query->where( 'product_id', $productId );
				} )
			],
			'ownerEmail'      => 'email|nullable',
			'activationLimit' => 'required|numeric|min:0',
			'validity'        => 'required|numeric|min:0',
			'status'          => [
				'required',
				Rule::in( array_keys( LicenseKey::getStatuses() ) )
			]
		];
	}

	protected function getImportRules(): array {
		return [
			'productId'       => 'required',
			'ownerEmail'      => 'email|nullable',
			'activationLimit' => 'required|numeric|min:0',
			'validity'        => 'required|numeric|min:0',
			'status'          => [
				'required',
				Rule::in( array_keys( LicenseKey::getStatuses() ) )
			]
		];
	}

	protected function getUpdateRules(): array {
		$productId = $this->productId;

		return [
			'productId'       => 'required',
			'licenseKey'      => [
				'required',
				Rule::unique( 'license_keys', 'license_key' )->where( function ( $query ) use ( $productId ) {
					return $query->where( 'product_id', $productId );
				} )->ignore( $this->licenseKeyId )
			],
			'ownerEmail'      => 'email|nullable',
			'activationLimit' => 'required|numeric|min:0',
			'validity'        => 'required|numeric|min:0',
			'status'          => [
				'required',
				Rule::in( array_keys( LicenseKey::getStatuses() ) )
			]
		];
	}

	protected function getMessages(): array {
		return [
			'productId.required' => __( 'The product field is required.' )
		];
	}

	protected function getDeleteRules(): array {
		return [
			'deleteId' => 'required'
		];
	}

	public function createItemUpdated( $propertyName ): void {
		$this->validateOnly( $propertyName, $this->getCreateRules() );
	}

	public function importItemsUpdated( $propertyName ): void {
		$this->validateOnly( $propertyName, $this->getImportRules() );
	}

	public function updateItemUpdated( $propertyName ): void {
		$this->validateOnly( $propertyName, $this->getUpdateRules() );
	}

	public function createItem(): void {
		$this->validate( $this->getCreateRules() );

		$licenseKey = new LicenseKey();

		$this->assignItemFields( $licenseKey );

		Log::add( '114', Auth::id(), request()->ip(), [ 'license-key-id' => $licenseKey->id ] );

		$this->dispatchBrowserEvent( 'close-create-modal' );
	}

	public function importItems(): void {
		$this->validate( $this->getImportRules() );

		$imported  = 0;
		$duplicate = 0;
		$count     = 0;
		$isDemo    = \Config::get( 'app.is_demo', false );

		$licenseKeys = preg_split( "/(\r\n|\n|\r)/", $this->importLicenseKeys );
		foreach ( $licenseKeys as $key ) {
			$count ++;
			if ( $isDemo && $count == 10 ) {
				break;
			}

			if ( $key != '' ) {
				if ( LicenseKey::where( 'license_key', $key )->count() == 0 ) {
					$licenseKey       = new LicenseKey();
					$this->licenseKey = $key;

					$this->assignItemFields( $licenseKey );

					$imported ++;
				} else {
					$duplicate ++;
				}
			}
		}

		$this->dispatchBrowserEvent( 'close-import-modal' );
		$this->dispatchBrowserEvent( 'show-toast', [
			'toastType'    => 'success',
			'toastMessage' => sprintf( __( '%d license keys imported, %d duplicates skipped.' ), $imported, $duplicate )
		] );

		if ( $isDemo ) {
			$this->dispatchBrowserEvent( 'show-toast', [
				'toastType'    => 'danger',
				'toastMessage' => __( 'The quantity imported is capped at 10 in the demo!' )
			] );
		}
	}

	public function updateItem(): void {
		$this->validate( $this->getUpdateRules() );

		$licenseKey = LicenseKey::find( $this->licenseKeyId );

		$this->assignItemFields( $licenseKey );

		Log::add( '113', Auth::id(), request()->ip(), [ 'license-key-id' => $this->licenseKeyId ] );

		$this->dispatchBrowserEvent( 'close-update-modal' );
		$this->resetInputs();
	}

	public function deleteItem(): void {
		$this->validate( $this->getDeleteRules() );
		$this->dispatchBrowserEvent( 'close-delete-modal' );

		LicenseKey::find( $this->deleteId )->delete();

		Log::add( '115', Auth::id(), request()->ip(), [ 'license-key-id' => $this->licenseKeyId ] );
	}

	public function openCreateModal(): void {
		$this->resetInputs();
		$this->dispatchBrowserEvent( 'open-create-modal' );
	}

	public function openImportModal(): void {
		$this->resetInputs();
		$this->dispatchBrowserEvent( 'open-import-modal' );
	}

	public function openUpdateModal( $id ): void {
		$licenseKey = LicenseKey::find( $id );

		$this->licenseKeyId    = $licenseKey->id;
		$this->productId       = $licenseKey->product_id;
		$this->licenseKey      = $licenseKey->license_key;
		$this->ownerName       = $licenseKey->owner_name;
		$this->ownerEmail      = $licenseKey->owner_email;
		$this->activationLimit = $licenseKey->activation_limit;
		$this->validity        = $licenseKey->validity;
		$this->status          = $licenseKey->status;

		$this->dispatchBrowserEvent( 'open-update-modal', [
			'productId'   => $licenseKey->product_id,
			'productName' => $licenseKey->product ? $licenseKey->product->name : sprintf( __( 'Product #%d Not Found' ), $this->productId )
		] );
	}

	public function resetInputs(): void {
		$this->productId         = 0;
		$this->licenseKey        = Str::uuid()->toString();
		$this->importLicenseKeys = '';
		$this->ownerName         = '';
		$this->ownerEmail        = '';
		$this->quantity          = '100';
		$this->activationLimit   = '0';
		$this->validity          = '0';
		$this->status            = 'available';
		$this->method            = '';

		$this->resetValidation();
	}

	/**
	 * @param LicenseKey $licenseKey
	 *
	 * @return void
	 */
	public function assignItemFields( LicenseKey $licenseKey ): void {
		$licenseKey->product_id       = $this->productId;
		$licenseKey->license_key      = $this->licenseKey;
		$licenseKey->owner_name       = $this->ownerName;
		$licenseKey->owner_email      = $this->ownerEmail;
		$licenseKey->activation_limit = $this->activationLimit;
		$licenseKey->validity         = $this->validity;
		$licenseKey->status           = $this->status;

		$licenseKey->save();
	}

	public function filterItems(): void {
		$this->dispatchBrowserEvent( 'filter-done' );
	}

	public function bulkAction(): void {
		$this->dispatchBrowserEvent( 'open-confirm-bulk-action' );
	}

	public function bulkActionConfirmed(): void {
		if ( $this->bulkAction == 'delete' ) {
			LicenseKey::whereIn( 'id', $this->bulkItems )->delete();

			Log::add( '111', Auth::id(), request()->ip(), [ 'license-key-ids' => $this->bulkItems ] );

			$this->bulkAction = '';
			$this->bulkItems  = [];
		}

		if ( $this->bulkAction == 'change-status' && in_array( $this->bulkActionStatus, array_keys( LicenseKey::getStatuses() ) ) ) {
			LicenseKey::whereIn( 'id', $this->bulkItems )->update( [ 'status' => $this->bulkActionStatus ] );

			Log::add( '112', Auth::id(), request()->ip(), [ 'license-key-ids' => $this->bulkItems ] );

			$this->bulkAction       = '';
			$this->bulkActionStatus = '';
			$this->bulkItems        = [];
		}

		$this->dispatchBrowserEvent( 'close-confirm-bulk-action' );
		$this->dispatchBrowserEvent( 'reset-bulk-input' );
	}

	public function render() {
		$statuses = LicenseKey::getStatuses();

		return view( 'livewire.license-keys.manage', [
			'licenseKeys' => LicenseKey::where( function ( $q ) use ( $statuses ) {
				if ( $this->filterLicenseKey != '' ) {
					$q->where( 'license_key', 'like', '%' . $this->filterLicenseKey . '%' );
				}

				if ( $this->filterOwnerName != '' ) {
					$q->where( 'owner_name', 'like', '%' . $this->filterOwnerName . '%' );
				}

				if ( $this->filterOwnerEmail != '' ) {
					$q->where( 'owner_email', 'like', '%' . $this->filterOwnerEmail . '%' );
				}

				if ( (int) $this->filterProductId > 0 ) {
					$q->where( 'product_id', $this->filterProductId );
				}

				if ( in_array( $this->filterStatus, array_keys( $statuses ) ) ) {
					$q->where( 'status', $this->filterStatus );
				}
			} )->orderBy( 'id', 'DESC' )->paginate( getOption( 'ui', 'itemsPerTable', 10 ) ),
			'statuses'    => $statuses
		] );
	}
}
