<?php

class Invoice {
	public $InvoiceID, $OrderID, $PONumber, $Customer, $InvoiceDate, $Salesman, $SalesmanOrder, $Items, $Notes,
	$DeliveryMethod, $InvoiceTotal, $AccountNumber, $Status, $SentPicking, $Packed, $PackingUser, $CreationDate,
	$InvoiceUser, $Void, $OnHold, $OnHoldDate, $VoidDate, $OnHoldVoidReason, $OnHoldVoidUser, $Terms, $Tax1Rate,
	$Tax2Rate, $Tax1Total, $Tax2Total, $InvoiceSubtotal, $hasQuotes, $ItemID;
	
	public function __construct($InvoiceID) {
		
		$query = "SELECT * FROM INVOICE_HEAD WHERE InvoiceID = $InvoiceID";
		global $con;
		$result = mysqli_query($con, $query);
		$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
		$this->OriginalColumns = array();
		
		foreach($row as $key => $value){
			$this->$key = $value;
			
			array_push($this->OriginalColumns, $key);
		}
		
		
		//
		// Get Columns Names and either if they need quotes in a query or not.
		//
		$this->hasQuotes = [];
		$query = "SHOW COLUMNS FROM `INVOICE_HEAD`";
		$result = mysqli_query($con,$query);
		while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
			if(stripos($row['Type'], "int") === 0 || stripos($row['Type'], "double") === 0 || stripos($row['Type'], "tinyint") === 0 || stripos($row['Type'], "numeric") === 0 || stripos($row['Type'], "double") === 0 || stripos($row['Type'], "decimal") === 0 || stripos($row['Type'], "float") === 0 || stripos($row['Type'], "bigint") === 0 || stripos($row['Type'], "real") === 0 || stripos($row['Type'], "bool") === 0){
				$this->hasQuotes[$row['Field']] = false;
			}else{
				$this->hasQuotes[$row['Field']] = true;
			}
		}
		
		$this->Customer = new Customer($this->AccountNumber);
		$this->SalesmanID = $this->Salesman;
		$this->Salesman = new Salesman($this->Salesman);
		$this->Items = array();
		$query = "SELECT INVOICE_DETAIL.* FROM INVOICE_DETAIL LEFT JOIN INVENTORY USING(Line, SKU) WHERE InvoiceID = '$InvoiceID' ORDER BY Location DESC";
		$result = mysqli_query($con, $query);
		$total = 0;
		//error_reporting(E_ALL);
		$this->ItemID = array();
		//echo $query ;
		while($row = mysqli_fetch_array($result)){
			//die('here');
			$item = new InvoiceItem($row['ID']);
			$this->ItemID[$row['Line'] . "|" . $row['SKU']] = $row['ID'];
			//var_dump($this->ItemID);
			$item->ItemsOriginalColumns = array();
			foreach($row as $key => $value){
				$item->$key = $value;
				//array_push($this->ItemsOriginalColumns, $key);
			}
			
			$total += $row['ShippedQty'] * $row['Price'];
			$total += $row['ShippedQty'] * $row['Core'];
			
			array_push($this->Items, $item);
			unset($item);
		}
		//var_dump($this->ItemID);
		$this->InvoiceSubtotal = $total;
		$this->Subtotal = $total;
		
