/**
 * Invoices Module - Cleaned Version
 * 
 * 16 controllers extracted to /controllers/ directory
 * Controllers are loaded via controllers.js manifest
 * 
 * This module now contains:
 * - Module definition and configuration
 * - Route configuration
 * - Services and factories
 * - Directives (if any)
 */

var Invoices = angular.module('invoices', []);

Invoices.config(['$routeProvider', function ($routeProvider) {

	// ------------- Sale Receipts ---------------- //

	$routeProvider.when('/sales/new', {
		controller: 'SalesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/sales/new/:taskId', {
		controller: 'SalesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/sales/booking/:taskId', {
		controller: 'SalesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/sales/browse', {
		controller: 'SalesBrowseCtrl',
		templateUrl: 'invoices/browse.html'
	});

	$routeProvider.when('/sales/view/:saleId', {
		controller: 'SalesViewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/sales/new/booking/:clientType/:clientId/:repairId', {
		controller: 'SalesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	// ------------- INVOICES ---------------- //

	$routeProvider.when('/invoices/new/', {
		controller: 'InvoicesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/invoices/new/:taskId', {
		controller: 'InvoicesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/invoices/new-project/:projectId', {
		controller: 'InvoicesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/invoices/view/:invoiceId', {
		controller: 'InvoicesViewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/invoices/browse/', {
		controller: 'InvoicesBrowseCtrl',
		templateUrl: 'invoices/browse.html'
	});

	// ------------- Quotes ---------------- //

	$routeProvider.when('/quotes/new/', {
		controller: 'QuotesNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/quotes/view/:quoteId', {
		controller: 'QuotesViewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/quotes/browse/', {
		controller: 'QuotesBrowseCtrl',
		templateUrl: 'invoices/browse.html'
	});

	// ------------- Purchase Orders ---------------- //

	$routeProvider.when('/purchase-orders/new/', {
		controller: 'PurchaseOrdersNewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/purchase-orders/view/:invoiceId', {
		controller: 'PurchaseOrdersViewCtrl',
		templateUrl: 'invoices/new.html'
	});

	$routeProvider.when('/purchase-orders/browse/', {
		controller: 'PurchaseOrdersBrowseCtrl',
		templateUrl: 'invoices/browse.html'
	});

	// ------------- Kashflow ---------------- //

	$routeProvider.when('/kashflow/sync/', {
		controller: 'KashflowSyncCtrl',
		templateUrl: 'kashflow/sync.html'
	});

}]);

// ------------------------------------------------------------------------
//
//	RESOURCES BELOW -->
//
// ------------------------------------------------------------------------

Invoices.factory('Sale', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
	methods['sendToXero'] = { method: 'POST', url: apiUrl('invoices/sales/send-to-xero/:sale'), params: { sale: '@id' } };
	var Sale = $resource(apiUrl('invoices/sales/:sale'), { sale: '@id' }, methods);
	angular.extend(Sale.prototype, _prototype);
	return Sale;
}]);

Invoices.factory('Invoice', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
	methods['sendToXero'] = { method: 'POST', url: apiUrl('invoices/send-to-xero/:invoice'), params: { invoice: '@id' } };
	var Invoice = $resource(apiUrl('invoices/invoices/:invoice'), { invoice: '@id' }, methods);
	angular.extend(Invoice.prototype, _prototype);
	return Invoice;
}]);

Invoices.factory('InvoiceTransaction', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
	methods['onlinePayment'] = { method: 'POST', url: apiUrl('invoices/transactions/online-payment') };

	var InvoiceTransaction = $resource(apiUrl('invoices/transactions/:transactionId'), { transactionId: '@id' }, methods);
	angular.extend(InvoiceTransaction.prototype, _prototype);
	return InvoiceTransaction;
}]);

Invoices.factory('Quote', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
	methods['convertToInvoice'] = { method: 'POST', url: apiUrl('invoices/convert-to-invoice/:quote'), params: { quote: '@id' } };

	var Quote = $resource(apiUrl('invoices/quotes/:quote'), { quote: '@id' }, methods);
	angular.extend(Quote.prototype, _prototype);
	return Quote;
}]);

Invoices.factory('PurchaseOrder', ['apiUrl', '$resource', 'ResourceMethods', 'ResourcePrototype', function (apiUrl, $resource, methods, _prototype) {
	var PurchaseOrder = $resource(apiUrl('invoices/purchase-orders/:purchase_order'), { purchase_order: '@id' }, methods);
	angular.extend(PurchaseOrder.prototype, _prototype);
	return PurchaseOrder;
}]);

Invoices.factory('InvoiceBookingService', ['Tasks', '$window', 'Invoice', '$http', 'ErrorsHandler', '$uibModal', 'apiUrl', function (Tasks, $window, Invoice, $http, ErrorsHandler, $uibModal, apiUrl) {

	var o = {};

	o.generate = function (task) {
		$window.open('/invoices#/invoices/new/' + task.id, '_blank');
	};

	o.generateSingleInvoice = function (project) {
		$window.open('/invoices#/invoices/new-project/' + project.id, '_blank');
	};

	o.show = function (task) {
		$window.open('/invoices#/invoices/view/' + task.invoice_number, '_blank');
	};

	o.print = function (task) {
		// Direct PDF generation - no need for two API calls
		var pdfUrl = '/generate-invoice/' + task.invoice_number;
		$window.open(pdfUrl, '_blank');
	};

	return o;
}]);

Invoices.factory('InvoiceService', ['$uibModal', '$timeout', '$location', 'ErrorsHandler', '$window', 'Messenger', '$http', 'apiUrl', 'InvoiceTransaction', 'Tasks', 'Customer', 'Client', 'Project', function ($uibModal, $timeout, $location, ErrorsHandler, $window, Messenger, $http, apiUrl, InvoiceTransaction, Tasks, Customer, Client, Project) {

	var o = function (Model) {

		// The model used
		this.model = Model;
		this.loading = false;

		// Totals variables
		this.total = 0;
		this.subtotal = 0;
		this.tax = 0;
		//These 3 type indexes are loaded later
		this.repairTypeIndex = 0;
		this.supportTypeIndex = 0;
		this.onsiteTypeIndex = 0;
		this.bookingFeeTypeIndex = 0;
		this.labourTypesLoaded = false;
		this.items = []

		this.data = {
			vat: 20,
			include_vat: true,
			invoice_date: moment().toDate(),
			items: [{ type: 'parts' }],
			method_of_payment: 'cash'
		};

		this.types = [{ name: 'Parts', value: 'parts' }, { name: 'Labour', value: 'labour' }];

		this.select2ClientOptions = {
			allowClear: true,
			minimumInputLength: 1,
			placeholder: 'Select a customer to filter by',
			query: function (options) {
				var loaded = 0;
				var results = [];
				var response = function (response) {
					loaded++;
					results = results.concat(response.data);

					if (loaded >= 2) {
						options.callback({
							more: response.current_page < response.last_page,
							results: results
						});
					}
				};

				Customer.get({ q: options.term, page: options.page }, response, ErrorsHandler);
				Client.get({ q: options.term, page: options.page }, response, ErrorsHandler);
			},
			formatResult: function (obj, container, query) {
				return obj.name;
			},
			formatSelection: function (obj) {
				return obj.name;
			}
		};

		// ------------------------------------------------------------------------
		//
		//	FUNCTIONS BELOW THIS LINE -->
		//
		// ------------------------------------------------------------------------
		this.findLabourTypeIds = function () {
			self = this;
			var arrayLength = self.types.length;
			for (var i = 0; i < arrayLength; i++) {
				if (self.types[i].name == "Labour - Support") {
					this.supportTypeIndex = i;
				}
				else if (self.types[i].name == "Labour - Onsite") {
					this.onsiteTypeIndex = i;
				}
				else if (self.types[i].name == "Labour - Repairs") {
					this.repairTypeIndex = i;

				}
				else if (self.types[i].name == "Labour - Booking Fee") {
					this.bookingFeeTypeIndex = i;
				}
			}
			this.labourTypesLoaded = true;
		};

		this.getProductTypes = function () {
			var self = this;
			// Removed unnecessary API calls to exroItems, exrotype, and kashflow/nominalcodesextended/Turnover
			self.findLabourTypeIds();
		};

		this.getProductTypes();

		this.loadTask = function (task_id) {
			var self = this;

			Tasks.get({ taskId: task_id }, function (response) {
				// Check to see if the invoice was invoiced already
				if (response.invoice_number) {
					$location.path('invoices/view/' + response.invoice_number);
					return false;
				}

				self.client_search = response.client;

				if (response.client_type == 'client') self.data.include_vat = false;

				self.data.items = [];
				self.data.task_id = task_id;

				var description, task_type;

				switch (response.type) {
					case 'repair': description = 'In shop repair with '; task_type = self.types[self.repairTypeIndex].value; break;
					case 'support': description = 'Remote support with '; task_type = self.types[self.supportTypeIndex].value; break;
					case 'onsite': description = 'Onsite support with '; task_type = self.types[self.onsiteTypeIndex].value; break;
					default: description = 'Labour with '; task_type = self.types[0].value; break;
				}

				var user_name = (response.user) ? response.user.name : '';

				// Insert labour if it is not an order
				if (response.type != 'order') {
					self.data.items.push({
						type: task_type,
						name: description + user_name + ' (REF: ' + response.id + ' on ' + moment(response.created_at).format("DD/MM/YYYY") + ')',
						price_sold_exc: response.labour,
						quantity: 1
					});

					self.data.items.push({
						type: task_type,
						name: response.title,
						price_sold_exc: 0,
						quantity: 0
					});
				}

				// Insert parts
				_.each(response.parts, function (part) {

					self.data.items.push({
						type: part.stock.kashflow_category_id ? part.stock.kashflow_category_id : (part.stock.group && part.stock.group.kashflow_category_id ? part.stock.group.kashflow_category_id : ''),
						name: part.stock.name,
						price_sold_exc: part.price * (part.vat / 100 + 1),
						quantity: part.quantity,
						stock_id: part.stock_id
					});
				});

			}, ErrorsHandler);
		};

		this.loadProject = function (project_id) {
			var self = this;

			Project.get({ projectId: project_id }, function (response) {
				self.client_search = response.client;

				if (response.client_type == 'client') self.data.include_vat = false;

				self.data.project_id = project_id;
				self.data.items = [];
				self.data.items.push({
					type: self.types[self.supportTypeIndex].value,
					name: 'Project #' + project_id,
					price_sold_exc: 0,
					quantity: 0
				});

				// Add all other tasks
				_.each(response.tasks, function (task) {
					var itemType;

					switch (task.type) {
						case 'repair': itemType = self.types[self.repairTypeIndex].value; break;
						case 'support': itemType = self.types[self.supportTypeIndex].value; break;
						case 'onsite': itemType = self.types[self.onsiteTypeIndex].value; break;
						default: itemType = self.types[0].value; break;
					}
					if (task.type != 'order') {
						self.data.items.push({
							type: itemType,
							name: task.title,
							price_sold_exc: task.labour,
							quantity: 1
						});
					}

					// Add parts for this task
					_.each(task.parts, function (part) {
						self.data.items.push({
							type: part.stock.kashflow_category_id ? part.stock.kashflow_category_id : (part.stock.group && part.stock.group.kashflow_category_id ? part.stock.group.kashflow_category_id : ''),
							name: part.stock.name,
							price_sold_exc: part.price * (part.vat / 100 + 1),
							quantity: part.quantity
						});
					});
				});

			}, ErrorsHandler);
		};

		/**
		 *	Calculates the total price for a product
		 */
		this.getTotalPrice = function (price) {
			return (this.data.include_vat) ? price : price * (this.data.vat / 100 + 1);
		};

		/**
		 *	Calculates the VAT for a product
		 */
		this.getVATPrice = function (price) {
			if (isNaN(price)) return '';

			return (this.data.include_vat) ? (price / (100 / this.data.vat + 1)).toFixed(2) : (price * this.data.vat / 100).toFixed(2);
		}

		/**
		 *	Updates the product data from the typeahead autocomplete search.
		 */
		this.updateProduct = function (product, ev, data) {
			console.log('updateProduct called with:', { product, ev, data });
			console.log('Current types available:', this.types);

			// Always reset price and stock info when product changes
			var oldPrice = product.price_sold_exc;
			var oldType = product.type;
			product.stock_id = null;
			product.quantity = 1;
			product.price_sold_exc = 0;
			console.log('Reset initial values:', { oldPrice, oldType, newPrice: product.price_sold_exc });

			if (data) {
				console.log('Processing product data:', data);

				// Update product data
				product.name = data.name;
				product.stock_id = data.id;
				product.quantity = 1;
				product.price_sold_exc = parseFloat(data.retail_price).toFixed(2);
				console.log('Updated basic product info:', { name: product.name, price: product.price_sold_exc });

				// Set Type based on product category - Laravel5 compatible mapping
				var typeSet = false;

				// Try new 'type' field first (current system)
				if (data.type) {
					console.log('Setting type from data.type:', data.type);
					product.type = data.type;
					typeSet = true;
				} else if (data.group && data.group.type) {
					console.log('Setting type from data.group.type:', data.group.type);
					product.type = data.group.type;
					typeSet = true;
				}
				// Fall back to kashflow_category_id (Laravel5 legacy)
				else if (data.kashflow_category_id) {
					console.log('Setting type from data.kashflow_category_id:', data.kashflow_category_id);
					product.type = '' + data.kashflow_category_id;
					typeSet = true;
				} else if (data.group && data.group.kashflow_category_id) {
					console.log('Setting type from data.group.kashflow_category_id:', data.group.kashflow_category_id);
					product.type = '' + data.group.kashflow_category_id;
					typeSet = true;
				}
				// Smart detection for labour items
				else if (data.name.toLowerCase().includes('labour') || data.name.toLowerCase().includes('repair') || data.name.toLowerCase().includes('service')) {
					console.log('Product name contains labour/repair/service, looking for Labour type');
					var labourType = this.types.find(t => t.name && (t.name.toLowerCase().includes('labour') || t.name.toLowerCase().includes('repair')));
					if (labourType) {
						console.log('Found Labour type:', labourType);
						product.type = labourType.value;
						typeSet = true;
					}
				}

				if (!typeSet) {
					console.log('No specific type found, defaulting to first type:', this.types[0]);
					product.type = this.types[0].value;
				}

				console.log('Final product type set to:', product.type);

				// Add new line if this is the last item and it has a name
				if (this.data.items && this.data.items[this.data.items.length - 1].name) {
					console.log('Adding new line as current item is last and has name');
					this.newLine(new Event('new_product'));
				}
			} else {
				console.log('No data provided (clearing/resetting product)');
				// Clear product data when input is cleared
				if (!product.name) {
					console.log('Product name is empty, resetting type to default:', this.types[0].value);
					product.type = this.types[0].value;
				}
			}

			// Log the changes
			console.log('Product changes:', {
				type: { old: oldType, new: product.type },
				price: { old: oldPrice, new: product.price_sold_exc },
				name: product.name,
				stockId: product.stock_id
			});

			// Always recalculate totals after any change
			this.calculateTotals();
			console.log('Totals recalculated');
		};

		/**
		 *	Calculate the total price of all the items
		 *	in the list.
		 */
		this.calculateTotals = function () {
			this.total = 0;
			this.subtotal = 0;
			this.tax = 0;
			var self = this;

			_.each(this.data.items, function (el) {
				self.subtotal += (el.price_sold_exc || 0) * (el.quantity || 0);
			});

			if (!this.data.include_vat) {
				this.tax = this.subtotal * this.data.vat / 100;
			} else {
				this.tax = this.subtotal / (100 / this.data.vat + 1);
				this.subtotal -= this.tax;
			}

			this.total = this.subtotal + this.tax;
		};

		/**
		*	Adds a new product to the list
		*/
		this.newLine = function (ev) {
			this.data.items.push({ type: this.types[0].value, name: null });
			$timeout(function () {
				$('textarea.tt-query:last').focus();
			}, 700);
		};

		/**
		 *	Removes an item from the list.
		 */
		this.remove = function (index) {
			this.data.items.splice(index, 1);
		};

		/**
		 * Saves and prints the form.
		 */
		this.save = function (print, email) {
			this.isBusy = false; // nadeem 10.3.17  - save fix - stop multiple presses being allowed through - disable button till reponse - http://stackoverflow.com/questions/26916852/disable-submit-button-in-angularjs

			var self = this;

			// Frontend validation
			var errors = [];

			if (!this.client_search) {
				errors.push("Please select a customer");
			}

			// For sales, payment method is required
			if (this.data.type === 'sale' && !this.data.method_of_payment) {
				errors.push("Please select a method of payment");
			}

			// Check if there are any items
			var hasItems = false;
			_.each(self.data.items, function (item) {
				if (item.name && item.quantity) {
					hasItems = true;
				}
			});
			if (!hasItems) {
				errors.push("Please add at least one item");
			}

			// If there are validation errors, show them and return
			if (errors.length > 0) {
				Messenger().post({
					message: errors.join("\n"),
					type: "error",
					showCloseButton: true
				});
				return false;
			}

			var original_date = this.data.invoice_date;
			var request_data = angular.copy(this.data);

			// Remove empty items
			_.each(self.data.items, function (item, index) {
				if (!item.name) {
					self.data.items.splice(index, 1);
				}
			});

			request_data.client_type = this.client_search.type;
			request_data.client_id = this.client_search.id;
			request_data.total_price = this.total;
			request_data.invoice_date = moment(request_data.invoice_date).format("X");
			if (print) request_data.print = true;
			self.loading = true;
			if (this.data.id) {
				this.model.update(request_data, function (res) {
					angular.extend(self.data, res || {});
					self.data.invoice_date = moment(res.invoice_date).toDate();
					self.loading = false;
					this.isBusy = false; // nadeem 10.3.17 - save fix
					Messenger("The invoice was successfully updated!");
					if (print)
						$window.open(res.print_url, '_blank');

					if (email) {
						self.showEmailModal();
					}

				}, function (a, b) {
					self.loading = false;
					ErrorsHandler(a, b);
				});
			}
			else {
				this.model.save(request_data, function (res) {
					angular.extend(self.data, res || {});
					self.data.invoice_date = moment(res.invoice_date).toDate();
					self.loading = false;
					this.isBusy = false;

					// Show success message for save
					var type = self.data.type === 'sale' ? 'Sale' : 'Invoice';
					Messenger().post({
						message: type + " created successfully!",
						type: "success",
						showCloseButton: true
					});

					if (print)
						$window.open(res.print_url, '_blank');

					if (email) {
						self.showEmailModal(self.data);
					} else {
						// Only redirect if email is not requested
						$location.path(res.type + 's/view/' + res.id);
					}

					// Only send to Xero for sales automatically, not invoices or quotes
					if (res.type === 'sale') {
						// Wait a short moment before starting Xero sync
						setTimeout(function () {
							// Start Xero sync
							self.data.xero_syncing = true;
							Messenger().post({
								message: "Sending to Xero...",
								type: "info",
								showCloseButton: true
							});

							self.sendToXero({ id: res.id }, function (xeroRes) {
								self.data.xero_syncing = false;
								self.data.xeroId = xeroRes.invoice.xeroId;
								Messenger().post({
									message: "Successfully synced with Xero!",
									type: "success",
									showCloseButton: true
								});
							}, function (error) {
								self.data.xero_syncing = false;
								self.data.xero_sync_error = error.data.message || 'Failed to sync with Xero';
								Messenger().post({
									message: "Failed to sync with Xero: " + self.data.xero_sync_error,
									type: "error",
									showCloseButton: true
								});
							});
						}, 1000); // Wait 1 second before starting Xero sync
					}
				}, function (response) {
					self.loading = false;
					self.isBusy = false;

					// Handle validation errors
					if (response.status === 422) {
						Messenger().post({
							message: response.data.error || "Validation failed",
							type: "error",
							showCloseButton: true
						});
					} else {
						// Handle other errors
						Messenger().post({
							message: response.data.error || "An error occurred while saving the invoice",
							type: "error",
							showCloseButton: true
						});
						ErrorsHandler(response);
					}
				});

			}
		};

		/**
		 *	Displays the email invoice modal
		 */
		this.showEmailModal = function () {
			var self = this;

			if (!self.data || !self.data.id) {
				Messenger("Cannot email invoice: Invoice not saved yet");
				return;
			}

			// Get client info from either data.client or client_search
			var clientInfo = self.data.client || self.client_search;

			if (!clientInfo) {
				Messenger("Cannot email invoice: No client information found");
				return;
			}

			var modalInstance = $uibModal.open({
				templateUrl: 'invoices/email.html',
				controller: 'InvoiceEmailModalCtrl',
				size: 'lg',
				resolve: {
					data: function () {
						return self.data;
					},
					client: function () {
						// Use the client data from either source
						return {
							data: {
								email: clientInfo.email || clientInfo.Email || '',
								Email: clientInfo.Email || clientInfo.email || '',
								name: clientInfo.name || clientInfo.Name || 'Customer'
							}
						};
					}
				}
			});

			modalInstance.result.then(function (result) {
				// Success notification is already shown in the modal controller
			}, function () {
				// Modal dismissed
			});
		};

		/**
		 * Displays a modal for entering a new payment.
		 */
		this.showPaymentModal = function (type) {
			if (!type) type = 'cash';

			var self = this;
			var modalInstance = $uibModal.open({
				templateUrl: 'invoices/payment.html',
				controller: 'InvoicePaymentModalCtrl',
				resolve: {
					data: function () {
						return self.data;
					},
					type: function () {
						return type;
					}
				}
			});
		};

		this.showOnlinePaymentModal = function () {
			var self = this;
			var modalInstance = $uibModal.open({
				templateUrl: 'invoices/online-payment.html',
				controller: 'InvoiceOnlinePaymentModalCtrl',
				resolve: {
					data: function () {
						return self.data;
					}
				}
			});
		};

		/**
		 *	Deletes an existing transaction
		 */
		this.deletePayment = function (payment) {
			var self = this;

			InvoiceTransaction.delete({ transactionId: payment.id }, function (response) {
				self.data.transactions = _.reject(self.data.transactions, function (el) { return el.id == payment.id; });
				angular.extend(self.data, response.invoice || {});
			}, ErrorsHandler);

			return false;
		};

		/**
		 * Deletes an invoice
		 */
		this.deleteInvoice = function (type) {
			var params = {};
			params[type + 'Id'] = this.data.id;

			this.model.delete(params, function (response) {
				Messenger("The invoice was successfully deleted");
				$location.path('invoices/browse');
			}, ErrorsHandler);
		};

		/**
* Sends an invoice to Xero
*/
		this.sendToXero = function () {
			try {
				var self = this;

				// Don't allow if already synced or syncing
				if (self.data.xeroId || self.data.xero_syncing) {
					return;
				}

				// Set syncing state
				self.data.xero_syncing = true;

				// Show syncing message
				Messenger().post({
					message: "Sending to Xero...",
					type: "info",
					showCloseButton: true
				});

				// Check if model has sendToXero method, if not use direct HTTP call
				if (typeof self.model.sendToXero === 'function') {
					try {
						// Use the proper API method instead of direct HTTP call
						self.model.sendToXero({ id: self.data.id }, function (response) {
							// Update invoice data with Xero response
							if (response.invoice) {
								angular.extend(self.data, response.invoice);
							} else {
								// Fallback for backward compatibility
								self.data.xeroId = response.xero_invoice_id;
								self.data.xero_synced_at = new Date();
							}

							// Set synced state
							self.data.xero_syncing = false;
							self.data.xero_sync_error = null;

							// Show success message
							Messenger().post({
								message: "Successfully synced with Xero!",
								type: "success",
								showCloseButton: true
							});

						}, function (error) {
							// Set error state
							self.data.xero_syncing = false;
							self.data.xero_sync_error = error.data.message || 'Failed to sync with Xero';

							// Show error message
							Messenger().post({
								message: "Failed to sync with Xero: " + self.data.xero_sync_error,
								type: "error",
								showCloseButton: true
							});
						});
					} catch (e) {
						// Fallback to direct HTTP call
						$http.post('/api/v1/invoices/send-to-xero/' + self.data.id, {}, {
							headers: {
								'Content-Type': 'application/json',
								'Accept': 'application/json'
							}
						}).then(function (response) {
							// Update invoice data with Xero response
							if (response.data.invoice) {
								angular.extend(self.data, response.data.invoice);
							} else {
								// Fallback for backward compatibility
								self.data.xeroId = response.data.xero_invoice_id;
								self.data.xero_synced_at = new Date();
							}

							// Set synced state
							self.data.xero_syncing = false;
							self.data.xero_sync_error = null;

							// Show success message
							Messenger().post({
								message: "Successfully synced with Xero!",
								type: "success",
								showCloseButton: true
							});

						}, function (error) {
							// Set error state
							self.data.xero_syncing = false;
							self.data.xero_sync_error = error.data.message || 'Failed to sync with Xero';

							// Show error message
							Messenger().post({
								message: "Failed to sync with Xero: " + self.data.xero_sync_error,
								type: "error",
								showCloseButton: true
							});
						});
					}
				} else {
					// Fallback: use direct HTTP call
					$http.post('/api/v1/invoices/send-to-xero/' + self.data.id, {}, {
						headers: {
							'Content-Type': 'application/json',
							'Accept': 'application/json'
						}
					}).then(function (response) {
						// Update invoice data with Xero response
						if (response.data.invoice) {
							angular.extend(self.data, response.data.invoice);
						} else {
							// Fallback for backward compatibility
							self.data.xeroId = response.data.xero_invoice_id;
							self.data.xero_synced_at = new Date();
						}

						// Set synced state
						self.data.xero_syncing = false;
						self.data.xero_sync_error = null;

						// Show success message
						Messenger().post({
							message: "Successfully synced with Xero!",
							type: "success",
							showCloseButton: true
						});

					}, function (error) {
						// Set error state
						self.data.xero_syncing = false;
						self.data.xero_sync_error = error.data.message || 'Failed to sync with Xero';

						// Show error message
						Messenger().post({
							message: "Failed to sync with Xero: " + self.data.xero_sync_error,
							type: "error",
							showCloseButton: true
						});
					});
				}
			} catch (e) {
				// Set error state if there's a critical error
				if (this.data) {
					this.data.xero_syncing = false;
					this.data.xero_sync_error = 'Critical error occurred';
				}
			}
		};

		/**
		 *	Opens the PDF invoice in a new window using our native Laravel PDF generation.
		 */
		this.print = function () {
			var pdfUrl = '/generate-invoice/' + (this.data.invoice_number || this.data.id);
			$window.open(pdfUrl, '_blank');
		};
	};

	return {
		create: function (Model) {
			return new o(Model);
		}
	};
}]);

Invoices.factory('SalesBookingService', ['Tasks', '$window', 'Sale', '$http', 'ErrorsHandler', '$uibModal', 'apiUrl', function (Tasks, $window, Sale, $http, ErrorsHandler, $uibModal, apiUrl) {

	var o = {};

	o.generate = function (task) {
		$window.open('/invoices#/sales/new/' + task.id, '_blank');
	};

	o.generateBookingFee = function (task) {
		$window.open('/invoices#/sales/booking/' + task.id, '_blank');
	};

	o.show = function (task) {
		$window.open('/invoices#/sales/view/' + task.invoice_number, '_blank');
	};

	o.showBookingFee = function (task) {
		$window.open('/invoices#/sales/view/' + task.booking_fee_id, '_blank');
	};

	o.print = function (task) {
		// Direct PDF generation - no need for two API calls
		var pdfUrl = '/generate-invoice/' + task.invoice_number;
		$window.open(pdfUrl, '_blank');
	};

	return o;
}]);