<?php

namespace WKO\Controllers\Menus;

use WKO\Controllers\Logs;
use WKO\Controllers\Render;
use WKO\Model\Entity\InstallmentRule;
use WKO\Model\Repository\InstallmentRules;

class Installments extends Render
{
	protected array $fields;
	protected $logger;

	public function __construct()
	{
		$this->logger = new Logs();
		$this->saveFields();
	}

	public function KoinSettingsFields()
	{

		$fields = [
			'section_title' => [
				'name' => __('Koin Installment Rules - Credit Card', 'wc-koin-official'),
				'type' => 'title',
				'desc' => '',
				'id'   => 'wc_koin_installments_section_title'
			],
			'enable_rule' => [
				'title' => __('Enable Rule', 'wc-koin-official'),
				'type' => 'checkbox',
				'id'   => 'wc_koin_enable_rule'
			],
			'override_rules' => [
				'title' => __('Override another rules', 'wc-koin-official'),
				'type' => 'checkbox',
				'desc' => __('By checking this box, this rule will override all other rules and will be the only one applied if the conditions are met. If left unchecked, this rule will be combined with other rules that meet the checkout parameters.', 'wc-koin-official'),
				'id'   => 'wc_koin_override_rules'
			],
			'rule_title' => [
				'title' => __('Rule Title', 'wc-koin-official'),
				'type' => 'text',
				'custom_attributes' => [
					'required' => 'required'
				],
				'id'   => 'wc_koin_rule_title'
			],
			'installment_display' => [
				'title' => __('Installment Display', 'wc-koin-official'),
				'type' => 'text',
				'desc' => __('Define how the installments will be displayed on checkout. Leave the field blank for default display.', 'wc-koin-official'),
				'id'   => 'wc_koin_installment_display'
			],
			'account_number' => [
				'title' => __('Account Number', 'wc-koin-official'),
				'type' => 'text',
				'id'   => 'wc_koin_account_number',
				'desc' => __("Fill if that rule uses a different account number, otherwise it's not necessary", 'wc-koin-official'),
			],
			'min_installments' => [
				'title' => __('Min installments quantity', 'wc-koin-official'),
				'type' => 'number',
				'id'   => 'wc_koin_min_installments',
				'custom_attributes' => [
					'min' => 0,
					'max' => 72
				]
			],
			'max_installments' => [
				'title' => __('Max installments quantity', 'wc-koin-official'),
				'type' => 'number',
				'id'   => 'wc_koin_max_installments',
				'custom_attributes' => [
					'min' => 0,
					'max' => 72
				]
			],
			'min_installment_value' => [
				'title' => __('Minimum Installment Value', 'wc-koin-official'),
				'type' => 'text',
				'id'   => 'wc_koin_min_installment_value'
			],
			"rate_transfer_type" => [
				'title'       => __('Rate Transfer Type', 'wc-koin-official'),
				'type'        => 'select',
				'desc'        => __('Select the credit card interest charging type (simple or by installment)', 'wc-koin-official'),
				'class'       => 'wko-rate-transfer-type',
				'options'     => [
					0 => __('Disabled', 'wc-koin-official'),
					1 => __('Simple', 'wc-koin-official'),
					2 => __('By Installment', 'wc-koin-official')
				],
				'id'          => 'wc_koin_rate_transfer_type'
			],

			"rate_transfer_format" => [
				'title'       => __('Rate Transfer Format', 'wc-koin-official'),
				'type'        => 'select',
				'desc'        => __('Select the credit card interest charging format (percentage or fixed rate)', 'wc-koin-official'),
				'class'       => 'wko-rate-transfer-format',
				'options'     => [
					1 => __('Percentage (%)', 'wc-koin-official'),
					2 => __('Fixed Value (R$)', 'wc-koin-official')
				],
				'id'          => 'wc_koin_rate_transfer_format'
			],

			"rate_transfer_simple" => [
				'title'       => __('Rate Value', 'wc-koin-official'),
				'type'        => 'text',
				'class'       => 'wko-rate-simple-value',
				'desc'        => __('In this option you can define the rate value.', 'wc-koin-official'),
				'placeholder' => '0',
				'id'          => 'wc_koin_rate_transfer_simple'
			],
			"rate_transfer_by_installments" => [
				'title'       => __('Rate value by installment', 'wc-koin-official'),
				'type'        => 'text',
				'class'       => 'wko-rate-by-installments-value',
				'desc'        => __('In this option you can define the fee amount for each installment.', 'wc-koin-official'),
				'default'     => json_encode(array_fill(1, 72, '0.00')),
				'id'          => 'wc_koin_rate_transfer_by_installments'
			],
			'start_date' => [
				'title' => __('Start Date', 'wc-koin-official'),
				'type' => 'datetime-local',
				'id'   => 'wc_koin_start_date',
				'custom_attributes' => [
					'required' => 'required'
				],
			],
			'end_date' => [
				'title' => __('End Date', 'wc-koin-official'),
				'type' => 'datetime-local',
				'id'   => 'wc_koin_end_date'
			],
			'payment_method_bins' => [
				'title' => __('Payment Method Bins', 'wc-koin-official'),
				'type' => 'textarea',
				'id'   => 'wc_koin_payment_method_bins',
				'custom_attributes' => [
					'rows' => 5
				],
				'desc' => __("It's possible to add the Credit Card BINs separated with a pipe, like: '555566|444433', or add a regex with the required BINs", 'wc-koin-official')
			],
			'exclude_payment_method_bins' => [
				'title' => __('Payment Method Bins to exclude', 'wc-koin-official'),
				'type' => 'textarea',
				'id'   => 'wc_koin_exclude_payment_method_bins',
				'custom_attributes' => [
					'rows' => 5
				],
				'desc' => __("Adding Credit Card BINs, like: '555566|444433', or add a regex with the required BINs, those BINs will deny the rule, applying the rule only if the BINs do not match this field", 'wc-koin-official')
			],

			'card_brands' => [
				'title' => __('Card Brands', 'wc-koin-official'),
				'type'     => 'multiselect',
				'desc'     => __('Select the card brands that are applicable.', 'wc-koin-official'),
				'class'    => 'wko-card-brands wc-enhanced-select',
				'options'  => [
					'VI' => __('Visa', 'wc-koin-official'),
					'CA' => __('MasterCard', 'wc-koin-official'),
					'AX' => __('American Express', 'wc-koin-official'),
					'DS' => __('Discover', 'wc-koin-official'),
					'JCB' => __('JCB', 'wc-koin-official'),
					'DC' => __('Diners Club', 'wc-koin-official'),
					'EC' => __('Elo', 'wc-koin-official'),
					'HC' => __('Hipercard', 'wc-koin-official'),
				],
				'id' => 'wc_koin_card_brands'
			],
			'products' => [
				'title' => __('Products', 'wc-koin-official'),
				'type'     => 'multiselect',
				'desc'     => __('Select the products that are applicable. Leave the field blank to apply to all products.', 'wc-koin-official'),
				'class'    => 'wko-products wc-enhanced-select',
				'options'  => $this->getProductOptions(),
				'id' => 'wc_koin_products'
			],
			'brands' => [
				'title' => __('Brands', 'wc-koin-official'),
				'type'     => 'multiselect',
				'desc'     => __('Select the product brands that are applicable. Leave the field blank to apply to all brands.', 'wc-koin-official'),
				'class'    => 'wko-brands wc-enhanced-select',
				'options'  => $this->getBrandOptions(),
				'id' => 'wc_koin_brands'
			],
			'categories' => [
				'title' => __('Categories', 'wc-koin-official'),
				'type'     => 'multiselect',
				'desc'     => __('Select the product categories that are applicable. Leave the field blank to apply to all categories.', 'wc-koin-official'),
				'class'    => 'wko-categories wc-enhanced-select',
				'options'  => $this->getCategoryOptions(),
				'id' => 'wc_koin_categories'
			],
			'submit_button' => [
				'type' => 'submit',
				'name' => __('Save Changes', 'wc-koin-official'),
				'class' => 'button-primary',
				'id'   => 'wc_koin_submit_button'
			],
			'section_end' => [
				'type' => 'sectionend',
				'id'   => 'wc_koin_section_end'
			]
		];

		return apply_filters('wc_koin_tab_settings', $fields);
	}

