use strict;
use warnings;

package API::Product::PricingImport;

use MIME::Base64;
use MIME::Entity;
use MIME::Lite;

use Acme::Damn ();

use List::MoreUtils qw/uniq/;

use SOAP::Lite ();
use base 'SOAP::Server::Parameters';

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

use ECS::Config;
use ECS::SQL;

use ECS::Product::PricingImport ();
use ECS::Product::PricingImport::Detail;
use ECS::Product::PricingImport::Report;
use ECS::Product::PricingImport::Summary;
use ECS::Product::PricingImport::Vendor ();
use ECS::Product::PricingImport::PreProcess;

my $website_config = \%ECS::Config::c;

return 1;

sub getIndex {
	my $self = shift;
	my $input = shift;
	
	my $imports_by_status = {
		'preprocess' => [],
		'init' => [],
		'review' => [],
		'commit' => [],
		'complete' => [],
		'cancel' => [],
		'error' => []
	};
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'data' => $imports_by_status,
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	my $DBH = ECS::SQL::connect();
	
	my @importIDs;
	
	my $query = '
		SELECT pricingImportID
		FROM pricingImport
		ORDER BY
			dtInitStart DESC,
			dtCommitStart DESC,
			pricingImportID DESC
		';
	
	map {
		push(@importIDs, $_->{'pricingImportID'});
	} @{ ECS::SQL::query({ 'DBH' => $DBH, 'sql' => $query, nolimit => 1 }) || [] };
	
	if (not @importIDs) {
		return $result;
	}
	
	my $imports = ECS::Product::PricingImport::Summary->loadMulti({
		'DBH' => $DBH,
		'pricingImportID' => \@importIDs
	});

	foreach my $pricingImportID (@importIDs) {
		if ($imports->{$pricingImportID}) {
			push(@{ $imports_by_status->{$imports->{$pricingImportID}->{'status'}} }, $imports->{$pricingImportID});
		}
	}
	
	# Get PreProcessor items as well.
	my @importPreProcessIDs;
	
	$query = '
		SELECT pricingImportPreProcessID
		FROM pricingImportPreProcess
		ORDER BY
			dtCreated DESC,
			pricingImportPreProcessID DESC
		';
	
	map {
		push(@importPreProcessIDs, $_->{'pricingImportPreProcessID'});
	} @{ ECS::SQL::query({ 'DBH' => $DBH, 'sql' => $query, nolimit => 1 }) || [] };
	
	if (not @importPreProcessIDs) {
		return $result;
	}
	
	$imports = ECS::Product::PricingImport::PreProcess->loadMulti({
		'DBH' => $DBH,
		'pricingImportPreProcessID' => \@importPreProcessIDs
	});

	foreach my $pricingImportPreProcessID (@importPreProcessIDs) {
		if ($imports->{$pricingImportPreProcessID}) {
            delete $imports->{$pricingImportPreProcessID}->{'DBH'};
            delete $imports->{$pricingImportPreProcessID}->{'DBHr'};
			push(@{ $imports_by_status->{'preprocess'} }, $imports->{$pricingImportPreProcessID});
		}
	}

	return $result;
}

# Retrieves
# - PricingImport Column specifications
# - all vendors capable of doing Pricing Imports (has markup_method)
# - all brands
sub getVendorsBrandsCols {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'data' => {},
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	my @cols;
	
	foreach my $k (keys %ECS::Product::PricingImport::cols) {
		my $col = $ECS::Product::PricingImport::cols{$k};
		
		push(@cols, {
			'label' => $k,
			'required' => ($col->{'required'} || 0),
			'field' => $col->{'field'},
			'type' => $col->{'type'},
			'notes' => $col->{'notes'}
		});
	}
	
	$result->{'data'}->{'cols'} = \@cols;
	
	my $DBH = ECS::SQL::connect();
	
	my @vendors;
	
	foreach my $vendor (@{ ECS::Product::PricingImport::Vendor::fetchAll({ 'DBH' => $DBH }) }) {
		push(@vendors, eval { Acme::Damn::damn($vendor) });
	}
	
	$result->{'data'}->{'vendors'} = \@vendors;
	
	my $query = 'SELECT
            brand.brandID,
            COALESCE(brand.name, brand.brandID) AS name,
            brand.abbr
        FROM
            brand
        WHERE
            brand.abbr IS NOT NULL
        ORDER BY
            UPPER(name)';
	$result->{'data'}->{'brands'} = ECS::SQL::query({ 'DBH' => $DBH, 'sql' => $query, nolimit => 1 }) || [];
	
	return $result;
}

