<?php
/*
 * LaraClassifier - Classified Ads Web Application
 * Copyright (c) BeDigit. All Rights Reserved
 *
 * Website: https://laraclassifier.com
 * Author: Mayeul Akpovi (BeDigit - https://bedigit.com)
 *
 * LICENSE
 * -------
 * This software is provided under a license agreement and may only be used or copied
 * in accordance with its terms, including the inclusion of the above copyright notice.
 * As this software is sold exclusively on CodeCanyon,
 * please review the full license details here: https://codecanyon.net/licenses/standard
 */

namespace App\Http\Controllers\Web\Admin;

use App\Http\Controllers\Web\Admin\Panel\PanelController;
use App\Http\Requests\Admin\Request as StoreRequest;
use App\Http\Requests\Admin\Request as UpdateRequest;
use App\Models\Package;
use App\Models\Payment;
use App\Models\PaymentMethod;
use App\Models\Post;
use App\Models\User;
use Illuminate\Http\RedirectResponse;

class PaymentController extends PanelController
{
	protected ?string $type = '';
	protected bool $isPromoPackage = false;
	protected bool $isSubsPackage = false;
	
	public function setup()
	{
		$this->type = request()->segment(3);
		$this->isPromoPackage = ($this->type == 'promotion');
		$this->isSubsPackage = ($this->type == 'subscription');
		
		$withRelation = [
			'payable',
			'payable.country',
			'package',
			'paymentMethod',
		];
		if ($this->isPromoPackage) {
			$withRelation = array_merge($withRelation, ['payable.user']);
		}
		
		/*
		|--------------------------------------------------------------------------
		| BASIC CRUD INFORMATION
		|--------------------------------------------------------------------------
		*/
		$this->xPanel->setModel(Payment::class);
		$this->xPanel->addClause('where', fn ($query) => $query->{$this->type}());
		$this->xPanel->with($withRelation);
		$this->xPanel->setRoute(urlGen()->adminUri('payments/' . $this->type));
		$this->xPanel->setEntityNameStrings(trans('admin.payment'), trans('admin.payments'));
		$this->xPanel->denyAccess(['create', 'update', 'delete']);
		$this->xPanel->removeAllButtons(); // Remove also: 'create' & 'reorder' buttons
		if (!request()->input('order')) {
			$this->xPanel->orderByDesc('created_at');
		}
		
		/*
		|--------------------------------------------------------------------------
		| COLUMNS
		|--------------------------------------------------------------------------
		*/
		if ($this->onIndexPage) {
			// Filters
			$this->xPanel->disableSearchBar();
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'id',
					'type'  => 'text',
					'label' => 'ID',
				],
				filterLogic: function ($value) {
					$this->xPanel->addClause('where', 'id', '=', $value);
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'from_to',
					'type'  => 'date_range',
					'label' => trans('admin.Date range'),
				],
				filterLogic: function ($value) {
					$dates = json_decode($value);
					$this->xPanel->addClause('where', 'created_at', '>=', $dates->from);
					$this->xPanel->addClause('where', 'created_at', '<=', $dates->to);
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'        => 'country',
					'type'        => 'select2',
					'label'       => mb_ucfirst(trans('admin.country')),
					'placeholder' => trans('admin.select'),
				],
				values: getCountries(),
				filterLogic: function ($value) {
					$payableClass = ($this->isPromoPackage) ? Post::class : User::class;
					
					$this->xPanel->addClause('whereHasMorph', 'payable', $payableClass, function ($query) use ($value) {
						$query->where('country_code', '=', $value);
					});
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'payable_id',
					'type'  => 'text',
					'label' => $this->isPromoPackage ? trans('admin.Listing') : mb_ucfirst(trans('admin.user')),
				],
				filterLogic: function ($value) {
					if (is_numeric($value) || isHashedId($value)) {
						$value = hashId($value, true) ?? $value;
						$this->xPanel->addClause('where', 'payable_id', '=', $value);
					} else {
						$payableClass = ($this->isPromoPackage) ? Post::class : User::class;
						$column = ($this->isPromoPackage) ? 'title' : 'name';
						
						$this->xPanel->addClause('whereHasMorph', 'payable', $payableClass, function ($query) use ($column, $value) {
							$query->where($column, 'like', $value . '%');
						});
					}
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'package',
					'type'  => 'dropdown',
					'label' => trans('admin.Package'),
				],
				values: $this->getPackages(),
				filterLogic: function ($value) {
					$this->xPanel->addClause('where', 'package_id', '=', $value);
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'payment_method',
					'type'  => 'dropdown',
					'label' => trans('admin.Payment Method'),
				],
				values: $this->getPaymentMethods(),
				filterLogic: function ($value) {
					$this->xPanel->addClause('where', 'payment_method_id', '=', $value);
				}
			);
			
