<?php 

define("HNB_API_URL","http://api.hnb.hr/tecajn/v1");
define("HNB_API_SREDNJI_TECAJ_FIELD","Srednji za devize");
define("HNB_API_VALUTA_FIELD","Valuta");


// define("BASE_URL","http://localhost/ych-invoicing-git/invoice.bookey.pro");
define("BASE_URL","http://invoice.bookey.pro");

define('INVOICE_EXPORT_PDF','PDF');
define('INVOICE_EXPORT_EXCEL','EXCEL');

function returnDisplayPrice($amount){
	return number_format($amount, 2, ".", ",");
}

function generate_vaild_price($price){
    $amount_number = false;
    if(is_string($price)){
		$regex_validation = preg_match("/^([\-]?[0-9]*(\.[0-9]*)?)$/", $price);
    	if(!$regex_validation){
    		return false;
    	}
		$amount_number = floatval($price);
		$amount_number = round($amount_number,2);
      	
    }
    else if(is_float($price)){
        $amount_number = round($price,2);
    }
    else if(is_numeric($price)){
        $amount_number = round($price,2);
    } 
    return $amount_number;
}

function generate_vaild_amount($amount){
    $amount_number = false;
    if(is_string($amount)){
		$regex_validation = preg_match("/^([\-]?[0-9]*(\.[0-9]*)?)$/", $amount);
    	if(!$regex_validation){
    		return false;
    	}
		$amount_number = floatval($amount);
    }
    else if(is_float($amount)){
        $amount_number = $amount;
    }
    else if(is_numeric($amount)){
        $amount_number = floatval($amount);
    } 
    return round($amount_number,2);
}

function getHRKcourse($second_currency, $date = false){
	if($date == false) $date = date("Y-m-d");
	$ch = curl_init(); 
	$second_currency = strtoupper($second_currency);
	curl_setopt($ch, CURLOPT_URL, HNB_API_URL."?valuta=".$second_currency."&datum=".$date); 
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "10");
	curl_setopt($ch, CURLOPT_TIMEOUT, "10" );
	// curl_setopt($ch, CURLOPT_HEADER, true);
	// curl_setopt($ch, CURLOPT_NOBODY, false);
	$tecaj_json = curl_exec($ch); 
	$http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	if(!$tecaj_json || $http_response_code!= "200" ){
		return false;
	} else {
		curl_close($ch); 
		$tecaj_eur = json_decode($tecaj_json,true);
		$tecaj_hrk_eur = "0";
		foreach ($tecaj_eur as $t) {
			if($t[HNB_API_VALUTA_FIELD] == $second_currency){
				$tecaj_hrk_eur = str_replace(",", ".", $t[HNB_API_SREDNJI_TECAJ_FIELD] );
				$tecaj_hrk_eur = floatval($tecaj_hrk_eur);
				break;
			}
		}
		if($tecaj_eur == "0"){
			return false;
		} else {
			return $tecaj_hrk_eur;
		}
	}
}

function getCourseRatio($main_currency, $other_currency, $date = false){
	if($date == false) $date = date("Y-m-d");
	$not_hrk = ($main_currency != "HRK")? true : false;
	$result = null;
	$result[$main_currency] = 1;
	foreach ($other_currency as $key=>$value){ // inicijaliziraj valute
		if($value && is_numeric($value)){
			$result[$key] = $value;
		} else {
			$result[$key] = 0;
		}

	}

	$ch = curl_init(); 
	curl_setopt($ch, CURLOPT_URL, HNB_API_URL."?datum=".$date); 
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "10");
	curl_setopt($ch, CURLOPT_TIMEOUT, "10" );

	$tecaj_json = curl_exec($ch); 
	$http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	if(!$tecaj_json || $http_response_code!= "200" ){
		return false;
	} else {
		curl_close($ch);
		$tecaj_vals = json_decode($tecaj_json,true);
		$tecaj_main = 1;
		if($not_hrk){
			foreach ($tecaj_vals as $t) {
				// odnos HRK 
				if($t[HNB_API_VALUTA_FIELD] == $main_currency){
					$tecaj_curr = str_replace(",", ".", $t['Srednji za devize'] );
					$tecaj_curr = floatval($tecaj_curr);
					if(isset($result["HRK"]) && $result["HRK"] == 0){
						$result["HRK"] = $tecaj_curr;
					}
					$result[$main_currency] = 1;
					$tecaj_main = $tecaj_curr;
				}

			}
		} else {
			$result[$main_currency] = 1;
		}

		foreach ($tecaj_vals as $t) {
			
			if( isset($result[$t[HNB_API_VALUTA_FIELD]]) && $result[$t[HNB_API_VALUTA_FIELD]] === 0 && $t[HNB_API_VALUTA_FIELD] != $main_currency ){

				$tecaj_curr = str_replace(",", ".", $t[HNB_API_SREDNJI_TECAJ_FIELD] );
				$tecaj_curr = floatval($tecaj_curr);
				if($not_hrk){
					$result[$t[HNB_API_VALUTA_FIELD]] = $tecaj_main/$tecaj_curr;
				} else {
					$result[$t[HNB_API_VALUTA_FIELD]] = 1/$tecaj_curr;
				}
					
			}

		}

		return $result;
		
	}
}



