import frappe
import json
from frappe.utils import flt


def calculate_tax_free_amounts(doc, method=None):
    """
    Calculate tax free amounts for Sales Invoice
    Called after calculate_taxes_and_totals
    """
    if doc.doctype != "Sales Invoice":
        return
    
    # Clear existing tax_free_amount values
    for tax in doc.get("taxes", []):
        if hasattr(tax, 'tax_free_amount'):
            tax.tax_free_amount = 0.0
    
    # Calculate tax free amounts
    for item in doc.get("items", []):
        if not item.get("item_code"):
            continue
            
        # Try to get tax template from item row first
        item_tax_template = item.get("item_tax_template")
        item_tax_rate = item.get("item_tax_rate")
        
        # If no tax info in item row, get from Item master
        if not item_tax_template and not item_tax_rate:
            try:
                item_doc = frappe.get_doc("Item", item.item_code)
                item_tax_template = item_doc.get("item_tax_template")
            except Exception:
                continue
        
        # Process item_tax_rate (JSON format)
        if item_tax_rate:
            try:
                if isinstance(item_tax_rate, str):
                    tax_rates = json.loads(item_tax_rate)
                else:
                    tax_rates = item_tax_rate
                    
                for account_head, rate in tax_rates.items():
                    if flt(rate) == 0.0:
                        # Find corresponding tax in sales invoice
                        for doc_tax in doc.get("taxes", []):
                            if doc_tax.account_head == account_head:
                                if hasattr(doc_tax, 'tax_free_amount'):
                                    doc_tax.tax_free_amount = flt(doc_tax.tax_free_amount) + flt(item.net_amount)
                                break
            except Exception:
                pass
        
        # Process item_tax_template
        elif item_tax_template:
            try:
                tax_template = frappe.get_doc("Item Tax Template", item_tax_template)
                
                for template_tax in tax_template.get("taxes", []):
                    if flt(template_tax.tax_rate) == 0.0:
                        # Find corresponding tax in sales invoice
                        for doc_tax in doc.get("taxes", []):
                            if doc_tax.account_head == template_tax.tax_type:
                                if hasattr(doc_tax, 'tax_free_amount'):
                                    doc_tax.tax_free_amount = flt(doc_tax.tax_free_amount) + flt(item.net_amount)
                                break
            except Exception:
                pass


@frappe.whitelist()
def recalculate_tax_free_amounts(doc):
    """
    API method to recalculate tax free amounts
    Called from client side when items change
    """
    if isinstance(doc, str):
        doc = frappe.parse_json(doc)
    
    # Convert to document object if it's a dict
    if isinstance(doc, dict):
        sales_invoice = frappe.get_doc(doc)
    else:
        sales_invoice = doc
    
    # Calculate tax free amounts
    calculate_tax_free_amounts(sales_invoice)
    
    # Return updated taxes
    taxes_data = []
    for tax in sales_invoice.get("taxes", []):
        tax_dict = tax.as_dict() if hasattr(tax, 'as_dict') else dict(tax)
        taxes_data.append(tax_dict)
        
    return taxes_data