	public function request(): void
	{
		$rule_id = isset($_GET['rule_id']) ? intval(wp_unslash($_GET['rule_id'])) : null;
		$action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : '';
		$repository = new InstallmentRules();


		if ($action) {
			$this->handleActionRequest($action, $rule_id);
		} else {
			$this->handleDefaultRequest($repository);
		}
	}

	public function saveFields()
	{
		$action = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_SPECIAL_CHARS);

		if (!$action || !in_array($action, ['edit_rule', 'create_rule'])) {
			return;
		}

		$this->validateNonce();

		$rule_id = filter_input(INPUT_POST, 'rule_id', FILTER_SANITIZE_NUMBER_INT);

		if ($action === 'edit_rule' && !$rule_id) {
			wp_die(__('Rule ID is missing', 'wc-koin-official'));
		}

		$fields = $this->KoinSettingsFields();
		$sanitized_data = $this->sanitizeFields($fields);

		$this->validateRequiredFields($fields, $sanitized_data);

		$repository = new InstallmentRules();
		$rule = $action === 'edit_rule' ? $repository->findById($rule_id) : new InstallmentRule();

		$this->assignRuleValues($rule, $sanitized_data);

		$repository->save($rule);

		// Log the changes
		$user = wp_get_current_user();
		$this->logger->log_installment_rule_changes(
			sprintf(__('Rule %s by %s', 'wc-koin-official'), $action === 'edit_rule' ? __('edited', 'wc-koin-official') : __('created', 'wc-koin-official'), $user->user_login),
			[
				'rule_id' => $rule_id,
				'data' => json_encode($rule),
				'user_id' => $user->ID,
				'user_login' => $user->user_login
			]
		);

