#!/usr/bin/perl -Ilibs

use strict;
use warnings;

package API::Product;

use API::Config;

use lib $API::Config::Config->{'Website_libs'};

use ECS::DB;
use ECS::dbConfig;
use ECS::Search::Product;
use ECS::Site;

use TMS::Product;
use TMS::Product::Format;
use TMS::Product::PricingRule::RuleRunner;
use TMS::Product::ProductHandler;
use TMS::Search::Product;

our $call = sub { 
    my $self = shift; 
    return unless $self; 
    my $method = shift;  
    return unless $method; 
    if (ref $self eq 'HASH') {
        return unless exists $self->{$method};
        return $self->{$method};
    } else {
        return unless $self->can( $method ); 
        return $self->$method(@_);
    }
};

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

# Searches product.description
# Returns array of hashes with keys: productID, descripion
# Returned array is sorted by search result score
sub createTMS { 
	my $class = shift;
	my $input = shift;
	our $call;
	
	my $response = {
		'success' => 1,
		'error' => undef,
		'update_DB'	=> $API::Config::Config->{'update_DB'}
	};
    
    unless ($input->{'productID'}) {
        $response->{'success'} = 0;
		$response->{'error'} = 'productID is required';
		return $response;
    }

    my $estore_dbh = ECS::DB->connect({'config' => $ECS::dbConfig::db{'mysql'}});
    my $tms_dbh = ECS::DB->connect({'config' => $ECS::dbConfig::db{'tms'}});
    
    my $productHandler = TMS::Product::ProductHandler->new({
        'dbh' => $estore_dbh,
        'dbhtms' => $tms_dbh,
        'search' => [{
            'me.productID' => $input->{'productID'},
        }],
    });
    

    my $productRow = $productHandler->productRows->[0];
    
    unless ($productRow) {
        $response->{'success'} = 0;
		$response->{'error'} = 'Failed to fetch Source Product';
		return $response;
    }
    
    my $productRowsMap = $productHandler->getRowsMap($productRow);


   	if ($productRowsMap->{'TMS.product'} && 
		(($productRowsMap->{'TMS.product'}->isa('ECS::DB::Schema::Result::Product') &&
			$productRowsMap->{'TMS.product'}->$call('TMSproduct')->$call('tmsProductID')) ||
		($productRowsMap->{'TMS.product'}->isa('ECS::DB::Schema::Result::TMS::Product') &&
			$productRowsMap->{'TMS.product'}->$call('tmsProductID')) )) {
		$response->{'success'} = 0;
		$response->{'error'} = 'TMS Product already exists';
		return $response;
    }
    
    if (($productRow->type || '') eq 'Kit') {
        for my $componentRow (@{ $productRowsMap->{'productComponent'} }) {
            my $componentProductRowsMap = $productHandler->getComponentRowsMap($componentRow);
            
            if (!$componentProductRowsMap->{'TMS.product'}
                    && !($componentRow->$call('product')->$call('TMSproduct')->$call('tmsProductID'))  
                    && !($componentRow->$call('TMSproduct')->$call('tmsProductID'))) {
                $response->{'success'} = 0;
                $response->{'error'} = sprintf('Kit Component ES#%d must exist as TMS Product before creating TMS Kit', (
                    $componentRow->componentProductID,
                ));
                return $response;
            }
        }
    }
    
    # check we don't have a partnumber conflict before creating
    # a new tms product (partnumber is copied from estore.product
    # to tms.product)
    my $tmsProductSearch = ECS::DB::Schema::getSchema({
        dbh     => $tms_dbh,
        schema  => 'TMS::Product'
    })->search({
        'me.partnumber' => $productRow->partnumber,
    });
    if ( my $tmsPartnumberMatch = $tmsProductSearch->next ) {
        $response->{'success'} = 0;
        $response->{error} = sprintf 'Partnumber %s already exists on Turner Product T#%d (ES#%d)' =>
            $tmsPartnumberMatch->partnumber,
            $tmsPartnumberMatch->tmsProductID,
            $tmsPartnumberMatch->productID;
        return $response;
    }

    my $tmsProductRow = $productHandler->getNewRow('TMS.product');
    
    # Copy column data from estore.product to tms.product
    # also copy noindividual
    $tmsProductRow->set_columns({
        (map { $_ => $productRow->$_ } qw(
            productID
            partnumber
            description
            noindividual
        )),
        'seName' => TMS::Product::Format::descriptionToSEName($productRow->description),
        %{ $input->{'overrideColumns'} || {} },
    });

    my $baseProductVendorColumns = $productHandler->getSchemaColumns('productVendor');
    my $tmsProductVendorColumns = $productHandler->getSchemaColumns('TMS.productVendor');
    my @tmsProductVendorRows;
    # support overriding product vendor columns, similarly to how we override product columns
    $input->{vendorOverrideColumns} ||= {};

    for my $productVendorRow (@{ $productRowsMap->{'productVendor'} }) {
        my $tmsProductVendorRow = $productHandler->getNewRow('TMS.productVendor');
        
        push(@tmsProductVendorRows, $tmsProductVendorRow);
        
        # Copy column data from estore.productVendor to tms.productVendor
        my %baseProductVendorData = ();
        for my $column ( keys %{ $baseProductVendorColumns } ) {
            if ( $tmsProductVendorColumns->{ $column } ) {
                $baseProductVendorData{ $column } = $productVendorRow->$column;
            }
        }

        $tmsProductVendorRow->set_columns({
            %baseProductVendorData,
            %{ $input->{vendorOverrideColumns} || {} },
        });
        
    }
    
    $productRowsMap->{'TMS.product'} = $tmsProductRow;
    $productRowsMap->{'TMS.productVendor'} = \@tmsProductVendorRows;
	
    unless ($input->{vendorOverrideColumns} && $input->{vendorOverrideColumns}{ruleOverride}) {
        my $ruleRunner = TMS::Product::PricingRule::RuleRunner->new({
            'dbh' => $estore_dbh,
            'dbhtms' => $tms_dbh,
            'productHandler' => $productHandler,
        });
        $ruleRunner->applyRules();
    }
    
    $tmsProductRow->insert();
    
    for my $tmsProductVendorRow (@tmsProductVendorRows) {
        $tmsProductVendorRow->insert();
    }

    my $tmsProduct = TMS::Product->new({
        'estore_dbh' => $estore_dbh,
        'tms_dbh'    => $tms_dbh,
        'productID'  => $input->{'productID'},
    });

    if($input->{'copyImages'}) {
        my $product = ECS::Product->new({
            'dbh'       => $estore_dbh,
            'productID' => $input->{'productID'},
        });
        _copyImages({
            'dbh'        => $estore_dbh,
            'dbhtms'     => $tms_dbh,
            'product'    => $product,
            'tmsProduct' => $tmsProduct,
        });
    }
   
    ECS::Search::Product::update($input->{'productID'}, {
        'doc' => {
            'tms' => TMS::Search::Product::productObjectToIndexData(
                $tmsProduct,
            ),
        },
    });
    
    $response->{'data'}->{'tmsProductID'} = $tmsProductRow->tmsProductID;
    
	return $response;
}

