import win32com.client
import xml.etree.ElementTree as ET

class QuickBooksSDK:
	def __init__(self):
		""" Initialize QBSDK Request Processor """
		self.qb = win32com.client.Dispatch("QBXMLRP2.RequestProcessor")
		# self.session_id = None
	# def open_connection(self):
	#     """ Open connection to QuickBooks """
	#     self.qb.OpenConnection("", "My Python App")
	#     self.qb.BeginSession("", 2)  # 2 = Use current QuickBooks session

	# def close_connection(self):
	#     """ Close connection to QuickBooks """
	#     self.qb.EndSession()
	#     self.qb.CloseConnection()

	def open_connection(self):
		""" Open connection to QuickBooks """
		self.qb = win32com.client.Dispatch("QBXMLRP2.RequestProcessor")
		self.qb.OpenConnection("", "My QuickBooks App")
		self.session_id = self.qb.BeginSession("", 2)  # 2 = Open in "No UI" mode
		print("Connection to QuickBooks established.", self.session_id)

	def close_connection(self):
		""" Close QuickBooks session and connection """
		if self.session_id:
			
			self.qb.EndSession(self.session_id)
		self.qb.CloseConnection()
		print("Connection to QuickBooks closed.")


	# def send_request(self, qbxml: str) -> str:
	#     """ Send qbXML request and return response """
	#     print("Sending XML Request to QuickBooks:\n", qbxml)  # Debugging print
	#     response = self.qb.ProcessRequest(qbxml)
	#     return response
	def send_request(self, qbxml: str) -> str:
		""" Send QBXML request to QuickBooks and return response """
		try:
			print("\n🔷 SENDING REQUEST TO QUICKBOOKS:")
			print(qbxml)  # Print the exact request
			print(self.session_id)
			response = self.qb.ProcessRequest(self.session_id, qbxml)

			print("\n✅ RESPONSE RECEIVED FROM QUICKBOOKS:")
			print(response if response else "No response received!")
			
			return response
		except Exception as e:
			print("\n❌ ERROR Processing Request:", str(e))
			return ""



	def parse_sales_order_response(self, xml_response: str):
		""" Parse SalesOrderQueryRs XML response into a Python dictionary """
		print(f'{xml_response = }')
		root = ET.fromstring(xml_response)
		sales_orders = []

		for order in root.findall(".//SalesOrderRet"):
			order_data = {
				"TxnID": order.findtext("TxnID", ""),
				"TxnDate": order.findtext("TxnDate", ""),
				"CustomerRef": order.findtext("CustomerRef/FullName", ""),
				"TotalAmount": order.findtext("TotalAmount", ""),
				"LineItems": []
			}

			for line in order.findall(".//SalesOrderLineRet"):
				line_item = {
					"ItemRef": line.findtext("ItemRef/FullName", ""),
					"Quantity": line.findtext("Quantity", ""),
					"Rate": line.findtext("Rate", ""),
					"Amount": line.findtext("Amount", "")
				}
				order_data["LineItems"].append(line_item)

			sales_orders.append(order_data)

		return sales_orders

	def get_sales_orders(self, from_date: str, to_date: str) -> str:
		""" Fetch sales orders from QuickBooks within date range """
		qbxml = f"""
        	<?xml version="1.0" encoding="utf-8"?>
	<?qbxml version="13.0"?>
                <QBXML>

                        <QBXMLMsgsRq onError="stopOnError">
                                <SalesOrderQueryRq requestID="1">
                                        <TxnDateRangeFilter>
                                                <FromTxnDate>2024-01-01</FromTxnDate>
                                                <ToTxnDate>2024-01-05</ToTxnDate>
                                        </TxnDateRangeFilter>
                                        <IncludeLineItems>1</IncludeLineItems>
                                </SalesOrderQueryRq>
                        </QBXMLMsgsRq>
                </QBXML>
		"""
		qbxml = qbxml.strip()
		print("\n🔍 CHECKING QBXML FORMAT BEFORE SENDING:")
		print(qbxml)  # Print request before sending

		response = self.send_request(qbxml)
		return response




# **🔹 Main Execution**
if __name__ == "__main__":
	qb = QuickBooksSDK()

	try:
		qb.open_connection()
		
		# Query sales orders from January 1, 2024 to January 5, 2024
		sales_orders = qb.get_sales_orders("2024-01-01", "2024-01-05")
		
		# Print hasil dalam format dictionary
		print("Sales Orders:", sales_orders)

	finally:
		qb.close_connection()