		$product_id = filter_input(INPUT_POST, 'product_id', FILTER_SANITIZE_SPECIAL_CHARS);
		if ($product_id) {
			$this->redirect(get_edit_post_link($product_id, ''));
		} else {
			$this->redirect('admin.php?page=wc-koin-official-installments');
		}
	}

	private function validateNonce()
	{
		$nonce = isset($_REQUEST['koin_settings_nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['koin_settings_nonce'])) : '';

		if (!wp_verify_nonce($nonce, 'save_koin_settings')) {
			wp_die(__('Nonce verification failed', 'wc-koin-official'));
		}
	}

	private function sanitizeFields(array $fields): array
	{
		$sanitized_data = [];

		foreach ($fields as $field) {
			$field_id = $field['id'];
			$field_value = filter_input(INPUT_POST, $field_id, FILTER_SANITIZE_SPECIAL_CHARS);

			if ($field['type'] === 'checkbox') {
				$field_value = $field_value ? 'yes' : 'no';
			} elseif ($field['type'] === 'number') {
				$field_value = filter_input(INPUT_POST, $field_id, FILTER_SANITIZE_NUMBER_INT);
			} elseif ($field['type'] === 'date') {
				$field_value = sanitize_text_field($field_value);
			} elseif ($field['type'] === 'textarea') {
				$field_value = sanitize_textarea_field($field_value);
			} elseif ($field['type'] === 'multiselect') {
				$field_value = filter_input(INPUT_POST, $field_id, FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
				if (is_array($field_value)) {
					$field_value = array_map('sanitize_text_field', $field_value);
				}
			} else {
				$field_value = sanitize_text_field($field_value);
			}

			$sanitized_data[$field_id] = $field_value;
		}

		return $sanitized_data;
	}

	private function validateRequiredFields(array $fields, array $sanitized_data): void
	{
		foreach ($fields as $field) {
			if (isset($field['custom_attributes']['required']) && empty($sanitized_data[$field['id']])) {
				wp_die(sprintf(__('The field %s is required', 'wc-koin-official'), $field['title']));
			}
		}
	}

	private function handleActionRequest(string $action, ?int $rule_id): void
	{
		$product_id = isset($_GET['product_id']) ? sanitize_text_field(wp_unslash($_GET['product_id'])) : '';

		switch ($action) {
			case 'delete_rule':
				$this->deleteRule($rule_id, $product_id);
				break;
			case 'edit_rule':
				$this->editRule($rule_id, $product_id);
				break;
			case 'create_rule':
				$fields = $this->KoinSettingsFields();
				if ($product_id) {
					$fields['products']['default'] = [$product_id];
				}
				$this->render('/Admin/menus/installments/rule.php', [
					'fields' => $fields,
					'rule_id' => 'new',
					'action' => 'create_rule',
					'product_id' => $product_id
				]);
				break;
			default:
				break;
		}
	}

	private function handleDefaultRequest(InstallmentRules $repository): void
	{
		$rules = $repository->findAll('updated_at', 'DESC');
		$this->render('/Admin/menus/installments/index.php', [
			'rules' => $rules['rows']
		]);
	}

	private function editRule(int $rule_id, ?string $product_id): void
	{
		$repository = new InstallmentRules();
		$rule = $repository->findById($rule_id);

		if (!$rule) {
			wp_die(__('Rule not found', 'wc-koin-official'));
		}

		$fields = $this->koinSettingsFields();
		$values = $this->getRuleValues($rule);

		foreach ($fields as &$field) {
			$field_id = $field['id'];
			if (isset($values[$field_id])) {
				$field['value'] = $values[$field_id];
			}
		}

		$this->render('/Admin/menus/installments/rule.php', [
			'fields' => $fields,
			'rule_id' => $rule_id,
			'action' => 'edit_rule',
			'product_id' => $product_id
		]);
	}

	private function deleteRule(?int $rule_id, ?string $product_id): void
	{
		$this->validateNonce();

		if (!$rule_id) {
			wp_die(__('Rule ID is missing', 'wc-koin-official'));
		}

		$repository = new InstallmentRules();
		$rule = $repository->findById($rule_id);

		// Log the deletion
		$user = wp_get_current_user();
		$this->logger->log_installment_rule_changes(
			sprintf(__('Rule deleted by %s', 'wc-koin-official'), $user->user_login),
			[
				'rule_id' => $rule_id,
				'data' => json_encode($rule),
				'user_id' => $user->ID,
				'user_login' => $user->user_login
			]
		);

		$repository->delete($rule_id);

		if ($product_id) {
			$this->redirect(get_edit_post_link($product_id, ''));
		} else {
			$this->redirect('admin.php?page=wc-koin-official-installments');
		}
	}

	private function getRuleValues(InstallmentRule $rule): array
	{
		return [
			'rule_id'                               => $rule->id,
			'wc_koin_enable_rule'                   => $rule->enableRule ? 'yes' : 'no',
			'wc_koin_override_rules'                => $rule->overrideRules ? 'yes' : 'no',
			'wc_koin_rule_title'                    => $rule->ruleTitle,
			'wc_koin_account_number'                => $rule->accountNumber,
			'wc_koin_min_installments'              => $rule->minInstallments,
			'wc_koin_max_installments'              => $rule->maxInstallments,
			'wc_koin_min_installment_value'         => $rule->minInstallmentValue,
			'wc_koin_rate_transfer_type'            => $rule->rateTransferType,
			'wc_koin_rate_transfer_format'          => $rule->rateTransferFormat,
			'wc_koin_rate_transfer_simple'          => $rule->rateTransferSimple,
			'wc_koin_rate_transfer_by_installments' => $rule->rateTransferByInstallments,
			'wc_koin_installment_display'           => $rule->installmentDisplay ?? '',
			'wc_koin_start_date'                    => $rule->startDate ? $rule->startDate->format('Y-m-d H:i:s') : '',
			'wc_koin_end_date'                      => $rule->endDate ? $rule->endDate->format('Y-m-d H:i:s') : '',
			'wc_koin_payment_method_bins'           => $rule->paymentMethodBins,
			'wc_koin_exclude_payment_method_bins'   => $rule->excludePaymentMethodBins,
			'wc_koin_card_brands'                   => json_decode($rule->cardBrands, true),
			'wc_koin_products'                      => json_decode($rule->products, true),
			'wc_koin_brands'                        => json_decode($rule->brands, true),
			'wc_koin_categories'                    => json_decode($rule->categories, true),
		];
	}

	private function assignRuleValues(InstallmentRule $rule, array $sanitized_data): void
	{
		$rule->enableRule                 = isset($sanitized_data['wc_koin_enable_rule']) ? $sanitized_data['wc_koin_enable_rule'] === 'yes' : false;
		$rule->overrideRules              = isset($sanitized_data['wc_koin_override_rules']) ? $sanitized_data['wc_koin_override_rules'] === 'yes' : false;
		$rule->ruleTitle                  = $sanitized_data['wc_koin_rule_title'] ?? '';
		$rule->accountNumber              = $sanitized_data['wc_koin_account_number'] ?? '';
		$rule->minInstallments            = isset($sanitized_data['wc_koin_min_installments']) ? (int)$sanitized_data['wc_koin_min_installments'] : null;
		$rule->maxInstallments            = isset($sanitized_data['wc_koin_max_installments']) ? (int)$sanitized_data['wc_koin_max_installments'] : null;
		$rule->minInstallmentValue        = isset($sanitized_data['wc_koin_min_installment_value']) ? (float)$sanitized_data['wc_koin_min_installment_value'] : null;
		$rule->rateTransferType           = isset($sanitized_data['wc_koin_rate_transfer_type']) ? (int)$sanitized_data['wc_koin_rate_transfer_type'] : null;
		$rule->rateTransferFormat         = isset($sanitized_data['wc_koin_rate_transfer_format']) ? (int)$sanitized_data['wc_koin_rate_transfer_format'] : null;
		$rule->rateTransferSimple         = $sanitized_data['wc_koin_rate_transfer_simple'] ?: 0;
		$rule->rateTransferByInstallments = $sanitized_data['wc_koin_rate_transfer_by_installments'] ?? '';
		$rule->installmentDisplay         = $sanitized_data['wc_koin_installment_display'] ?? '';
		$rule->startDate                  = $sanitized_data['wc_koin_start_date'] ? new \DateTime($sanitized_data['wc_koin_start_date']) : null;
		$rule->endDate                    = $sanitized_data['wc_koin_end_date'] ? new \DateTime($sanitized_data['wc_koin_end_date']) : null;
		$rule->paymentMethodBins          = $sanitized_data['wc_koin_payment_method_bins'] ?? '';
		$rule->excludePaymentMethodBins   = $sanitized_data['wc_koin_exclude_payment_method_bins'] ?? '';
		$rule->cardBrands                 = $sanitized_data['wc_koin_card_brands'] ? wp_json_encode($sanitized_data['wc_koin_card_brands']) : '';
		$rule->products                   = $sanitized_data['wc_koin_products'] ? wp_json_encode($sanitized_data['wc_koin_products']) : '';
		$rule->brands                     = $sanitized_data['wc_koin_brands'] ? wp_json_encode($sanitized_data['wc_koin_brands']) : '';
		$rule->categories                 = $sanitized_data['wc_koin_categories'] ? wp_json_encode($sanitized_data['wc_koin_categories']) : '';
	}

	/**
	 * Get product options for multiselect
	 */
	private function getProductOptions(): array
	{
		$products = wc_get_products([
			'status' => 'publish',
			'limit' => -1,
			'orderby' => 'name',
			'order' => 'ASC'
		]);

		$options = [];
		foreach ($products as $product) {
			$options[$product->get_id()] = $product->get_name();
		}

		return $options;
	}

	/**
	 * Get brand options for multiselect
	 */
	private function getBrandOptions(): array
	{
		return get_terms([
			'taxonomy' => 'product_brand',
			'hide_empty' => false,
			'orderby' => 'name',
			'order' => 'ASC',
			'fields' => 'id=>name'
		]);
	}

	/**
	 * Get category options for multiselect
	 */
	private function getCategoryOptions(): array
	{
		return get_terms([
			'taxonomy' => 'product_cat',
			'hide_empty' => false,
			'orderby' => 'name',
			'order' => 'ASC',
			'fields' => 'id=>name'

		]);
	}
}