sub saveNotes {
	my $self = shift;
	my $input = shift;
	
	if (not $input->{'pricingImportID'}) {
		return {
			'success' => 0,
			'error' => 'pricingImportID is Required',
			'update_DB'	=> $Config->{'update_DB'}
		};
	}
	
	my $DBH = ECS::SQL::connect();
	
	if (
		ECS::Product::PricingImport::Detail::saveNotes({
			'DBH' => $DBH,
			'pricingImportID' => $input->{'pricingImportID'},
			'notes' => $input->{'notes'}
		})
	) {
		return {
			'success' => 1,
			'error' => undef,
			'update_DB'	=> $Config->{'update_DB'}
		}
	} else {
		return {
			'success' => 0,
			'error' => 'Failed to Save Pricing Import Notes',
			'update_DB'	=> $Config->{'update_DB'}
		}
	}
}

sub saveVendorNotes {
	my $self = shift;
	my $input = shift;
	
	if (not $input->{'vendorID'}) {
		return {
			'success' => 0,
			'error' => 'Vendor is Required',
			'update_DB'	=> $Config->{'update_DB'}
		};
	}
	
	my $DBH = ECS::SQL::connect();
	
	if (
		ECS::Product::PricingImport::Vendor::saveImportNotes({
			'DBH' => $DBH,
			'vendorID' => $input->{'vendorID'},
			'importNotes' => $input->{'importNotes'}
		})
	) {
		return {
			'success' => 1,
			'error' => undef,
			'update_DB'	=> $Config->{'update_DB'}
		}
	} else {
		return {
			'success' => 0,
			'error' => 'Failed to Save Vendor Pricing Import Notes',
			'update_DB'	=> $Config->{'update_DB'}
		}
	}
}

sub newImport {
	my $self = shift;
	my $input = shift;
	my $envelope = pop;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'data' => {},
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	foreach my $k ('employeeID', 'ipaddr', 'vendorID', 'brandID') {
		if (not $input->{$k}) {
			$result->{'success'} = 0;
			$result->{'error'} = $k.' is required to create new Pricing Import';
			return $result;
		}
	}
	
	my @parts = $envelope->parts();
	my $file;
	
	if (
		defined($parts[0])
		and defined($parts[0]->[0])
	) {
		$file = $parts[0]->[0];
	} else {
		$result->{'success'} = 0;
		$result->{'error'} = 'No pricing file found';
		return $result;
	}
	
	my $DBH = ECS::SQL::connect();
	
	$input->{'status'} = 'init';
	
	$input->{'overrideMarkupMethod'} ||= 'NO';
	$input->{'overrideTargetMarkup'} ||= 'NO';
	
	my $pricingImportID = ECS::SQL::insert({
		'DBH' => $DBH,
		'table' => 'pricingImport',
		'columns' => ['employeeID', 'ipaddr', 'vendorID', 'brandID', 'status', 'overrideMarkupMethod', 'overrideTargetMarkup', 'importType'],
		'hash' => $input
	});
	
	if (not $pricingImportID) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Unable to create new Pricing Import';
		return $result;
	}
	
	ECS::Product::PricingImport::Detail::saveNotes({
		'DBH' => $DBH,
		'pricingImportID' => $pricingImportID,
		'notes' => $input->{'notes'}
	});
	
	ECS::Product::PricingImport::Vendor::saveImportNotes({
		'DBH' => $DBH,
		'vendorID' => $input->{'vendorID'},
		'importNotes' => $input->{'vendorImportNotes'}
	});
	
	ECS::Product::PricingImport::Vendor::saveCalcFields({
		'DBH' => $DBH,
		'vendorID' => $input->{'vendorID'},
		'calcFields' => $input->{'calcFields'}
	});
	
	ECS::Product::PricingImport::Detail::saveCalcFields({
		'DBH' => $DBH,
		'pricingImportID' => $pricingImportID,
		'calcFields' => $input->{'calcFields'}
	});
	
	# Split the Comma Separated String and save each vendorID
	my @updateVendorIDs = split(/,/, $input->{'updateVendorIDs'});
    @updateVendorIDs = uniq(@updateVendorIDs);
	foreach my $vendorID (@updateVendorIDs) {
		ECS::Product::PricingImport::Detail::saveUpdateVendors({
			'DBH' => $DBH,
			'pricingImportID' => $pricingImportID,
			'vendorID' => $vendorID
		});
	}
	
	# Split the Comma Separated String and save each brandID
	my @updateBrandIDs = split(/,/, $input->{'updateBrandIDs'});
    @updateBrandIDs = uniq(@updateBrandIDs);
	foreach my $brandID (@updateBrandIDs) {
		ECS::Product::PricingImport::Detail::saveUpdateBrands({
			'DBH' => $DBH,
			'pricingImportID' => $pricingImportID,
			'brandID' => $brandID
		});
	}
	
	if (open(my $of, '>'.$website_config->{'pricing_import'}->{'file_dir'}.'/init/import_'.$pricingImportID.'.zip')) {
		print $of $file->bodyhandle->as_string;
	} else {
		$result->{'success'} = 0;
		$result->{'error'} = 'Unable to save pricing file';
		return $result;
	}
	
	$result->{'data'}->{'pricingImportID'} = $pricingImportID;
	
	return $result;
}

