#!/usr/bin/perl -Ilibs

package API::Order::Payment;

use strict;
use warnings;

use Carp;
use Try::Tiny;

use API::Order;

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

use ECS::DB;
use ECS::dbConfig;

use ECS::Time ();
use ECS::Order ();
use ECS::GP;
use ECS::Payment::OnAccount;
use ECS::Product::Inventory::Parkingspot;

use PerlX::Maybe;
###############################################################################
# Not an API method
# Requires
# - $p->{'order'}
# Now featuring API calls!
# Requires:
# - $p->{'orderID'}
sub invoice {
	my $p = shift;
	my $userID;
    my $result = {
        'success'   => 1,
		'update_DB'	=> $Config->{'update_DB'},
        };

    # called as an API method
    if(ref $p ne "HASH") {
        $p = shift;
        $userID = $p->{'userID'} || '';
        my $orderID = $p->{'orderID'};
        $p->{'input'}->{'orderIDs'} = [ $orderID ];

        $p->{'DBH'} ||= ECS::DB->connect({'config' => $ECS::dbConfig::db{'mysql'}});
        $p->{'DBH'} ||= ECS::DB->connect({'config' => $ECS::dbConfig::db{'mysqlSlave'}, readonly => 1});

        # load the necessary information to invoice the order.
        # we should already have this if we're being called non-API
        $p->{'order'} = ECS::Order->load({
            'DBH'       => $p->{'DBH'},
            'orderID'   => $orderID,
            });
        
    } else {
        $userID = $p->{'input'}->{'userID'} || '';
    }
	my $dropship = $p->{dropShip};
	$dropship ||= 0;
	my $pr_count = $p->{prCount} || 0;
	my $order_complete = defined $p->{orderComplete} ? $p->{orderComplete} : 1;
	my $pr_items = $p->{prItems} || 0;

	my $order = $p->{'order'};
	
	if ($order->{'INVOICED'} eq "YES" && lc($order->{status}) ne 'ds partial shipped' && lc($p->{input}{reqStatus}||'') ne 'ds partial shipped') {
		$p->{'notes'} = 'Order already invoiced.';
		API::Order::addNotes($p);
		return $result;
	}
    
	my $order_total_cents = 0;
    my $orderID = $p->{'orderID'};
	my $invoice = $p->{invoice};  
    for my $item (@{ $order->invoiceItems }) {
        
        # Can't adjust stock level of a service
        # Kits should have already been excluded in ECS::Order->invoiceItems builder
        next if $item->{'product'}->productType eq 'Service';
		my $qty = $item->{qty};
		my $product_id = $item->{product}->productID;

        if( $order->orderLocation->orderLocationID ) {
			ECS::Product::Inventory::Parkingspot::adjustParkingSpotQty({
				'productID' => $item->{'product'}->productID,
				'dbh'       => $p->{'DBH'},
				'scannerUserID' => $userID,
				'locs' => {
					$order->orderLocation->locID => (-${qty}),
				},
				
			});
		}
		
        $item->{'product'}->stockAdjustment({
            'qty' => (-1 * $qty),
            'reason' => 'invoice',
            'itemID' => $item->{'cartitemID'},
        });
    }

	$order->orderLocation->delete if( $order->orderLocation->orderLocationID );
	
	$order->{'POSinvoice'} = 'Invoiced';
	#$order->{'POSinvoice'} = $order_complete ? 'Invoiced' : sprintf '%02.0f', $order_remaining_cents;
    $order->{'INVOICED'} = "YES"; # $order_complete ? 'YES' : 'NO';
	
    my $hasManualPayment;
	for my $payment ($order->getActivePayments) {
		if ($payment->method eq 'onaccount'
            or $payment->method eq 'wiretransfer'
            ) {
			$payment->status('Paid');
            $hasManualPayment = 1;
		}
	}
	
    $result->{'data'}->{'POSinvoice'} = $order->{'POSinvoice'};
	
	# Update Order
	if (not $order->save) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to Update Order';
		return $result;
	}
    my $order_total = $invoice ? $invoice->total : $order->total;
    ECS::Payment::OnAccount::insertCreditAdjustment({
        'DBH'        => $p->{'DBH'},
        'customerID' => $order->customerID,
        'site'       => $order->site,
        'input'      => {
            'creditAmount' => -1 * $order_total,
            'creditReason' => 9, # Invoice
            'employeeID'   => "Invoice",
            'reasonText'   => "E#" . $order->orderID . ($pr_count ? ".$pr_count" : ""),
        },
    });

    my $courierCreditNotes;
    if($order->customer->courierCredit eq "YES"
        and $hasManualPayment
        ) {
        try {
            _courierCredit({
                'DBH'   => $p->{'DBH'},
                'order' => $order,
				order_total => $order_total,
            });
            $courierCreditNotes = "Automatically credited courier claim.";
        }
        catch {
            $courierCreditNotes = "Failed to automatically credit: $_";
        };
    }
    
    my $customer_balance = ECS::Payment::OnAccount::getCreditBalance({
        'DBH' => $p->{'DBH'},
        'customerID' => $order->customerID,
    });
    
    # ManageMore sent back customer balances as "positive if the Customer owes ECS money"
    $customer_balance *= -1;
    
    $result->{'data'}->{'customer_balance'} = $customer_balance;
	
	$p->{'notes'} = sprintf('Invoice created.%s balance $%0.2f.', (
		($order_complete ? ' final' : ''),
        $customer_balance,
    ));
    $p->{'notes'} .= " $courierCreditNotes" if $courierCreditNotes;
	API::Order::addNotes($p);
	if ($invoice) {
		my $couriers = ECS::Shipping::Courier::getCouriers;
		my $courier = $invoice->shipping->courier;
	}
    
    ECS::GP::enqueue({
        'action' => 'invoice',
        'orderID' => $order->orderID,
		maybe 'invoiceCount' => $pr_count,
		maybe 'invoiceID' => ($invoice ? $invoice->orderInvoiceID : undef),
		($dropship) ? (dropShip => 1) : (),
    });
	
    return $result;
}

###############################################################################

sub _courierCredit {
    my ($p) = @_;

    my $order = $p->{'order'}
        or croak "Missing order";
	my $order_total = $p->{order_total} || $order->total;

    my %reasons = (
        # siteID => storeCreditTransactionReasonID
        1 => 20, # ECS Courier Claim
        2 => 21, # TMS Courier Claim
    );
    my $creditReason = $reasons{ $order->site->siteID }
        or croak "Unable to find credit reason";

    my $trxID = ECS::Payment::OnAccount::insertCreditAdjustment({
        'DBH'        => $order->DBH,
        'customerID' => $order->customerID,
        'site'       => $order->site,
        'input'      => {
            'creditAmount' => $order_total,
            'creditReason' => $creditReason,
            'employeeID'   => "Courier Claim",
            'reasonText'   => "E#" . $order->orderID,
        },
    });

    croak "Failed to create credit adjustment"
        unless $trxID;

    ECS::GP::enqueue({
        'action'                   => "balanceAdjustment",
        'storeCreditTransactionID' => $trxID,
        'siteID'                   => $order->site->siteID,
    });

    return;
}

###############################################################################

1;
