#!/usr/bin/perl
use strict;

package API::Order::Shipping::Shipment;

use API::Order::Shipping;
use API::Order::Shipping::Package;

our $Config;
BEGIN {
	use API::Config;
	$Config = $API::Config::Config;
}
use lib ($Config->{'Website_libs'});

use ECS::SQL;
use ECS::Shipping;
use ECS::Shipping::Shipment;

# Requires
# - orderID
sub overrideShipment {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'update_DB'	=> $Config->{'update_DB'}
	};

	my $p = {
		'DBH' => ECS::SQL::connect(),
		'DBH' => ECS::SQL::connect('SLAVE'),
		'input' => $input
	};
	
	if (!defined $p->{'input'}->{'orderID'} || !$p->{'input'}->{'orderID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'No order specified';
		return $result;
	}
	
	$p->{'orderID'} = $p->{'input'}->{'orderID'};
	
	return $result if (!$Config->{'update_DB'});
	
	$p->{'input'}->{'typeID'} = 'orderID';
	
	if (!API::Order::Shipping::getShippingSummary($p)) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Unable to retrieve order details';
		return $result;
	}
	
	foreach my $k (keys %{ $p->{'order'} }) {
		$p->{'input'}->{$k} = $p->{'order'}->{$k};
	}
	
	API::Order::Shipping::getCourier($p);
	
	API::Order::Shipping::getWarehouseShipment($p);
	
	API::Order::Shipping::Package::getShippedPackages($p);

	# despite of the shipmentType, save only shipments by part
	# when trying to override by dims, ignore and save by part
	$p->{'keyType'} = 'part';
	if (!ECS::Shipping::Shipment::saveShipment($p)) {
		$result->{success} = 0;
		$result->{error} = 'Failed to save shipment configuration';
		return $result;
	}

	# Update order with ignoreShipment = 'override'
	if (!ECS::SQL::query({ 
		'DBH' => $p->{'DBH'}, 
		'sql' => "UPDATE orderShipping SET ignoreShipment = 'override', shipmentID = ".$p->{'order'}->{'shipmentID'}." WHERE orderID = ".$p->{'order'}->{'orderID'} 
		})
		) {
		$result->{success} = 0;
		$result->{error} = 'Failed to update order details';
		return $result;
	}

	return $result;
}

# Not an API method
# Requires
# - $p->{'order'}
# - $p->{'order'}->{'packages'}
# - $p->{'order'}->{'packagesVolume'} (must savePackages to get this)
# - $p->{'shipment'}
# Sets
# - $p->{'order'}->{'ignoreShipment'}
# - $p->{'order'}->{'shipmentID'} (in some cases)
sub savePreviousShipment {
	my $p = shift;
	my $order = $p->{'order'};

	# don't save the shipping quote for Freight
	$order->{'ignoreShipment'} = 'custom' if ( 
		defined $order->{'shipmentID'} 
		&& $order->{'shipmentID'} 
		&& $order->{'hasCustomBox'}
		&& $p->{'courier'}->{'shippingCourierCode'} eq 'FREIGHT'
		); 
	
	# All products that are in the warehouse should have dimSet = 1	
	return 1 if ( !defined $p->{'shipment'} || !$p->{'shipment'}->{'dimSet'} ); 

	# The shipment has at least one type of previous shipment
	if ( ECS::Shipping::Shipment::orderHasPreviousShipment($p) ) {
		
		# Shipment has history by part; not sure if it has by dims as well
		# but we don't care if it has shipment by dims 
		# because we assume that it was saved when the shipment by part was saved first 
		# and we don't modify the previous shipment by dims once it was inserted
		if ( $order->{'shipmentKeyType'} eq 'part' and $order->{'inputIgnoreShipment'} ) { 

			$p->{'keyType'} = 'part';
			
			# Attempt to Optimize Previous Shipments: the packer ignored the previous shipment info
			# Check if the packer packed more efficiently than the existing previous shipment (compare total box volumes)
			
			# If total package volume is less than total estimated boxes volume, packer wins :)
			if (sprintf('%0.2f', $order->{'packagesVolume'}) < sprintf('%0.2f', $order->{'boxEstimatesVolume'})) {

				if (ECS::Shipping::Shipment::saveShipment($p)) {
					$order->{'ignoreShipment'} = 'won';
				} else {
					return 0;
				}
				
			} else { # packer loses :(
				$order->{'ignoreShipment'} = 'lost';
			}
		}
		# Shipment has no history by part, so insert a brand new entry in the DB
		# Don't care about the history by dims since we don't override it any more
		elsif ( $order->{'shipmentKeyType'} eq 'dims') {
			$p->{'keyType'} = 'part';
			ECS::Shipping::Shipment::saveShipment($p);
		} else {
			return 0; # This should never happen; All shipmentIDs should have a type ('part' or 'dims')
		}
	} 
	# Save both shipment by Part and by Dims since the shipment has no history of previous shipments	
	else {
		# Save the previous shipment by dims first
		$p->{'keyType'} = 'dims';
		ECS::Shipping::Shipment::saveShipment($p);
		
		# Save the previous shipment by part second
		# because we want the shipmentID of by part to remain in the $p hash
		$p->{'keyType'} = 'part';
		undef $p->{'shipment'}->{'newShipmentBoxes'}; # clear old boxes
		ECS::Shipping::Shipment::saveShipment($p);
	}
	
	return 1;
}

# Requires
# - orderID
sub voidShipment {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	my $p = {
		'DBH'  => ECS::SQL::connect(),
		'DBHr' => ECS::SQL::connect('SLAVE'),
		'input' => $input
	};
	
	if (!defined $p->{'input'}->{'orderID'} || !$p->{'input'}->{'orderID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'No order specified';
		return $result;
	}
	
	return $result if (!$Config->{'update_DB'});
	
	$p->{'orderID'} = $p->{'input'}->{'orderID'};
	
	if (!API::Order::Shipping::getShippingSummary($p)) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Unable to retrieve order details';
		return $result;
	}
	
	foreach my $k (keys %{ $p->{'order'} }) {
		$p->{'input'}->{$k} = $p->{'order'}->{$k};
	}
	
	$p->{'input'}->{'typeID'} = 'orderID';
	
	API::Order::Shipping::getCourier($p);
	
	API::Order::Shipping::getService($p);
	
	API::Order::Shipping::getWarehouseShipment($p);
	
	API::Order::Shipping::Package::getShippedPackages($p);
	
	API::Order::Shipping::Package::buildPackageProductDetails($p);
	
	if (!ECS::Shipping::Package::hasLabels($p)) {
		$result->{'success'} = 0;
		$result->{'error'} = 'No Shipping Labels to Void';
		return $result;
	}
	
	my ($success, $error) = ECS::Shipping::Package::voidLabels($p);
	
	if (!$success) {
		$result->{'success'} = 0;
		$result->{'error'} = $error;
		return $result;
	}
	
	return $result;
}

sub getIgnoreShipmentReasons {
	my $p = shift;
	
	my $sql = 'SELECT ignoreShipmentReasonID, reason FROM ignoreShipmentReason WHERE active = 1';
	return ECS::SQL::query({ 'DBH' => $p->{'DBHr'}||$p->{DBH}, 'sql' => $sql });
}

sub getOverridePackReasons {
	my $p = shift;
	
	my $sql = 'SELECT overridePackReasonID, reason, active FROM overridePackReason WHERE active = 1';
	return ECS::SQL::query({ 'DBH' => $p->{'DBHr'}||$p->{DBH}, 'sql' => $sql });
}

1;
