/* global console, Klarna */
jQuery( function ( $ ) {
	"use strict"

	var klarna_payments = {
		authorization_response: {},
		iframe_loaded: false,
		show_form: false,
		klarna_container_selector: "#klarna_container_2",
		checkout_values: {},
		addresses: {},
		log: ( ...args ) => {
			if ( klarna_payments_params.debug ) {
				console.log( ...args )
			}
		},

		check_changes: function () {
			$(
				".woocommerce-billing-fields input, .woocommerce-billing-fields select, .woocommerce-shipping-fields input, .woocommerce-shipping-fields select",
			).each( function () {
				var fieldName = $( this ).attr( "name" )
				var fieldValue = $( this ).val()
				if ( klarna_payments.checkout_values[ fieldName ] !== fieldValue ) {
					klarna_payments.checkout_values[ fieldName ] = fieldValue
					$( this ).trigger( "change" )
				}
			} )
		},

		debounce_changes: function ( func, wait, immediate ) {
			var timeout
			return function () {
				var context = this,
					args = arguments
				var later = function () {
					timeout = null
					if ( ! immediate ) func.apply( context, args )
				}
				var callNow = immediate && ! timeout
				clearTimeout( timeout )
				timeout = setTimeout( later, wait )
				if ( callNow ) func.apply( context, args )
			}
		},

		start: function () {
			// Store all billing and shipping values.
			$( document ).ready( function () {
				$( "#customer_details input, #customer_details select" ).each( function () {
					var fieldName = $( this ).attr( "name" )
					var fieldValue = $( this ).val()
					klarna_payments.checkout_values[ fieldName ] = fieldValue
				} )
				if ( klarna_payments.isKlarnaPaymentsSelected() ) {
					klarna_payments.initKlarnaCredit()
					klarna_payments.load().then( klarna_payments.loadHandler )
				}
			} )

			/**
			 * When WooCommerce updates checkout
			 * Happens on initial page load, country, state and postal code changes
			 */
			$( "body" ).on( "updated_checkout", function () {
				// Unblock the payments element if blocked
				var blocked_el = $( ".woocommerce-checkout-payment" )
				var blocked_el_data = blocked_el.data()
				if ( blocked_el.length && 1 === blocked_el_data[ "blockUI.isBlocked" ] ) {
					blocked_el.unblock()
				}

				// Check if we need to hide the shipping fields
				klarna_payments.maybeHideShippingAddress()

				if ( klarna_payments.isKlarnaPaymentsSelected() ) {
					klarna_payments.initKlarnaCredit()
					klarna_payments.load().then( klarna_payments.loadHandler )
				}
			} )

			/**
			 * Clear auth token if there's checkout error.
			 */
			$( document.body ).on( "checkout_error", function () {
				$( 'input[name="klarna_payments_authorization_token"]' ).remove()
			} )

			/**
			 * Phone field changes. Has to be 5 characters or longer for KP to work.
			 */
			$( "form.checkout" ).on(
				"keyup",
				"#billing_phone",
				klarna_payments.debounce_changes( function () {
					if ( klarna_payments.isKlarnaPaymentsSelected() ) {
						//$('#place_order').attr('disabled', true);
						if ( $( this ).val().length > 4 ) {
							klarna_payments.initKlarnaCredit()
							klarna_payments.load().then( klarna_payments.loadHandler )
						}
					}
				}, 750 ),
			)

			/**
			 * Email field changes, check if WooCommerce says field is valid.
			 */
			$( "form.checkout" ).on(
				"keyup",
				"#billing_email",
				klarna_payments.debounce_changes( function () {
					if ( klarna_payments.isKlarnaPaymentsSelected() ) {
						//$('#place_order').attr('disabled', true);
						if ( ! $( this ).parent().hasClass( "woocommerce-invalid" ) ) {
							klarna_payments.initKlarnaCredit()
							klarna_payments.load().then( klarna_payments.loadHandler )
						}
					}
				}, 750 ),
			)

			/**
			 * Billing company field changes.
			 */
			$( "form.checkout" ).on(
				"keyup",
				"#billing_company",
				klarna_payments.debounce_changes( function () {
					if ( klarna_payments.isKlarnaPaymentsSelected() ) {
						klarna_payments.initKlarnaCredit()
						klarna_payments.load().then( klarna_payments.loadHandler )
					}
				}, 750 ),
			)

			/**
			 * When changing payment method.
			 */
			$( "body" ).on( "change", 'input[name="payment_method"]', function () {
				// If Klarna Payments is selected and iframe is not loaded yet, disable the form. Also collapse any unselected Klarna Payments gateways.
				if ( klarna_payments.isKlarnaPaymentsSelected() ) {
					klarna_payments.initKlarnaCredit()
					klarna_payments.load().then( klarna_payments.loadHandler )
					klarna_payments.collapseGateways()
				}

				// Enable the form if any other payment method is selected.
				if ( ! klarna_payments.isKlarnaPaymentsSelected() ) {
					$( "#place_order" ).attr( "disabled", false )
				}

				// Check if we need to hide the shipping fields
				klarna_payments.maybeHideShippingAddress()
			} )
		},

		load: function () {
			var $defer = $.Deferred()

			// Dont run load during checkout completion.
			if ( $( "form.checkout" ).hasClass( "processing" ) ) {
				return $defer.reject()
			}

			var klarna_payments_container_selector_id = "#" + klarna_payments.getSelectorContainerID()
			klarna_payments.log( klarna_payments_container_selector_id )

			if ( klarna_payments_container_selector_id ) {
				var klarnaLoadedInterval = setInterval( function () {
					var Klarna = false

					try {
						Klarna = window.Klarna
					} catch ( e ) {
						klarna_payments.log( e )
					}

					if ( Klarna && Klarna.Payments ) {
						clearInterval( klarnaLoadedInterval )
						clearTimeout( klarnaLoadedTimeout )

						var options = {
							container: klarna_payments_container_selector_id,
							payment_method_category:
								klarna_payments.getSelectedPaymentCategory() === "klarna_payments"
									? ""
									: klarna_payments.getSelectedPaymentCategory(),
						}

						if ( "US" === $( "#billing_country" ).val() ) {
							var address = klarna_payments.get_address_from_checkout_form()

							Klarna.Payments.load( options, address, function ( response ) {
								$defer.resolve( response )
							} )
						} else {
							Klarna.Payments.load( options, function ( response ) {
								$defer.resolve( response )
							} )
						}
					}
				}, 100 )

				var klarnaLoadedTimeout = setTimeout( function () {
					clearInterval( klarnaLoadedInterval )
					$defer.reject()
				}, 3000 )

				return $defer.promise()
			}
		},

		loadHandler: function ( response ) {
			klarna_payments.iframe_loaded = true

			if ( response.show_form ) {
				klarna_payments.show_form = true
			}
		},

		isKlarnaPaymentsSelected: function () {
			if ( $( 'input[name="payment_method"]:checked' ).length ) {
				var selected_value = $( 'input[name="payment_method"]:checked' ).val()
				return selected_value.indexOf( "klarna_payments" ) !== -1
			}

			return false
		},

		isTermsAccepted: function () {
			if ( ! $( "#terms" ).length || $( "#terms" ).is( ":checked" ) ) {
				return true
			}

			return false
		},

		setRadioButtonValues: function () {
			$( 'input[name="payment_method"]' ).each( function () {
				if ( $( this ).val().indexOf( "klarna_payments" ) !== -1 ) {
					$( this ).val( "klarna_payments" )
				}
			} )
		},

		getSelectorContainerID: function () {
			var containerID = $( 'input[name="payment_method"]:checked' ).attr( "id" ).replace( "payment_method_", "" )

			return containerID + "_container"
		},

		getSelectedPaymentCategory: function () {
			var selected_category = $( 'input[name="payment_method"]:checked' )
				.attr( "id" )
				.replace( "payment_method_", "" )
			klarna_payments.log( selected_category )
			return selected_category.replace( "klarna_payments_", "" )
		},

		authorize: function () {
			var $defer = $.Deferred()
			var address = klarna_payments.get_address()

			klarna_payments.authorization_response = {}

			try {
				Klarna.Payments.authorize(
					address,
					{
						payment_method_category:
							klarna_payments.getSelectedPaymentCategory() === "klarna_payments"
								? ""
								: klarna_payments.getSelectedPaymentCategory(),
					},
					function ( response ) {
						klarna_payments.authorization_response = response
						$defer.resolve( response )
					},
				)
			} catch ( e ) {
				klarna_payments.logToFile( e )
			}

			return $defer.promise()
		},

		get_address: function () {
			var address = {
				billing_address: {
					given_name: klarna_payments.addresses.billing.given_name,
					family_name: klarna_payments.addresses.billing.family_name,
					email: klarna_payments.addresses.billing.email,
					phone: klarna_payments.addresses.billing.phone,
					country: klarna_payments.addresses.billing.country,
					region: klarna_payments.addresses.billing.region,
					postal_code: klarna_payments.addresses.billing.postal_code,
					city: klarna_payments.addresses.billing.city,
					street_address: klarna_payments.addresses.billing.street_address,
					street_address2: klarna_payments.addresses.billing.street_address2,
					organization_name:
						"b2b" === klarna_payments_params.customer_type
							? klarna_payments.addresses.billing.organization_name
							: "",
				},
				shipping_address: {},
			}

			address.shipping_address = $.extend( {}, address.billing_address )

			if ( $( "#ship-to-different-address" ).find( "input" ).is( ":checked" ) ) {
				address.shipping_address.given_name = klarna_payments.addresses.shipping.given_name
				address.shipping_address.family_name = klarna_payments.addresses.shipping.family_name
				address.shipping_address.country = klarna_payments.addresses.shipping.country
				address.shipping_address.region = klarna_payments.addresses.shipping.region
				address.shipping_address.postal_code = klarna_payments.addresses.shipping.postal_code
				address.shipping_address.city = klarna_payments.addresses.shipping.city
				address.shipping_address.street_address = klarna_payments.addresses.shipping.street_address
				address.shipping_address.street_address2 = klarna_payments.addresses.shipping.street_address2
			}

			return address
		},

		get_address_from_checkout_form: function () {
			var address = {
				billing_address: {
					given_name: klarna_payments.checkout_values.billing_first_name,
					family_name: klarna_payments.checkout_values.billing_last_name,
					email: klarna_payments.checkout_values.billing_email,
					phone: klarna_payments.checkout_values.billing_phone,
					country: klarna_payments.checkout_values.billing_country,
					region: klarna_payments.checkout_values.billing_state,
					postal_code: klarna_payments.checkout_values.billing_postcode,
					city: klarna_payments.checkout_values.billing_city,
					street_address: klarna_payments.checkout_values.billing_address_1,
					street_address2: klarna_payments.checkout_values.billing_address_2,
					organization_name:
						"b2b" === klarna_payments_params.customer_type
							? klarna_payments.checkout_values.billing_company
							: "",
				},
				shipping_address: {},
			}

			address.shipping_address = $.extend( {}, address.billing_address )

			if ( $( "#ship-to-different-address" ).find( "input" ).is( ":checked" ) ) {
				address.shipping_address.given_name = klarna_payments.checkout_values.shipping_first_name
				address.shipping_address.family_name = klarna_payments.checkout_values.shipping_last_name
				address.shipping_address.country = klarna_payments.checkout_values.shipping_country
				address.shipping_address.region = klarna_payments.checkout_values.shipping_state
				address.shipping_address.postal_code = klarna_payments.checkout_values.shipping_postcode
				address.shipping_address.city = klarna_payments.checkout_values.shipping_city
				address.shipping_address.street_address = klarna_payments.checkout_values.shipping_address_1
				address.shipping_address.street_address2 = klarna_payments.checkout_values.shipping_address_2
			}

			return address
		},

		collapseGateways: function () {
			$( 'input[name="payment_method"]' ).each( function () {
				if ( $( this ).is( ":checked" ) ) {
					$( this ).siblings( "div.payment_box" ).show()
				} else {
					$( this ).siblings( "div.payment_box" ).hide()
				}
			} )
		},

		maybeHideShippingAddress: function () {
			if ( false !== klarna_payments.isKlarnaPaymentsSelected() ) {
				if ( "b2b" === klarna_payments_params.customer_type ) {
					jQuery( "#customer_details .col-2" ).hide()
				}
			} else {
				jQuery( "#customer_details .col-2" ).show()
			}
		},

		initKlarnaCredit: function ( client_token ) {
			var client_token = klarna_payments.getClientToken()
			window.klarnaInitData = { client_token: client_token }
			Klarna.Payments.init( klarnaInitData )
		},

		printErrorMessage: function ( message ) {
			$( "#klarna-payments-error-notice" ).remove()
			const is_pay_for_order = true == klarna_payments_params.pay_for_order
			const $target = is_pay_for_order ? $( "div.woocommerce-notices-wrapper" ) : $( "form.checkout" )

			$target.prepend(
				'<div id="klarna-payments-error-notice" class="woocommerce-NoticeGroup"><ul class="woocommerce-error" role="alert"><li>' +
					message +
					"</li></ul></div>",
			)
			$.scroll_to_notices( $target )
		},

		authorizeKlarnaOrder: function ( order_id, order_key ) {
			klarna_payments.authorize().done( function ( response ) {
				if ( "authorization_token" in response ) {
					$( "body" ).trigger( "kp_auth_success" )
					$.ajax( klarna_payments_params.place_order_url, {
						type: "POST",
						dataType: "json",
						async: true,
						data: {
							order_key: order_key,
							order_id: order_id,
							auth_token: klarna_payments.authorization_response.authorization_token,
							nonce: klarna_payments_params.place_order_nonce,
						},
						success: function ( response ) {
							// Log the success.
							klarna_payments.log( "kp_place_order success" )
							klarna_payments.log( response )
						},
						error: function ( response ) {
							// Log the error.
							klarna_payments.logToFile( response )
						},
						complete: function ( response ) {
							if ( response.responseJSON.success === true ) {
								window.location.href = response.responseJSON.data
							} else {
								$( "form.checkout" ).removeClass( "processing" ).unblock()
								$( "form.checkout" )
									.find( ".input-text, select, input:checkbox" )
									.trigger( "validate" )
									.blur()
								$( "form.checkout" ).trigger( "update_checkout" )
							}
						},
					} )
				} else {
					$( "body" ).trigger( "kp_auth_failed" )

					// Re-enable the form.
					$( "body" ).trigger( "updated_checkout" )
					$( "form.checkout" ).removeClass( "processing" )
					$( "form.checkout" ).unblock()

					const reason = response.show_form ? "aborted by customer" : "rejected by Klarna"
					klarna_payments.logToFile(
						`(Order ${ order_id }): No authorization_token in response. Reason: ${ reason }.`,
					)
					$( "form.woocommerce-checkout" ).removeClass( "processing" ).unblock()
					$.ajax( klarna_payments_params.auth_failed_url, {
						type: "POST",
						dataType: "json",
						async: true,
						data: {
							show_form: response.show_form,
							order_key: order_key,
							order_id: order_id,
							nonce: klarna_payments_params.auth_failed_nonce,
						},
					} )
				}
			} )
		},

		klarnaPayForOrder: function ( event ) {
			if ( klarna_payments.isKlarnaPaymentsSelected() ) {
				event.preventDefault()

				if ( ! klarna_payments.isTermsAccepted() ) {
					klarna_payments.printErrorMessage( klarna_payments_params.i18n.terms_not_checked )
					return
				}

				klarna_payments.addresses = klarna_payments_params.addresses
				klarna_payments.authorizeKlarnaOrder(
					klarna_payments_params.order_id,
					klarna_payments_params.order_key,
				)
			}
		},

		getClientToken: function () {
			if ( $( "#kp_client_token" ).length > 0 ) {
				return $( "#kp_client_token" ).val()
			} else {
				return klarna_payments_params.client_token
			}
		},

		orderSubmit: function ( event ) {
			if ( klarna_payments.isKlarnaPaymentsSelected() ) {
				event.preventDefault()

				if ( $( "form.checkout" ).is( ".processing" ) ) {
					return false
				}

				$( "form.checkout" ).addClass( "processing" )
				$( "form.checkout" ).block( {
					message: null,
					overlayCSS: {
						background: "#fff",
						opacity: 0.6,
					},
				} )

				$.ajax( {
					type: "POST",
					url: klarna_payments_params.submit_order,
					data: $( "form.checkout" ).serialize(),
					dataType: "json",
					success: function ( data ) {
						try {
							if ( "success" === data.result ) {
								klarna_payments.logToFile(
									"Successfully placed order. Starting authorization with Klarna",
								)
								klarna_payments.addresses = data.addresses
								klarna_payments.authorizeKlarnaOrder( data.order_id, data.order_key )
							} else {
								throw "Result failed"
							}
						} catch ( err ) {
							if ( data.messages ) {
								klarna_payments.logToFile( "Checkout error | " + data.messages )
								klarna_payments.failOrder( "submission", data.messages )
								// If requested, reload the page.
							} else if ( true === data.reload ) {
								window.location.reload()
							} else {
								klarna_payments.logToFile( "Checkout error | " + err )
								klarna_payments.failOrder(
									"submission",
									'<div class="woocommerce-error">' + "Checkout error" + "</div>",
								)
							}
						}
					},
					error: function ( data ) {
						try {
							klarna_payments.logToFile( "AJAX error | " + JSON.stringify( data ) )
						} catch ( e ) {
							klarna_payments.logToFile( "AJAX error | Failed to parse error message." )
						}
						klarna_payments.failOrder(
							"ajax-error",
							'<div class="woocommerce-error">Internal Server Error</div>',
						)
					},
				} )
			}
		},

		/**
		 * Fails the order with Klarna on a checkout error and timeout.
		 * @param {string} event
		 */
		failOrder: function ( event, error_message ) {
			// Re-enable the form.
			$( "body" ).trigger( "updated_checkout" )
			$( "form.checkout" ).removeClass( "processing" )
			$( "form.checkout" ).unblock()

			// Print error messages, and trigger checkout_error, and scroll to notices.
			$( ".woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message" ).remove()
			$( "form.checkout" ).prepend(
				'<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">' + error_message + "</div>",
			) // eslint-disable-line max-len
			$( "form.checkout" ).removeClass( "processing" ).unblock()
			$( "form.checkout" ).find( ".input-text, select, input:checkbox" ).trigger( "validate" ).blur()
			$( document.body ).trigger( "checkout_error", [ error_message ] )
			$.scroll_to_notices( $( "form.checkout" ) )
		},

		/**
		 * Logs the message to the klarna payments log in WooCommerce.
		 * @param {string} message
		 */
		logToFile: function ( message ) {
			klarna_payments.log( message )
			$.ajax( {
				url: klarna_payments_params.log_to_file_url,
				type: "POST",
				dataType: "json",
				data: {
					message: message,
					nonce: klarna_payments_params.log_to_file_nonce,
				},
			} )
		},
	}
	klarna_payments.start()
	$( document ).ready( function () {
		klarna_payments.setRadioButtonValues()
	} )

	$( document ).ajaxComplete( function () {
		klarna_payments.setRadioButtonValues()
	} )

	$( document ).on( "click", 
		// CHANGE: Use a class selector for the place order button as more than one place order button might exist on the same page
		"input#place_order, button#place_order, .fc-place-order-button", 
		function ( e ) {
		// No strict comparison: wp_localize_script() converts booleans to strings "1", respectively, "0".
		if ( true == klarna_payments_params.pay_for_order ) {
			klarna_payments.klarnaPayForOrder( e )
		} else {
			klarna_payments.orderSubmit( e )
		}
	} )
} )
