import frappe
from .item_service import ItemService

class EstimateService:
    
    @staticmethod
    def exists(estimate_name: str) -> bool:
        """Check if a Quotation document exists by name."""
        print(f"DEBUG: Checking existence of Quotation document with name: {estimate_name}")
        result = frappe.db.exists("Quotation", estimate_name) is not None
        print(f"DEBUG: Quotation document existence: {result}")
        return result
    
    @staticmethod
    def get(estimate_name: str) -> frappe._dict:
        """Retrieve a Quotation document by name. Returns None if not found."""
        print(f"DEBUG: Retrieving Quotation document with name: {estimate_name}")
        if EstimateService.exists(estimate_name):
            estimate_doc = frappe.get_doc("Quotation", estimate_name)
            print("DEBUG: Quotation document found.")
            return estimate_doc
        print("DEBUG: Quotation document not found.")
        return None
    
    
    @staticmethod
    def get_or_throw(estimate_name: str) -> frappe._dict:
        """Retrieve a Quotation document by name or throw an error if not found."""
        estimate_doc = EstimateService.get(estimate_name)
        if estimate_doc:
            return estimate_doc
        raise ValueError(f"Quotation document with name {estimate_name} does not exist.")
    
    @staticmethod
    def update_value(docname: str, fieldname: str, value, save: bool = True) -> None:
        """Update a specific field value of an Quotation document."""
        print(f"DEBUG: Updating Quotation {docname}, setting {fieldname} to {value}")
        if save:
            print("DEBUG: Saving updated Quotation document.")
            estimate_doc = EstimateService.get_or_throw(docname)
            setattr(estimate_doc, fieldname, value)
            estimate_doc.save(ignore_permissions=True)
        else:
            print("DEBUG: Not saving Quotation document as save=False.")
            frappe.db.set_value("Quotation", docname, fieldname, value)
        print(f"DEBUG: Updated Quotation {docname}: set {fieldname} to {value}")
    
    @staticmethod
    def get_value(docname: str, fieldname: str) -> any:
        """Get a specific field value of a Quotation document. Returns None if document does not exist."""
        print(f"DEBUG: Getting value of field {fieldname} from Quotation {docname}")
        if not EstimateService.exists(docname):
            print("DEBUG: Value cannot be retrieved; Quotation document does not exist.")
            return None
        value = frappe.db.get_value("Quotation", docname, fieldname)
        print(f"DEBUG: Retrieved value: {value}")
        return value
    
    @staticmethod
    def get_value_or_throw(docname: str, fieldname: str) -> any:
        """Get a specific field value of a Quotation document or throw an error if document does not exist."""
        value = EstimateService.get_value(docname, fieldname)
        if value is not None:
            return value
        raise ValueError(f"Quotation document with name {docname} does not exist.")
    
    @staticmethod
    def update(estimate_name: str, update_data: dict) -> frappe._dict:
        """Update an existing Quotation document."""
        print(f"DEBUG: Updating Quotation {estimate_name} with data: {update_data}")
        estimate_doc = EstimateService.get_or_throw(estimate_name)
        for key, value in update_data.items():
            setattr(estimate_doc, key, value)
        estimate_doc.save(ignore_permissions=True)
        print(f"DEBUG: Updated Quotation document: {estimate_doc.as_dict()}")
        return estimate_doc
    
    @staticmethod
    def create(estimate_data: dict) -> frappe._dict:
        """Create a new Quotation document."""
        print(f"DEBUG: Creating new Quotation with data: {estimate_data}")
        estimate_doc = frappe.get_doc({
            "doctype": "Quotation",
            **estimate_data
        })
        estimate_doc.insert(ignore_permissions=True)
        print(f"DEBUG: Created Quotation document: {estimate_doc.as_dict()}")
        return estimate_doc
    
    @staticmethod
    def link_estimate_to_customer(estimate_doc: frappe._dict, customer_type: str, customer_name: str) -> None:
        """Link a Quotation document to a client document."""
        print(f"DEBUG: Linking Quotation {estimate_doc.name} to {customer_type} {customer_name}")
        estimate_doc.customer_type = customer_type
        estimate_doc.customer = customer_name
        estimate_doc.save(ignore_permissions=True)
        print(f"DEBUG: Linked Quotation {estimate_doc.name} to {customer_type} {customer_name}")
    
    @staticmethod
    def map_project_template_to_filter(project_template: str = None) -> dict | None:
        """Map a project template to a filter."""
        print(f"DEBUG: Mapping project template {project_template} to quotation category")
        if not project_template:
            print("DEBUG: No project template provided, defaulting to 'General'")
            return None
        mapping = {
            # SNW Install is both Irrigation and SNW-S categories
            "SNW Install": ["in", ["Irrigation", "SNW-S", "Landscaping"]],
        }
        category = mapping.get(project_template, "General")
        print(f"DEBUG: Mapped to quotation category: {category}")
        return { "item_group": category }