package Cyber::Booking;
use strict;
use warnings;

use Data::Dumper;
use String::Random;
use POSIX 'strftime';
use Encode;
use JSON;
use LWP::UserAgent;
use IO::Compress::Gzip qw(gzip);
use IO::Uncompress::Gunzip qw( gunzip );
use Cyber::Database;
use Date::Simple qw(date);
no warnings "uninitialized";

#Constructor
sub new {
	my $class = shift;
	
	my $obj = {};
	
	my $obj_database = new Cyber::Database;
	$obj->{'obj_database'} = $obj_database;
	
	bless $obj, $class;
	
	return $obj;
}

sub get_booking_list {
	my $class = shift;

	my $whr->{'is_booking_processed'} = 1;
	if ( $class->{'user_type'} == 2 ) {
		$whr->{'agent_id'} = $class->{'user_id'};
	}

	my $booking_list = $class->{'obj_database'}->get({
		'table'  => 'booking_master',
		'hash'   => 1,
		'select' => '*',
		'where'  => $whr
	});

	if ( defined $booking_list ) {
		$class->{'booking_list'} = $booking_list;
	}
	return 1;
}

sub fetch_property_list {
	my $class = shift;

	my $cgi_params = $class->{'cgi_params'};

	my $property_list = [];

	#Fetch Hotel list
	my $whr = undef;
	if ( defined $cgi_params->{'community'} && $cgi_params->{'community'} !~ /^\s*$/ ) {
		$whr->{'community_id'} = $cgi_params->{'community'};
	}
	if ( defined $cgi_params->{'no_of_bedrooms'} && $cgi_params->{'no_of_bedrooms'} !~ /^\s*$/ ) {
		$whr->{'no_of_bedroom'} = $cgi_params->{'no_of_bedrooms'};
	}
	
	unless ( defined $whr ) {
		$whr->{'1'} = 1;
	}

	$property_list = $class->{'obj_database'}->get({
		'table'  => 'hotel_master',
		'hash'   => 1,
		'select' => '*',
		'where'  => $whr
	});

	my $property_id_string = '';
	my $property_list_hash = {};
	if ( defined $property_list && scalar @$property_list ) {
		foreach my $x ( @$property_list ) {
			$property_id_string .= $x->{'hotel_code'};
			$property_id_string .= ',';

			delete $x->{'html_text_description'};

			$property_list_hash->{$x->{'hotel_code'}} = $x;
		}
		$property_id_string =~ s/,$//;

		if ( $property_id_string ) {
			$class->{'property_id_string'} = $property_id_string;
		}
		$class->{'property_list'} = $property_list_hash;
	}

	return 1;
}

sub fetch_available_property {
	my $class = shift;

	my $cgi_params = $class->{'cgi_params'};
	my $check_in_date = $cgi_params->{'check_in_date'};
	my $check_out_date = $cgi_params->{'check_out_date'};

	my $availability_list = undef;

	my $property_id_string = $class->{'property_id_string'};
	my $whr;
	if ( $property_id_string ) {
		$whr = [
			"hotel_code in ($property_id_string)"
		];

		$availability_list = $class->{'obj_database'}->get({
			'table'  => 'allocation_master',
			'hash'   => 1,
			'select' => '*',
			'where'  => $whr
		});
	}
	else {
		$availability_list = $class->{'obj_database'}->get({
			'table'  => 'allocation_master',
			'hash'   => 1,
			'select' => '*',
		});
	}

	my $available_property_string = '';

	my $diff_days = ::get_delta_days( $check_in_date, $check_out_date );
	if ( defined $availability_list && ref $availability_list eq 'ARRAY' ) {
		foreach my $x ( @$availability_list ) {
			my $hotel_code = $x->{'hotel_code'};
			my $booked_json = $x->{'availability'};

			my $booked_days_data = undef;
			eval {
				$booked_days_data = from_josn( $booked_json );
			};

			my $is_available = 1;
			if ( $diff_days > 0 ) {
				for ( my $i = 0; $i < $diff_days; $i++ ) {
					my $stay_date = ::add_number_of_day( $check_in_date, $i );

					if ( exists $booked_days_data->{$stay_date} ) {
						$is_available = 0;
					}
				}
			}

			if ( $is_available ) {
				$available_property_string .= $hotel_code;
				$available_property_string .= ',';
			}
		}
	}
	$available_property_string =~ s/,$//;

	$class->{'available_property_id_string'} = $available_property_string;

	return 1;
}

