import frappe
import json
from custom_ui.db_utils import build_error_response, build_success_response, process_filters, process_sorting
from custom_ui.services import DbService, ClientService, AddressService, ContactService

@frappe.whitelist()
def get_week_bid_meetings(week_start, week_end, company):
    """Get On-Site Meetings scheduled within a specific week."""
    try:
        meetings = frappe.db.get_all(
            "On-Site Meeting",
            fields=["*"],
            filters=[
                ["status", "!=", "Cancelled"],
                ["start_time", ">=", week_start],
                ["start_time", "<=", week_end],
                ["company", "=", company]
            ],
            order_by="start_time asc"
        )
        for meeting in meetings:
            address_doc = AddressService.get_or_throw(meeting["address"])
            meeting["address"] = address_doc.as_dict()
            contact_doc = ContactService.get_or_throw(meeting["contact"]) if meeting.get("contact") else None
            meeting["contact"] = contact_doc.as_dict() if contact_doc else None
        return build_success_response(meetings)
    except Exception as e:
        frappe.log_error(message=str(e), title="Get Week On-Site Meetings Failed")
        return build_error_response(str(e), 500)
    
@frappe.whitelist()
def get_bid_meeting_note_form(project_template):
    bid_meeting_note_form_name = frappe.db.get_value("Project Template", project_template, "bid_meeting_note_form")
    if not bid_meeting_note_form_name:
        return build_error_response(f"No Bid Meeting Note Form configured for Project Template '{project_template}'", 404)
    try:
        note_form = frappe.get_doc("Bid Meeting Note Form", bid_meeting_note_form_name)
        return build_success_response(note_form.as_dict())
    except Exception as e:
        frappe.log_error(message=str(e), title="Get Bid Meeting Note Form Failed")
        return build_error_response(str(e), 500)

@frappe.whitelist()
def get_bid_meetings(fields=["*"], filters={}, company=None):
    """Get paginated On-Site Meetings with filtering and sorting support."""
    try:
        print("DEBUG: Raw bid meeting options received:", filters)

        processed_filters = process_filters(filters)

        meetings = frappe.db.get_all(
            "On-Site Meeting",
            fields=fields,
            filters=processed_filters,
            order_by="creation desc"
        )
        for meeting in meetings:
            address_doc = frappe.get_doc("Address", meeting["address"])
            meeting["address"] = address_doc.as_dict()

        return build_success_response(
            meetings
        )
    except Exception as e:
        frappe.log_error(message=str(e), title="Get On-Site Meetings Failed")
        return build_error_response(str(e), 500)

@frappe.whitelist()
def get_bid_meeting_note(name):
    """Get a specific Bid Meeting Note by name."""
    try:
        note = frappe.get_doc("Bid Meeting Note", name)
        return build_success_response(note.as_dict())
    except frappe.DoesNotExistError:
        return build_error_response(f"Bid Meeting Note '{name}' does not exist.", 404)
    except Exception as e:
        frappe.log_error(message=str(e), title="Get Bid Meeting Note Failed")
        return build_error_response(str(e), 500)
    
@frappe.whitelist()
def get_unscheduled_bid_meetings(company):
    """Get On-Site Meetings that are unscheduled."""
    try:
        meetings = frappe.db.get_all(
            "On-Site Meeting",
            fields=["*"],
            filters={"status": "Unscheduled", "company": company},
            order_by="creation desc"
        )
        for meeting in meetings:
            address_doc = AddressService.get_or_throw(meeting["address"])
            meeting["address"] = address_doc.as_dict()
            # client_doc = ClientService.get_client_doctype(meeting["party_name"])
            # meeting["client"] = client_doc.as_dict() if client_doc else None
            contact_doc = ContactService.get_or_throw(meeting["contact"]) if meeting.get("contact") else None
            meeting["contact"] = contact_doc.as_dict() if contact_doc else None
        return build_success_response(meetings)
    except Exception as e:
        frappe.log_error(message=str(e), title="Get Unscheduled On-Site Meetings Failed")
        return build_error_response(str(e), 500)