			$this->xPanel->addFilter(
				options: [
					'name'  => 'status',
					'type'  => 'dropdown',
					'label' => trans('admin.Status'),
				],
				values: [
					'pending' => trans('global.pending'),
					'onHold'  => trans('global.onHold'),
					'valid'   => trans('global.valid'),
					'expired' => trans('global.expired'),
					// 'canceled' => trans('global.canceled'),
					// 'refunded' => trans('global.refunded'),
				],
				filterLogic: function ($value) {
					if ($value == 'pending') {
						$this->xPanel->addClause('where', function ($query) {
							$query->where(function ($query) {
								$query->valid()->orWhere(fn ($query) => $query->onHold());
							})->columnIsEmpty('active');
						});
					}
					if ($value == 'onHold') {
						$this->xPanel->addClause('where', function ($query) {
							$query->onHold()->isActive();
						});
					}
					if ($value == 'valid') {
						$this->xPanel->addClause('where', function ($query) {
							$query->valid()->isActive();
						});
					}
					if ($value == 'expired') {
						$this->xPanel->addClause('where', function ($query) {
							$query->where(function ($query) {
								$query->notValid()->where(fn ($query) => $query->columnIsEmpty('active'));
							})->orWhere(fn ($query) => $query->notValid());
						});
					}
					if ($value == 'canceled') {
						$this->xPanel->addClause('where', fn ($query) => $query->canceled());
					}
					if ($value == 'refunded') {
						$this->xPanel->addClause('where', fn ($query) => $query->refunded());
					}
				}
			);
			
			if (config('addons.offlinepayment.installed')) {
				$this->xPanel->addFilter(
					options: [
						'name'  => 'payment_type',
						'type'  => 'dropdown',
						'label' => trans('admin.type'),
					],
					values: [
						'real' => trans('admin.real_payment'),
						'fake' => trans('admin.fake_payment'),
					],
					filterLogic: function ($value) {
						if ($value == 'real') {
							$this->xPanel->addClause('where', fn ($query) => $query->notManuallyCreated());
						}
						if ($value == 'fake') {
							$this->xPanel->addClause('where', fn ($query) => $query->manuallyCreated());
						}
					}
				);
			}
			
			// COLUMNS
			$this->xPanel->addColumn([
				'name'  => 'id',
				'label' => "ID",
			]);
			
			$this->xPanel->addColumn([
				'name'  => 'created_at',
				'label' => trans('admin.Date'),
			]);
			
			$this->xPanel->addColumn([
				'name'          => 'payable_id',
				'label'         => $this->isPromoPackage ? trans('admin.Listing') : mb_ucfirst(trans('admin.user')),
				'type'          => 'model_function',
				'function_name' => 'crudPayableTitleColumn',
			]);
			
			$this->xPanel->addColumn([
				'name'          => 'package_id',
				'label'         => trans('admin.Package'),
				'type'          => 'model_function',
				'function_name' => 'crudPackageNameColumn',
			]);
			
			$this->xPanel->addColumn([
				'name'          => 'payment_method_id',
				'label'         => trans('admin.Payment Method'),
				'type'          => 'model_function',
				'function_name' => 'crudPaymentMethodNameColumn',
			]);
			
			$this->xPanel->addColumn([
				'name'          => 'amount',
				'label'         => trans('admin.amount'),
				'type'          => 'model_function',
				'function_name' => 'crudAmountColumn',
			]);
			
			$this->xPanel->addColumn([
				'name'          => 'active',
				'label'         => trans('admin.Approved'),
				'type'          => 'model_function',
				'function_name' => 'crudActiveColumn',
			]);
		}
		
		/*
		|--------------------------------------------------------------------------
		| FIELDS
		|--------------------------------------------------------------------------
		*/
		// if ($this->onCreatePage || $this->onEditPage) {}
	}
	
	public function store(StoreRequest $request): RedirectResponse
	{
		return parent::storeCrud($request);
	}
	
	public function update(UpdateRequest $request): RedirectResponse
	{
		return parent::updateCrud($request);
	}
	
	// PRIVATE
	
	private function getPackages(): array
	{
		$entries = Package::query()
			->{$this->type}()
			->where('price', '>', 0)
			->orderBy('currency_code')
			->orderBy('lft')
			->get();
		
		$array = [];
		if ($entries->count() > 0) {
			foreach ($entries as $entry) {
				$array[$entry->id] = $entry->name . ' (' . $entry->price . ' ' . $entry->currency_code . ')';
			}
		}
		
		return $array;
	}
	
	private function getPaymentMethods(): array
	{
		$entries = PaymentMethod::query()->orderBy('lft')->get();
		
		$array = [];
		if ($entries->count() > 0) {
			foreach ($entries as $entry) {
				$array[$entry->id] = $entry->display_name;
			}
		}
		
		return $array;
	}
}