sub cancel_booking {
	my $class = shift;

	my $cgi_params = $class->{'cgi_params'};
	my $hotel_code = $cgi_params->{'hotel_code'};
	my $third_party_booking_id = $cgi_params->{'third_party_booking_id'};
	my $booking_master_id = $cgi_params->{'booking_master_id'};

	##Do first request
	my $url = $::config{'base_url'}->{'api_additional_url'};

	my $credential = $::config{'credential'};

	my $username = $credential->{'USERNAME'};
	my $password = $credential->{'PASSWORD'};

	my $xml = '<?xml version="1.0" encoding="utf-8"?>
	<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
	  <soap12:Body>
	    <CancelBooking xmlns="http://xml.ciirus.com/">
	      	<APIUsername>'.$username.'</APIUsername>
	      	<APIPassword>'.$password.'</APIPassword>
	      	<BookingID>'.$third_party_booking_id.'</BookingID>
	    </CancelBooking>
	  </soap12:Body>
	</soap12:Envelope>';

	my $response_xml = undef;
	eval {
		$response_xml = $class->make_request( $url, $xml, 'CancelBooking' );
	};

	my $response = undef;
	if ( defined $response_xml ) {
		eval {
			$response = ::parse_xml_data_by_xml_fast( $response_xml );
		};
	}
	
	my $is_error = 0;
	my $error_message = undef;		
	if ( defined $response ) {

		my $booking_response = $response->{'soap:Envelope'}->{'soap:Body'};
		if ( exists $booking_response->{'soap:Fault'} ) {
			$is_error = 1;
			$error_message = $booking_response->{'soap:Fault'}->{'soap:Reason'}->{'soap:Text'}->{'content'};
		}
		else {

			##update booking master
			eval {
				my $system_booking_id = $class->{'system_booking_id'};

				$class->{'obj_database'}->set(
					'table' => 'booking_master',
					'update' => {
						'booking_status'        => 2,
						'booking_status_string' => 'Cancelled',
						'is_booking_processed'  => 1,
						'cancelled_by_agent_id' => $class->{'user_id'},
						'modify_date'           => strftime("%Y-%m-%d %H:%M:%S", localtime(time())),
					},
					'where' => {
						'id' => $booking_master_id,
					}
				);
			};
		}
	}

	$class->{'is_cancel_error'} = $is_error;
	$class->{'cancel_error'} = $error_message;

	return 1;
}

sub make_request {
	my $class = shift;

	my $url = shift;
	my $xml = shift;
	my $action = shift;

	my $obj_useragent = LWP::UserAgent->new();   
	$obj_useragent->agent('Mozilla/5.0 [en] (Win98; U)');
	$obj_useragent->protocols_allowed( [ 'http', 'https']);

	my $request = HTTP::Request->new( POST => $url );
			
	$request->content( $xml );
	
	$request->content_type("application/soap+xml; charset=utf-8");
	$obj_useragent->default_header('SOAPAction' => 'http://xml.ciirus.com/'.$action);

	my $response = $obj_useragent->request($request);

	my $resp_content = $response->content;
	
	return $resp_content;
}