###############################################################################
# Non-API method, copy images from an ECS product to a TMS product
sub _copyImages {
    my $p = shift;

    my $sql = q{
        SELECT
            image.imageID
        FROM image
        JOIN imageref
            USING (imageID)
        WHERE
            imageref.partnumber = ?
        ORDER BY
            imageref.displayOrder
    };
    my $sthGetImages = $p->{'dbh'}->prepare( $sql );
    $sthGetImages->execute( $p->{'product'}->partnumber );

    my @imageIDs = map { $_->[0] } @{ $sthGetImages->fetchall_arrayref };

    $sql = q{
        INSERT INTO
            imageref
        SET
            imageID      = ?,
            partnumber   = ?,
            displayOrder = ?
    };
    my $sthAddImage = $p->{'dbhtms'}->prepare( $sql );

    my $displayOrder = 0;
    for my $imageID (@imageIDs) {
        $sthAddImage->execute(
            $imageID,
            $p->{'tmsProduct'}->partnumber,
            $displayOrder ++,
        );
    }

    $sql = q{
        UPDATE image
        JOIN imageref
            USING (imageID)
        SET
            status = 'AddingTMS'
        WHERE
            imageref.partnumber = ?
    };
    my $sthAddingTMS = $p->{'dbh'}->prepare( $sql );
    $sthAddingTMS->execute( $p->{'product'}->partnumber );
    
    my $ecsMainimage = ($p->{'product'}->mainimage);
    if($ecsMainimage) {
        $sql = qq(
            UPDATE product
            SET 
                mainimage = ?
            WHERE 
                productID = ?;
 
        );
        
        my $sthAddingTMSMainimage = $p->{'dbhtms'}->prepare( $sql );
        $sthAddingTMSMainimage->execute( $ecsMainimage, $p->{'product'}->productID );
    }
    else{
        $sql = qq{
            UPDATE product 
            SET 
                mainimage = ( select imageID from imageref where partnumber = ? limit 1 )
            WHERE
               productID = ?;

        };
        
        my $sthAddingTMSMainimage = $p->{'dbhtms'}->prepare( $sql );
        $sthAddingTMSMainimage->execute( $p->{'tmsProduct'}->partnumber, $p->{'product'}->productID );
    }

    return;
}

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

1;
