<?php
class ModelExtensionPaymentKlarnaAccount extends Model {
	public function getMethod($address, $total) {
		$this->load->language('extension/payment/klarna_account');

		$status = true;

		$klarna_account = $this->config->get('klarna_account');

		if (!isset($klarna_account[$address['iso_code_3']])) {
			$status = false;
		} elseif (!$klarna_account[$address['iso_code_3']]['status']) {
			$status = false;
		}

		if ($status) {
			$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$klarna_account[$address['iso_code_3']]['geo_zone_id'] . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");

			if ($klarna_account[$address['iso_code_3']]['total'] > 0 && $klarna_account[$address['iso_code_3']]['total'] > $total) {
				$status = false;
			} elseif (!$klarna_account[$address['iso_code_3']]['geo_zone_id']) {
				$status = true;
			} elseif ($query->num_rows) {
				$status = true;
			} else {
				$status = false;
			}

			// Maps countries to currencies
			$country_to_currency = array(
				'NOR' => 'NOK',
				'SWE' => 'SEK',
				'FIN' => 'EUR',
				'DNK' => 'DKK',
				'DEU' => 'EUR',
				'NLD' => 'EUR'
			);

			if (!isset($country_to_currency[$address['iso_code_3']]) || !$this->currency->has($country_to_currency[$address['iso_code_3']])) {
				$status = false;
			}

			if ($address['iso_code_3'] == 'NLD' && $this->currency->has('EUR') && $this->currency->format($total, 'EUR', '', false) > 250.00) {
				$status = false;
			}
		}

		$payment_option = array();

		if ($status) {
			$total = $this->currency->format($total, $country_to_currency[$address['iso_code_3']], '', false);

			$pclasses = $this->config->get('klarna_account_pclasses');

			if (isset($pclasses[$address['iso_code_3']])) {
				$pclasses = $pclasses[$address['iso_code_3']];
			} else {
				$pclasses = array();
			}

			foreach ($pclasses as $pclass) {
				// 0 - Campaign
				// 1 - Account
				// 2 - Special
				// 3 - Fixed
				if (!in_array($pclass['type'], array(0, 1, 3))) {
					continue;
				}

				if ($pclass['type'] == 2) {
					$monthly_cost = -1;
				} else {
					if ($total < $pclass['minamount']) {
						continue;
					}

					if ($pclass['type'] == 3) {
						continue;
					} else {
						$sum = $total;

						$lowest_payment = $this->getLowestPaymentAccount($address['iso_code_3']);
						$monthly_cost = 0;

						$monthly_fee = $pclass['invoicefee'];
						$start_fee = $pclass['startfee'];

						$sum += $start_fee;

						$base = ($pclass['type'] == 1);

						$minimum_payment = ($pclass['type'] === 1) ? $this->getLowestPaymentAccount($address['iso_code_3']) : 0;

						if ($pclass['months'] == 0) {
							$payment = $sum;
						} elseif ($pclass['interestrate'] == 0) {
							$payment = $sum / $pclass['months'];
						} else {
							$interest_rate = $pclass['interestrate'] / (100.0 * 12);

							$payment = $sum * $interest_rate / (1 - pow((1 + $interest_rate), -$pclass['months']));
						}

						$payment += $monthly_fee;

						$balance = $sum;
						$pay_data = array();

						$months = $pclass['months'];

						while (($months != 0) && ($balance > 0.01)) {
							$interest = $balance * $pclass['interestrate'] / (100.0 * 12);
							$new_balance = $balance + $interest + $monthly_fee;

							if ($minimum_payment >= $new_balance || $payment >= $new_balance) {
								$pay_data[] = $new_balance;
								break;
							}

							$new_payment = max($payment, $minimum_payment);

							if ($base) {
								$new_payment = max($new_payment, $balance / 24.0 + $monthly_fee + $interest);
							}

							$balance = $new_balance - $new_payment;

							$pay_data[] = $new_payment;

							$months -= 1;
						}

						$monthly_cost = round(isset($pay_data[0]) ? ($pay_data[0]) : 0, 2);

						if ($monthly_cost < 0.01) {
							continue;
						}

						if ($pclass['type'] == 1 && $monthly_cost < $lowest_payment) {
							$monthly_cost = $lowest_payment;
						}

						if ($pclass['type'] == 0 && $monthly_cost < $lowest_payment) {
							continue;
						}
					}
				}

				$payment_option[$pclass['id']]['monthly_cost'] = $monthly_cost;
				$payment_option[$pclass['id']]['pclass_id'] = $pclass['id'];
				$payment_option[$pclass['id']]['months'] = $pclass['months'];
			}
		}

		if (!$payment_option) {
			$status = false;
		}

		$sort_order = array();

		foreach ($payment_option as $key => $value) {
			$sort_order[$key] = $value['monthly_cost'];
		}

		array_multisort($sort_order, SORT_ASC, $payment_option);

		if ($address['company']) {
			$status = false;
		}

		$method = array();

		if ($status) {
			$method = array(
				'code'       => 'klarna_account',
				'title'      => sprintf($this->language->get('text_title'), $this->currency->format($this->currency->convert($payment_option[0]['monthly_cost'], $country_to_currency[$address['iso_code_3']], $this->session->data['currency']), 1, 1)),
				'terms'      => sprintf($this->language->get('text_terms'), $klarna_account[$address['iso_code_3']]['merchant'], strtolower($address['iso_code_2'])),
				'sort_order' => $klarna_account[$address['iso_code_3']]['sort_order'],
			);
		}

		return $method;
	}

	private function getLowestPaymentAccount($country) {
		switch ($country) {
			case 'SWE':
				$amount = 50.0;
				break;
			case 'NOR':
				$amount = 95.0;
				break;
			case 'FIN':
				$amount = 8.95;
				break;
			case 'DNK':
				$amount = 89.0;
				break;
			case 'DEU':
			case 'NLD':
				$amount = 6.95;
				break;
			default:
				$log = new Log('klarna_account.log');
				$log->write('Unknown country ' . $country);

				$amount = null;
				break;
		}

		return $amount;
	}
}