@frappe.whitelist()
def submit_bid_meeting_note_form(bid_meeting, project_template, fields, form_template):
    """Submit Bid Meeting Note Form data for a specific On-Site Meeting."""
    if isinstance(fields, str):
        fields = json.loads(fields)
    try:
        print(f"DEBUG: Submitting Bid Meeting Note Form for meeting='{bid_meeting}' from template='{form_template}' with fields='{fields}'")
        
        meeting = DbService.get_or_throw("On-Site Meeting", bid_meeting)       
        
        # Update fields on the meeting
        meeting_note_field_docs = [{
            "label": field.get("label"),
            "type": field.get("type"),
            "value": json.dumps(field.get("value")) if isinstance(field.get("value"), (list, dict)) else field.get("value"),
            "row": field.get("row"),
            "column": field.get("column"),
            "value_doctype": field.get("doctype_for_select"),
            "available_options": field.get("options"),
            "include_available_options": field.get("include_available_options", False),
            "conditional_on_field": field.get("conditional_on_field"),
            "conditional_on_value": field.get("conditional_on_value"),
            "doctype_label_field": field.get("doctype_label_field")
        } for field in fields]
        new_bid_meeting_note_doc = frappe.get_doc({
            "doctype": "Bid Meeting Note",
            "bid_meeting": bid_meeting,
            "project_template": project_template,
            "form_template": form_template,
            "fields": meeting_note_field_docs
        })
        new_bid_meeting_note_doc.insert(ignore_permissions=True)
        for field_row, field in zip(new_bid_meeting_note_doc.fields, fields):
            print(f"DEBUG: {field_row.label} - {field.get('label')}")
            if not isinstance(field.get("value"), list):
                continue
            for item in field["value"]:
                if not isinstance(item, dict):
                    continue
                new_bid_meeting_note_doc.append("quantities", {
                    "meeting_note_field": field_row.name,
                    "item": item.get("item"),
                    "quantity": item.get("quantity")
                })
        new_bid_meeting_note_doc.save(ignore_permissions=True)
        meeting.bid_notes = new_bid_meeting_note_doc.name
        meeting.status = "Completed"
        meeting.save()
        frappe.db.commit()
        
        return build_success_response(meeting.as_dict())
    except frappe.DoesNotExistError:
        return build_error_response(f"On-Site Meeting '{bid_meeting}' does not exist.", 404)
    except Exception as e:
        frappe.log_error(message=str(e), title="Submit Bid Meeting Note Form Failed")
        return build_error_response(str(e), 500)

@frappe.whitelist()
def get_bid_meeting(name):
    """Get a specific On-Site Meeting by name."""
    try:
        meeting = frappe.get_doc("On-Site Meeting", name)
        meeting_dict = meeting.as_dict()
        
        # Get the full address data
        if meeting_dict.get("address"):
            address_doc = AddressService.get_or_throw(meeting_dict["address"])
            meeting_dict["address"] = address_doc.as_dict()
        if meeting_dict.get("contact"):
            contact_doc = ContactService.get_or_throw(meeting_dict["contact"])
            meeting_dict["contact"] = contact_doc.as_dict()
        if meeting_dict.get("bid_notes"):
            bid_meeting_note_doc = frappe.get_doc("Bid Meeting Note", meeting_dict["bid_notes"])
            meeting_dict["bid_notes"] = bid_meeting_note_doc.as_dict()
        
        return build_success_response(meeting_dict)
    except frappe.DoesNotExistError:
        return build_error_response(f"On-Site Meeting '{name}' does not exist.", 404)
    except Exception as e:
        frappe.log_error(message=str(e), title="Get On-Site Meeting Failed")
        return build_error_response(str(e), 500)


@frappe.whitelist()
def create_bid_meeting(data):
    """Create a new On-Site Meeting with Unscheduled status."""
    if isinstance(data, str):
        data = json.loads(data)
    try:
        print(f"DEBUG: Creating meeting with data='{data}'")
        
        address_doc = DbService.get_or_throw("Address", data.get("address"))

        # Create the meeting with Unscheduled status
        meeting = frappe.get_doc({
            "doctype": "On-Site Meeting",
            "address": address_doc.name,
            "notes": data.get("notes") or "",
            "status": "Unscheduled",
            "company": data.get("company"),
            "contact": data.get("contact"),
            "party_type": address_doc.customer_type,
            "party_name": address_doc.customer_name,
            "project_template": data.get("project_template")
        })
        meeting.insert(ignore_permissions=True)
        # ClientService.append_link(address_doc.customer_name, "onsite_meetings", "onsite_meeting", meeting.name)
        # AddressService.append_link(address_doc.name, "onsite_meetings", "onsite_meeting", meeting.name)
        meeting.flags.ignore_permissions = True
        frappe.db.commit()

        # Clear any auto-generated messages from Frappe
        frappe.local.message_log = []

        print(f"DEBUG: Meeting created successfully: {meeting.name}")

        return build_success_response(meeting.as_dict())
    except Exception as e:
        frappe.log_error(message=str(e), title="Create On-Site Meeting Failed")
        return build_error_response(str(e), 500)

@frappe.whitelist()
def update_bid_meeting(name, data):
    """Update an existing On-Site Meeting."""
    try:
        if isinstance(data, str):
            data = json.loads(data)

        meeting = frappe.get_doc("On-Site Meeting", name)
        
        # Only update fields that are explicitly provided in the data
        for key, value in data.items():
            print(f"DEBUG: Updating field '{key}' to value '{value}'")
            if key == "address" and value is not None:
                # Convert full address to address name
                value = frappe.db.get_value("Address", {"full_address": value}, "name")
                meeting.set(key, value)
            elif key in ["assigned_employee", "completed_by"] and value is not None:
                # Convert employee name to employee ID
                value = frappe.db.get_value("Employee", {"employee_name": value}, "name")
                meeting.set(key, value)
            else:
                # For all other fields, set the value as-is (including None to clear fields)
                meeting.set(key, value)
            print(f"DEBUG: Field '{key}' updated to '{meeting.get(key)}'")
        meeting.save()
        frappe.db.commit()
        
        return build_success_response(meeting.as_dict())
    except frappe.DoesNotExistError:
        return build_error_response(f"On-Site Meeting '{name}' does not exist.", 404)
    except Exception as e:
        return build_error_response(str(e), 500)