		$this->InvoiceTotal = $total;
		if($this->Status){
			$this->TotalTax = $this->Tax1Total+$this->Tax2Total;
			$this->InvoiceTotal = $total+$this->TotalTax;
		}else{
			$this->calculateTax();	
		}
		
		
	}
	
	public function calculateTax(){
		global $con;
		if($this->Status){
			return;
		}else{
			$tax1Total = 0;
			$tax2Total = 0;
			
			
			
			foreach($this->Items as $key => $item){
				
				if($item->Taxable1 && !$this->Customer->TaxExempt1){
					$tax1Total += $item->Price*$item->ShippedQty*$this->Tax1Rate;
					
				}
				if($item->Taxable2 && !$this->Customer->TaxExempt2){
					$tax2Total += $item->Price*$item->ShippedQty*$this->Tax2Rate;
				}
			}
			$this->Tax1Total = round($tax1Total,2);
			$this->Tax2Total = round($tax2Total,2);
			$this->TotalTax = $tax1Total+$tax2Total;
			$this->InvoiceTotal += $tax1Total + $tax2Total;
			
			return;			
		}
		
	}
	public function VoidInvoice($reason){
		global $con;
		if(!$this->Status){
			$query = "UPDATE INVOICE_HEAD SET Status = 0, Void = 1, HoldVoidReason= '" . mysqli_real_escape_string($con, $reason) . "', HoldVoidUser= '" . $_SESSION['Username'] . "', VoidDate = DATE_ADD(NOW(), INTERVAL -4 HOUR), Subtotal = " . $this->InvoiceSubtotal . " WHERE InvoiceID = " . $this->InvoiceID;
			
			if(mysqli_query($con, $query)){
				return true;
			}else{
				return false;
			}
		}else{
			return false;
		}
	}
	public function Finalize(){
		global $con;
		if(!$this->Status){
			if($this->Terms == -1){
				$this->Terms = 0;
			}
			$query = "UPDATE INVOICE_HEAD SET Status = True, InvoiceDate = DATE_ADD(NOW(), INTERVAL -4 HOUR), DueDate = DATE_ADD(NOW(), INTERVAL {$this->Terms} DAY), Subtotal = " . $this->InvoiceSubtotal . ", Tax1Total = " . $this->Tax1Total . ", Tax2Total = " . $this->Tax2Total . " WHERE InvoiceID = " . $this->InvoiceID;
			mysqli_query($con,$query);
			foreach($this->Items as $key => $item){
				$query = "UPDATE INVENTORY SET Qty = Qty - " . mysqli_real_escape_string($con, $item->ShippedQty) . " WHERE `Group` = '" . mysqli_real_escape_string($con, $item->Group) . "' AND `Line` = '" . mysqli_real_escape_string($con, $item->Line) . "' AND `SKU` = '" . mysqli_real_escape_string($con, $item->SKU) . "'";
				mysqli_query($con, $query);
			}
			$this->sendEmail();
			return true;
		}else{
			return false;
		}
		
	}
	public function sendEmail($to){
		global $con;
		global $config;
		global $root;
		$typeText = "Invoice";
		if($this->InvoiceTotal < 0){
			$typeText = "Credit";
		}
		
		$subject = "New $typeText #" . $this->InvoiceID;
		
		
		
		$pdf = false;
		if ($pdf) {
			
		}else{
			
			
			
			require_once $_SERVER['DOCUMENT_ROOT'] . '/assets/PHPMailerAutoload.php';
			 
			$results_messages = array();
			 
			$mail = new PHPMailer(true);
			
			$mail->CharSet = 'utf-8';
			 
			//class phpmailerAppException extends phpmailerException {}
			 
			try {
				if(is_null($to)){
				
					$to = $this->Customer->Email;
				}else{
					//$to = "noemail@westingpr.com";
				}
			
			if(!PHPMailer::validateAddress($to)) {
			  throw new phpmailerException("Email address " . $to . " is invalid -- aborting!");
			}
			$mail->isMail();
			$mail->addReplyTo($config['FromEmail']);
			$mail->From       = $config['FromEmail'];
			$mail->FromName   = $config['FromEmailName'];
			$mail->addAddress($to);
			
			//$mail->addBCC("invoice@westingpr.com");
			
			
			if ($this->Customer->Salesman->Email != "" || $this->Customer->Salesman->Email != null) {
				$mail->addCC($this->Customer->Salesman->Email);	
			}
			
			$mail->Subject  = $subject;
			$typeText = "Invoice";
			if($this->InvoiceTotal < 0){
				$typeText = "Credit";
			}
			$title = $config["FromEmailName"];
			$body = 
			'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
			<html>
			<head>
			  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
			  <title>' . $title . '</title>
			</head>
			<body>
			  <div style="width: 640px; font-family: Arial, Helvetica, sans-serif; font-size: 16px;">
				<img src="'.$root.'/img/'. $config['SmallLogo'] .'" style="width: 150px;" />
				<p>New ' . $typeText . ' for ' . $this->Customer->Name . ' <br />
				Account Number: ' . $this->Customer->AccountNumber . '<br />
				Notas: ' . $this->Notes . '<br />
				
				<a href="' . $root . 'mod.php?p=invoice&a=customerview&id=' . $this->InvoiceID . '&key=' . $this->getTokenKey() . '">View Invoice #' . $this->InvoiceID . '</a>
				</p>
				<div align="center">
				  
				</div>
				
			  </div>
			</body>
			</html>';
			
			$mail->WordWrap = 78;
			$mail->msgHTML($body, dirname(__FILE__), true); //Create message bodies and embed images
			//$mail->addAttachment('images/phpmailer_mini.png','phpmailer_mini.png');  // optional name
			//$mail->addAttachment('images/phpmailer.png', 'phpmailer.png');  // optional name
			
			$privatekeyfile = 'dkim_private.key';
			//Make a new key pair
			//(2048 bits is the recommended minimum key length -
			//gmail won't accept less than 1024 bits)
			$pk = openssl_pkey_new(
				array(
					'private_key_bits' => 2048,
					'private_key_type' => OPENSSL_KEYTYPE_RSA
				)
			);
			openssl_pkey_export_to_file($pk, $privatekeyfile);
			
			$mail->DKIM_domain = 'westingpr.com';
			$mail->DKIM_private = $privatekeyfile;
			$mail->DKIM_selector = 'phpmailer';
			$mail->DKIM_passphrase = ''; //key is not encrypted
			
			
			try {
			  $mail->send();
			  unlink($privatekeyfile);
			  $results_messages[] = "Message has been sent using MAIL";
			  return $results_messages;
			}
			catch (phpmailerException $e) {
			  throw new phpmailerException('Unable to send to: ' . $to. ': '.$e->getMessage());
			}
			}
			catch (phpmailerException $e) {
			  $results_messages[] = $e->errorMessage();
			}
			
		}
		
	}
	public function getTokenKey(){
		$realKey = md5($this->InvoiceID . "InvoiceWestingPR");
		$realKey = substr($realKey, -16);
		return $realKey;
	}
	public function setTerms($days){
		global $con;
		$this->Terms = $days;
		$query = "UPDATE INVOICE_HEAD SET DueDate = DATE_ADD(DATE_ADD(NOW(), INTERVAL $days DAY), INTERVAL -4 HOUR), Terms = " . $days . " WHERE InvoiceID = " . $this->InvoiceID;
		//echo $query;
		mysqli_query($con,$query);
	}
	public function setSalesman($salesmanID){
		global $con;
		$sm = new Salesman($salesmanID);
		if($sm->ID){
			$query = "UPDATE INVOICE_HEAD SET Salesman = '" . $salesmanID . "' WHERE InvoiceID = " . $this->InvoiceID;
			$result = mysqli_query($con, $query);	
		}
		
	}
	public function deleteInvoiceItem($id){
		global $con;
		if(!$this->Status){
			$query = "DELETE FROM INVOICE_DETAIL WHERE id = $id AND InvoiceID = ". $this->InvoiceID;
			mysqli_query($con, $query);
			return mysqli_affected_rows($con);	
		}else{
			echo "Already Finalized";
			return false;
		}
		
	}
	public function addNewItem($sku, $qty = 1){
		global $con;
		if(!$this->Status){
			$item = new Item("%", "%", $sku);
			if(is_null($item->SKU)){
				
				return false;
			}
			$price = getCustomerPrice($item->Group, $item->Line, $item->SKU, $this->AccountNumber);
			$query = "INSERT INTO INVOICE_DETAIL (InvoiceID, `Group`, `Line`, SKU, Description, Notes, OrderQty, ShippedQty, AvgCost, Core, Price, Taxable1, Taxable2)
						VALUES (
						" . $this->InvoiceID .",
						'" . $item->Group . "',
						'" . $item->Line . "',
						'" . $item->SKU . "',
						'" . $item->Description . "',
						'" . $item->Notes . "',
						$qty,
						$qty,
						" . $item->AvgCost . ",
						" . $item->Core . ",
						" . $price . ",
						" . $item->Taxable1 . ",
						" . $item->Taxable2 . "
						
						)";
						
			return mysqli_query($con, $query);
		}else{
			echo "Already finalized";
			return false;
		}
	}
	public function setItemOrderQty($id, $qty){
		global $con;
		$query = "UPDATE INVOICE_DETAIL SET OrderQty = " . $qty . " WHERE ID = " . $id;
		$result = mysqli_query($con, $query);
	}
	public function setItemPrice($id, $price){
		global $con;
		$query = "UPDATE INVOICE_DETAIL SET Price = " . $price . " WHERE ID = " . $id;
		$result = mysqli_query($con, $query);
	}
	public function setItemShippedQty($id, $qty){
		global $con;
		$query = "UPDATE INVOICE_DETAIL SET ShippedQty = " . $qty . " WHERE ID = " . $id;
		$result = mysqli_query($con, $query);
	}
	public function setCrate($crateNumber){
		global $con;
		$query = "INSERT IGNORE INTO INVOICE_CRATE (InvoiceID, CrateNumber) VALUES ('" . $this->InvoiceID . "','$crateNumber')";
		//echo $query;
		$result = mysqli_query($con, $query);
		if($result){
			return true;
		}else{
			return false;
		}
	}
	public function removeCrate($crateNumber){
		global $con;
		$query = "DELETE FROM INVOICE_CRATE WHERE InvoiceID = '" . $this->InvoiceID . "' AND CrateNumber LIKE '$crateNumber'";
		//echo $query;
		$result = mysqli_query($con, $query);
		if($result){
			return true;
		}else{
			return false;
		}
	}
	public function getCrates(){
		global $con;
		$query = "SELECT * FROM INVOICE_CRATE WHERE InvoiceID = '" . $this->InvoiceID . "'";
		$result = mysqli_query($con, $query);
		$data = array();
		while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
			array_push($data, $row);
		}
		return $data;
		
	}
	public function save(){
	
		
		
		global $con;
		$this->Salesman = $this->SalesmanID;
		$query = "UPDATE INVOICE_HEAD SET ";
		$saveQuery = [];
		foreach($this->hasQuotes as $fieldName => $quotes){
			if($fieldName != "InvoiceID"){
				$saveQuery[] = $this->saveString($fieldName, $this->$fieldName);	
			}
		}
		$query .= implode(", ", $saveQuery) . " WHERE `InvoiceID` = " . $this->InvoiceID;
		mysqli_query($con, $query);
		//echo $query . "\n";
		$this->Salesman = new Salesman($this->SalesmanID);	
		
	}
	private function saveString($Column, $Value){
		
		if(is_null($Value)){
			$returnValue = "NULL";	
		}elseif(strtoupper($Value) == "NOW()"){
			$returnValue = "NOW()";
		}else{
			$returnValue = ($this->hasQuotes[$Column])?"'$Value'":"$Value";	
		}
		return " `$Column` = $returnValue ";
	}
	public function getInvoiceItem($Line, $SKU){
		$id=($this->ItemID[$Line . "|" . $SKU]);
		//var_dump($id);
		return new InvoiceItem($id);
	}
	public function updateCustomerInfo(){
		$this->Customer->Address1 = $this->BillToAddress1;
		$this->Customer->Address2 = $this->BillToAddress2;
		$this->Customer->City = $this->BillToCity;
		$this->Customer->State = $this->BillToState;
		$this->Customer->ZipCode = $this->BillToZip;
		if($this->BillToName != ""){
			$this->Customer->Name = $this->BillToName;	
		}
		
		$this->Customer->ShipToAddress1 = $this->ShipToAddress1;
		$this->Customer->ShipToAddress2 = $this->ShipToAddress2;
		$this->Customer->ShipToCity = $this->ShipToCity;
		$this->Customer->ShipToState = $this->ShipToState;
		$this->Customer->ShipToZip = $this->ShipToZip;
		$this->Customer->save();
		
	}
	
}