function getRatiosForDatesAndCurrEUR($dates){
	$res = [];
	$today_ratio = getCourseRatio("EUR", ["HRK"=>null] );
	foreach ($dates as $date) {
		$res[$date] = [];
		$ratio1 = getCourseRatio("HRK", ["EUR"=>null], $date);
		$ratio2 = getCourseRatio("EUR", ["HRK"=>null], $date);
		$i = NULL;
		$i["curr1"] = "HRK";
		$i["curr2"] = "EUR";
		$i["ratio"] = $ratio1["EUR"] ;

		array_push($res[$date], $i);

		$i["curr1"] = "EUR";
		$i["curr2"] = "HRK";
		$i["ratio"] = $ratio2["HRK"];

		array_push($res[$date],$i );

		$i["curr1"] = "EUR";
		$i["curr2"] = "EUR";
		$i["ratio"] = $ratio2["EUR"] / $today_ratio["EUR"];

		array_push($res[$date],$i );

		$i["curr1"] = "HRK";
		$i["curr2"] = "HRK";
		$i["ratio"] = 1;

		array_push($res[$date],$i );
	}

	return $res;

}

function findRatio($ratios, $datum_tecaja, $valuta_placanja, $valuta_stavke){
	
	/*
		$ratios must be in shape of [
			"2020-02-03" => [
					"curr1"=> "EUR | HRK | ...",
					"curr2"=> "EUR | HRK | ...",
					"ratio"=> float
				], ....
			]
			, ......
		]
		
		$valuta_placanja - 
		$valuta_stavke - 
	*/

	$ratio_value = 1;
	
	$ratio = array_values(array_filter( $ratios, function($v, $k) use ($valuta_placanja, $valuta_stavke, $datum_tecaja, &$ratio_value) {
		if($k !== $datum_tecaja ) return false;
		$r = array_values(array_filter( $v, function($v1, $k1) use ($valuta_placanja, $valuta_stavke, &$ratio_value) {
		 	if( $v1["curr1"] === $valuta_placanja && $v1["curr2"] === $valuta_stavke){
			   $ratio_value = $v1["ratio"];
			}
		}, ARRAY_FILTER_USE_BOTH));
	}, ARRAY_FILTER_USE_BOTH));

	return floatval($ratio_value);
}




/*
	Billing funkcija je majka svega. 
	Racuna SVE brojke (cijene, porezi, predujmovi itd) za stavke u računu i valute.
	Ako postoje preddefinirane vrijednosti valuta onda se one uzimaju.
	Preddefinirane vrijednosti postoje zbog toga da se ne uzima tekući tečaj a račun je iz nekog drugog dana.
	Ako "VALUTA" => null , onda se uzme srednji tecaj na danasnji dan
 */