sub fetch_booking_master_data {
	my $class = shift;

	my $cgi_params = $class->{'cgi_params'};
	my $booking_master_id = $cgi_params->{'booking_master_id'};

	my $user_id = $class->{'user_id'};

	##special condition for search booking external via guest or via user
	my $whr = {};
	$whr->{'id'} = $booking_master_id;
	if ( $class->{'user_type'} != 1 ) {
		$whr->{'agent_id'} = $user_id;
	}

	my $get_booking_master_data = $class->{'obj_database'}->get({
		'table'  => 'booking_master',
		'hash'   => 1,
		'select' => '*',
		'where'  => $whr,
	});

	if ( defined $get_booking_master_data ) {
		$class->{'booking_master_data'} = $get_booking_master_data->[0];
	}

	return 1;
}

sub fetch_property_detail {
	my $class = shift;

	my $booking_master_data = $class->{'booking_master_data'};
	my $hotel_code = $booking_master_data->{'hotel_code'} ;

	my $property_detail = undef;
	my $whr->{'hotel_code'} = $hotel_code;

	eval {
		$property_detail = $class->{'obj_database'}->get({
			'table'  => 'hotel_master',
			'hash'   => 1,
			'select' => '*',
			'where'  => $whr
		});
	};

	if ( defined $property_detail ) {
		$class->{'property_detail'} = $property_detail->[0];
	}

	return 1;
}

sub send_email {
	my $class = shift;

	my $credential = $::config{'credential'};

    my $smtpserver   = $credential->{'EMAIL_HOST'};
	my $smtpport     = $credential->{'EMAIL_PORT'};
	my $smtpuser     = $credential->{'EMAIL_USER'};
	my $smtppassword = $credential->{'EMAIL_PASS'};

	use Email::Sender::Simple qw(sendmail);
	use Email::Sender::Transport::SMTPS ();
	use Email::Simple ();
	use Email::Simple::Creator ();
	use Email::MIME;

	my $transport = Email::Sender::Transport::SMTPS->new({
	 	host => $smtpserver,
	 	port => $smtpport,
	  	ssl => "starttls",
	  	sasl_username => $smtpuser,
	  	sasl_password => $smtppassword,
	});

	my $booking_status = 'Confirmed';
	if ( $class->{'booking_master_data'} == 2 ) {
		$booking_status = 'Cancelled';
	}

	my $from = $credential->{'EMAIL_FROM'};
	my $to = $class->{'booking_master_data'}->{'email'},
	my $subject = "Avanti Florida Villas $booking_status Booking Voucher:".$class->{'booking_master_data'}->{'third_party_booking_id'};
	my $body = $class->{'email_content'};

	my @parts = (
	    Email::MIME->create(
	        attributes => {
	            content_type => "text/html",
	            disposition  => "attachment",
	            charset      => "UTF-8",
	            encoding     => "base64",
	        },
	        body_str => $body,
	    ),
	);

	my $email = Email::MIME->create(
	    header_str => [
	        From => $from,
	        To => $to,
	        Subject => $subject,
	    ],
	    parts      => [ @parts ],
	);
	# my $email = Email::Simple->create(
	# 	header => [
	# 		To      => $to,
	# 		From    => $from,
	# 		Subject => $subject,
	# 	],
	# 	body => 'Testing',
	# );
	# $email->header_set( 'content-type' => 'text/html' );
	$email->content_type_set( 'text/html' );
	eval {
		sendmail($email, { transport => $transport });
	};
	if ( $@ ) {
		print $@;
	}
}

sub get_agent_detail {
	my $class = shift;

	my $cgi_params = $class->{'cgi_params'};
	my $agent_id = $class->{'booking_master_data'}->{'agent_id'} || $cgi_params->{'agent_id'};

	my $agent_detail = $class->{'obj_database'}->get({
		'table'  => 'user_master',
		'hash'   => 1,
		'select' => '*',
		'where'  => {
			'id' => $agent_id,
		}
	})->[0];

	if ( defined $agent_detail ) {
		$class->{'agent_detail'} = $agent_detail;
	}
	return 1;
}

1;