sub getDetails {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'data' => {},
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	$input->{'pricingImportID'} =~ s/\D//g;
	
	if (not $input->{'pricingImportID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Pricing Import ID is required to fetch details';
		return $result;
	}
	
	my $DBH = ECS::SQL::connect();
	
	my $import = ECS::Product::PricingImport::Detail->load({
		'DBH' => $DBH,
		'pricingImportID' => $input->{'pricingImportID'}
	});
	
	if ($import) {
		
		if ($import->{'status'} eq 'complete') {
			$import->loadReportSummaries();
		}
		
		# DBH can't be passed through SOAP
		delete($import->{'DBH'});
		delete($import->{'DBHr'});
	}
	
	$result->{'data'} = $import;
	
	return $result;
}

sub cancelImport {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	$input->{'pricingImportID'} =~ s/\D//g;
	
	if (not $input->{'pricingImportID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Pricing Import ID is required to cancel import';
		return $result;
	}
	
	my $DBH = ECS::SQL::connect();
	
	my $import = ECS::Product::PricingImport::Detail->load({
		'DBH' => $DBH,
		'pricingImportID' => $input->{'pricingImportID'}
	});
	
	$import->{'status'} = 'cancel';
	
	if (not $import->save()) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to Update Pricing Import';
	}
	
	if (not $import->archive()) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to Archive Parts';
	}
	
	return $result;
}

sub commitImport {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	$input->{'pricingImportID'} =~ s/\D//g;
	
	if (not $input->{'pricingImportID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Pricing Import ID is required to commit import';
		return $result;
	}
	
	my $DBH = ECS::SQL::connect();
	
	my $import = ECS::Product::PricingImport::Detail->load({
		'DBH' => $DBH,
		'pricingImportID' => $input->{'pricingImportID'}
	});
	
	$import->{'status'} = 'commit';
	
	if ($import->save()) {
		$result->{'success'} = 1;
	} else {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to Update Pricing Import';
	}
	
	return $result;
}

sub loadReportItems {
	my $self = shift;
	my $input = shift;
	
	if (not $input->{'pricingImportID'}) {
		return {
			'success' => 0,
			'error' => 'Pricing Import ID is required',
			'update_DB'	=> $Config->{'update_DB'}
		}
	}
	
	if (not $input->{'reportKey'}) {
		return {
			'success' => 0,
			'error' => 'Report Key is required',
			'update_DB'	=> $Config->{'update_DB'}
		}
	}
	
	my $DBH = ECS::SQL::connect();
	
	my $report = ECS::Product::PricingImport::Report->loadSummary({
		'DBH' => $DBH,
		'pricingImport' => {
			'pricingImportID' => $input->{'pricingImportID'}
		},
		'report_key' => $input->{'reportKey'}
	});
	
	$report->loadItemsDisplay($input->{'index'}, $input->{'offset'});
	
	return {
		'success' => 1,
		'data' => $report->{'items'},
		'error' => undef,
		'update_DB'	=> $Config->{'update_DB'}
	}
}

sub getPriceUpdateReport {
	my $self = shift;
	my $input = shift;
	
	my $result = {
		'success' => 1,
		'error' => undef,
		'data' => {},
		'update_DB'	=> $Config->{'update_DB'}
	};
	
	$input->{'pricingImportID'} =~ s/\D//g;
	
	if (not $input->{'pricingImportID'}) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Pricing Import ID is required to commit import';
		return $result;
	}
	
	my $DBH = ECS::SQL::connect();
	
	my $import = ECS::Product::PricingImport::Summary->load({
		'DBH' => $DBH,
		'pricingImportID' => $input->{'pricingImportID'}
	});
	
	if (not $import) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to load Pricing Import';
		return $result;
	}
	
	if (not $import->getPriceUpdateReport()) {
		$result->{'success'} = 0;
		$result->{'error'} = 'Failed to load Pricing Update Report';
		return $result;
	}
	
	$result->{'data'}->{'pricingImport'} = $import;
	
	return $result;
}