function billing($items, $datum_racuna, $u_sustavu_pdva=true, $valuta = "HRK" , $other_currency = ["EUR"=>null]  ){
	/*
		$items format -> POST-form-data
		[
			[ naziv, opis, jedinica_mjere, kolicina, cijena_po_jedinici, stopa_pdv, popust ],
			...,
			..,
			.,
		]
	*/

	$errors = [];
	$tecaj = [];

	$tecaj_hrk = false;
	if(empty($other_currency) && $valuta == "HRK" ){
		$tecaj["HRK"] = 1;
	} else {
		$tecaj = getCourseRatio($valuta, $other_currency, $datum_racuna);
		
	}

	if($tecaj == false) {
		$errors[] = "There was an error while getting the exchange rate. Try again in few minutes.";
	}


	$pdv_stope = [];
	$stavke = [];
	$total = [];

	$predujam = [];
	$predujam['stavke'] = [];
	$predujam['total'] = [];

	if(empty($errors)){
		// postavi predujam na 0
			foreach ($tecaj as $ot_curr=>$value) {
				$predujam['total'][$ot_curr] = [];
				$predujam['total'][$ot_curr]['ukupno_predujam_pdv'] = 0;
				$predujam['total'][$ot_curr]['ukupno_predujam_bez_pdv'] = 0;
				$predujam['total'][$ot_curr]['ukupno_predujam'] = 0; 
			}

		// postavi total na 0
			foreach ($tecaj as $ot_curr => $value) {

				$total[$ot_curr]['total'] = floatval(0);
				$total[$ot_curr]['total_bez_pdv'] = floatval(0);
				$total[$ot_curr]['total_pdv'] = floatval(0);

			}

		$number_of_records = 1;
	}

	$datumi_tecaja = [];
	foreach ($items as $item ){
		if( isset($item["item_date"]) && $item["item_date"] && isset($item["item_currency"]) && $item["item_currency"] ) {
			 array_push($datumi_tecaja, $item["item_date"] );
		 }
	
	}
	$ratios = getRatiosForDatesAndCurrEUR($datumi_tecaja);


	if(empty($errors)) {
		foreach($items as $item ){

			/* ========= ZA SVAKI PROIZVOD ======== */

			if(	
				!isset($item['naziv']) || 
				!isset($item['opis']) || 
				!isset($item['jedinica_mjere']) || 
				!isset($item['kolicina']) || 
				!isset($item['cijena_po_jedinici']) || 
				!isset($item['stopa_pdv']) || 
				!isset($item['popust']) ) {
				$errors[] = "Invalid item provided!";
				continue;
			}

		
			// provjeri da li je u sustavu pdv ( note: na predujam se stavlja PDV)
			if(!$u_sustavu_pdva && !(isset($item['is_advance']) && $item['is_advance']=="1") ){
				$item['stopa_pdv'] = 0;
			} 

			// ne numerični podaci
			$name = $item['naziv'];
			$description = $item['opis'];
			$mesure = $item['jedinica_mjere'];
			$amount = generate_vaild_amount($item['kolicina']);
			$price_per_unit = generate_vaild_price($item['cijena_po_jedinici']);

			$stopa_pdv = (is_numeric($item['stopa_pdv']))? floatval($item['stopa_pdv']) : false;
			$popust = (is_numeric($item['popust']))? floatval($item['popust']) : false;

			// provjeri ako su svi podaci dobri
			if(!$amount){
				$errors[] = "Neispravna količina za stavku \"$name\". Napomena: Koristite točku (.) kao decimalnu točku.";
			}

			if(!$price_per_unit){
				$errors[] = "Neispravna cijena za stavku \"$name\". Napomena: Koristite točku (.) kao decimalnu točku.";
			} 

			if($stopa_pdv === false){
				$errors[] = "Neispravna stopa poreza za stavku \"$name\". Napomena: Koristite točku (.) kao decimalnu točku.";
			}

			if($popust === false){
				$errors[] = "Neispravan popust za stavku \"$name\". Napomena: Koristite točku (.) kao decimalnu točku.";
			} 

			if(!empty($errors)){
				continue;
			}

			/* ============================================= */
			/* ============ OPĆI PODACI ZA STAVKU ========== */
			/* ============================================= */

				$p = null; // tekuci proizvod
				$p['name'] = $name;
				$p['description'] = $description;
				$p['mesure'] = $mesure;
				$p['amount'] = $amount;
				$p['stopa_pdv'] = $stopa_pdv;
				$p['popust'] = $popust;
				$p['product_prices'] = [];

				

			/* ======================================================= */
			/* ===== IZRACUNAJ CIJENE PROIZVODA ZA VALUTE ===== */
			/* ======================================================= */

			foreach ($tecaj as $ot_curr=>$value) {
				
				$price_per_unit_dv = $price_per_unit*$value;

				/* ako je stavka predujam, uzmi tecaj i datum koji je u stavci i pronađi tečaj */
				if(isset($item['is_advance']) && $item['is_advance'] == "1" ) {
					$datum_tecaja = $item["item_date"];
					$valuta_predujma = $item["item_currency"];
					$course_ratio = findRatio($ratios, $datum_tecaja, $valuta, $ot_curr );
					$price_per_unit_dv = $price_per_unit*$course_ratio;	
				}

				/* ako je stavka storno, uzmi tecaj i datum koji je u stavci i pronađi tečaj */
				if(isset($item['is_storno']) && $item['is_storno'] === "1" ) {
					$datum_tecaja = $item["item_date"];
					$valuta_predujma = $item["item_currency"];
					$course_ratio = findRatio($ratios, $datum_tecaja, $valuta, $ot_curr );
					$price_per_unit_dv = $price_per_unit*$course_ratio;	
				}
				
		        if(isset($item['boravisna']) && $item['boravisna'] == "1" ) {
					if($ot_curr == "HRK") {
						$price_per_unit_dv = $price_per_unit;
					} else {
						$price_per_unit_dv = $price_per_unit*($value/$tecaj['HRK']);
					}
				}

				$price_per_unit_dv = round($price_per_unit_dv,2);
				$osnovica_dv = $amount * $price_per_unit_dv;
				$osnovica_dv = round($osnovica_dv,2);

				$osnovica_sa_popustom_dv = $osnovica_dv;
				$popust_iznos_dv = 0 ;

				// ako je definiran popust
				if($popust > 0){
					$popust_iznos_dv = $osnovica_dv * ($popust/100);
					$popust_iznos_dv = round($popust_iznos_dv, 2);
					$osnovica_sa_popustom_dv = $osnovica_dv - $popust_iznos_dv;
					$osnovica_sa_popustom_dv = round($osnovica_sa_popustom_dv, 2);
				}

				// iznos PDV-a
				$pdv_dv = $osnovica_sa_popustom_dv*($stopa_pdv/100);
				$pdv_dv = round($pdv_dv, 2);

				// osnovica i PDV
				$osnovica_i_pdv_dv = $osnovica_sa_popustom_dv + $pdv_dv;
				$osnovica_i_pdv_dv = round($osnovica_i_pdv_dv, 2);

				$product_prices[$ot_curr]['price_per_unit'] = $price_per_unit_dv;
				$product_prices[$ot_curr]['popust_iznos'] = $popust_iznos_dv;
				$product_prices[$ot_curr]['pdv_iznos'] = $pdv_dv;
				$product_prices[$ot_curr]['osnovica'] = $osnovica_dv;
				$product_prices[$ot_curr]['osnovica_i_pdv'] = $osnovica_i_pdv_dv;
				$product_prices[$ot_curr]['osnovica_sa_popustom'] = $osnovica_sa_popustom_dv;
				$product_prices[$ot_curr]['item_total'] = $osnovica_i_pdv_dv;

				// ako je predujam izracunaj total za predujam
				if( isset($item['is_advance']) && $item['is_advance'] ){

					$predujam['total'][$ot_curr]['ukupno_predujam_pdv'] += $pdv_dv;
					$predujam['total'][$ot_curr]['ukupno_predujam_bez_pdv'] += $osnovica_sa_popustom_dv;
					$predujam['total'][$ot_curr]['ukupno_predujam'] += $osnovica_i_pdv_dv; 

				} else { // ako nije predujam

					// izračunaj TOTAL
					$total[$ot_curr]['total'] += $osnovica_i_pdv_dv;
					$total[$ot_curr]['total'] = round($total[$ot_curr]['total'], 2);

					$total[$ot_curr]['total_bez_pdv'] += $osnovica_sa_popustom_dv;
					$total[$ot_curr]['total_bez_pdv'] = round($total[$ot_curr]['total_bez_pdv'], 2);

					$total[$ot_curr]['total_pdv'] += $pdv_dv;
					$total[$ot_curr]['total_pdv'] = round($total[$ot_curr]['total_pdv'], 2);

					// STOPE PDV-a
					$stopa_pronadjena = false;
					for($i=0; $i<sizeof($pdv_stope); $i++){
						if($pdv_stope[$i]["stopa"] == $stopa_pdv){
							$stopa_pronadjena = true;
							if(isset($pdv_stope[$i]["total"][$ot_curr])){
								$pdv_stope[$i]["total"][$ot_curr] += $pdv_dv;
								$pdv_stope[$i]["iznos_osnovice"][$ot_curr] += $osnovica_sa_popustom_dv;

							} else {
								$pdv_stope[$i]["total"][$ot_curr] = $pdv_dv;
								$pdv_stope[$i]["iznos_osnovice"][$ot_curr] = $osnovica_sa_popustom_dv;
							}
						
						}
					} 
					if(!$stopa_pronadjena){
						$pdv_stopa_temp["stopa"] = $stopa_pdv;
						$pdv_stopa_temp["total"][$ot_curr] = $pdv_dv;
						$pdv_stopa_temp["iznos_osnovice"][$ot_curr] = $osnovica_sa_popustom_dv;
						array_push($pdv_stope, $pdv_stopa_temp);
					}

				}
				

			} // kraj for petlje

			// STAVI CIJENE U PRICES
			$p['product_prices'] = $product_prices;
			$p['is_advance'] = false;

			if( isset($item['is_advance']) && $item['is_advance'] ){ // AKO JE PREDUJAM STAVI U PREDUJMOVE 
				$p['is_advance'] = true;
				array_push($predujam['stavke'], $p);
				continue;
			} else { // AKO NIJE PREDUJAM SAVI U STAVKE
				array_push($stavke, $p);
			}
			
		}
	}

	$result = null;
	$result['pdv_stope'] = $pdv_stope;
	$result['stavke'] = $stavke;
	$result['ukupno'] = $total;
	$result['predujam'] = $predujam;
	
	if(empty($errors)){
		foreach ($tecaj as $ot_curr => $value) {
			$result['ostatak_za_uplatu'][$ot_curr] = $total[$ot_curr]['total'] + $predujam['total'][$ot_curr]['ukupno_predujam'];
			$result['ostatak_za_uplatu'][$ot_curr] = round($result['ostatak_za_uplatu'][$ot_curr], 2);
		}
	}

	$result['errors'] = $errors;

	$result['tecajevi'] = $tecaj;

	return $result;
}