class InvoiceItem{
	public $OrderQty;
	public $ShippedQty;
	public $ID;
	private $hasQuotes, $PRIVATE_KEY, $TABLE_NAME;
	
	public function __construct($ID){
		global $con;
		
		//
		//	Private Key
		//
		$this->PRIVATE_KEY = "ID";
		//
		// Table name
		//
		$this->TABLE_NAME = "INVOICE_DETAIL";
		//
		// Get Table Column and add to object.
		//
		$query = "SELECT * FROM `{$this->TABLE_NAME}` JOIN INVENTORY USING(Line, SKU) WHERE `{$this->TABLE_NAME}`.`{$this->PRIVATE_KEY}` = $ID";
		$result = mysqli_query($con, $query);
		//echo $query . "<BR>";
		
		
		
		$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
		
		foreach($row as $key => $value){
			
				
				
				$this->$key = $value;
		}
		//
		// Get Columns Names and either if they need quotes in a query or not.
		//
		
		$this->hasQuotes = [];
		$query = "SHOW COLUMNS FROM `{$this->TABLE_NAME}`";
		$result = mysqli_query($con,$query);
		while($row = mysqli_fetch_array($result, MYSQLI_ASSOC)){
			if(stripos($row['Type'], "int") === 0 || stripos($row['Type'], "double") === 0 || stripos($row['Type'], "tinyint") === 0 || stripos($row['Type'], "numeric") === 0 || stripos($row['Type'], "double") === 0 || stripos($row['Type'], "decimal") === 0 || stripos($row['Type'], "float") === 0 || stripos($row['Type'], "bigint") === 0 || stripos($row['Type'], "real") === 0 || stripos($row['Type'], "bool") === 0){
				$this->hasQuotes[$row['Field']] = false;
			}else{
				$this->hasQuotes[$row['Field']] = true;
			}
		}
	}
	public function getAttribute($name){
		$inventoryItem = new InventoryItem($this->Group, $this->Line, $this->SKU);
		return $inventoryItem->getAttribute($name);
		
	}
	public function delete(){
		global $con;
		$query = $con->prepare("DELETE FROM `{$this->TABLE_NAME}` WHERE `{$this->PRIVATE_KEY}` = ?");
		$query->bind_param("i", $this->id);
		return $query->execute();
		
		
	}
	//
	// Function to create a "column = value" string usable by mysql query;
	//
	private function saveString($Column, $Value){
		
		
		if(is_null($Value)){
			$returnValue = "NULL";	
		}else{
			$returnValue = ($this->hasQuotes[$Column])?"'$Value'":"$Value";	
		}
		return " `$Column` = $returnValue ";
	}
	//
	// function to save all the values in the object to the table.
	//
	public function save(){
		global $con;
		
		$query = "UPDATE `{$this->TABLE_NAME}` SET ";
		$saveQuery = [];
		
		foreach($this->hasQuotes as $fieldName => $quotes){
			if($fieldName != $this->PRIVATE_KEY){
				$saveQuery[] = $this->saveString($fieldName, $this->$fieldName);
				//var_dump($this->saveString($fieldName, $this->$fieldName));
			}
			
		}
		$query .= implode(", ", $saveQuery) . " WHERE `{$this->PRIVATE_KEY}` = " . $this->{$this->PRIVATE_KEY};
		//echo $query;
		return mysqli_query($con, $query);
	}
	
	
	public function setPrice($Price){
		global $con;
		$query = "UPDATE `{$this->TABLE_NAME}` SET Price = " . $Price . " WHERE `{$this->PRIVATE_KEY}` = " . $ID;
		$result = mysqli_query($con, $query);
	}
}

?>