function obracun_za_najmodavca($iznos, $provizija, $pdv_na_proviziju){

	$agencijska_provizija_postotak = floatval($provizija);
	$pdv_na_proviziju = floatval($pdv_na_proviziju);

	$bruto_iznos = floatval($iznos["HRK"]);
	$agencijska_provizija_postotak = floatval($provizija);
	$agencijska_provizija_iznos = $bruto_iznos * ($agencijska_provizija_postotak/100);
	$agencijska_provizija_iznos = round($agencijska_provizija_iznos, 2);

	$pdv_na_proviziju_iznos = $agencijska_provizija_iznos * ($pdv_na_proviziju/100);
	$pdv_na_proviziju_iznos = round($pdv_na_proviziju_iznos, 2);

	$ukupno_odbici = $agencijska_provizija_iznos + $pdv_na_proviziju_iznos;
	$iznos_za_isplatu = $bruto_iznos - $ukupno_odbici;


	$bruto_iznos_eur = floatval($iznos["EUR"]);
	$agencijska_provizija_iznos_eur = $bruto_iznos_eur * ($agencijska_provizija_postotak/100);
	$agencijska_provizija_iznos_eur = round($agencijska_provizija_iznos_eur, 2);

	$pdv_na_proviziju_iznos_eur = $agencijska_provizija_iznos_eur * ($pdv_na_proviziju/100);
	$pdv_na_proviziju_iznos_eur = round($pdv_na_proviziju_iznos_eur, 2);

	$ukupno_odbici_eur = $agencijska_provizija_iznos_eur + $pdv_na_proviziju_iznos_eur;
	$iznos_za_isplatu_eur = $bruto_iznos_eur - $ukupno_odbici_eur;

	return [
		"HRK" => [
			'bruto_iznos' => $bruto_iznos,
			'agencijska_provizija_postotak' => $agencijska_provizija_postotak,
			'pdv_na_proviziju' => $pdv_na_proviziju,
			'agencijska_provizija_iznos' => $agencijska_provizija_iznos,
			'pdv_na_proviziju_iznos' => $pdv_na_proviziju_iznos,
			'ukupno_odbici' => $ukupno_odbici,
			'iznos_za_isplatu' => $iznos_za_isplatu
		],
		"EUR" => [
			'bruto_iznos' => $bruto_iznos_eur,
			'agencijska_provizija_postotak' => $agencijska_provizija_postotak,
			'pdv_na_proviziju' => $pdv_na_proviziju,
			'agencijska_provizija_iznos' => $agencijska_provizija_iznos_eur,
			'pdv_na_proviziju_iznos' => $pdv_na_proviziju_iznos_eur,
			'ukupno_odbici' => $ukupno_odbici_eur,
			'iznos_za_isplatu' => $iznos_za_isplatu_eur
		]
	];

}

function is_json($value = null){
	$ret = true;
	if(null === @json_decode($value)){
		$ret = false;
	}
	return $ret;
}


?>