import frappe
import json

@frappe.whitelist()
def get_records(start=0, page_length=1000):
    """Fetch all Customer records for the modify records form."""
    records = frappe.get_all(
        "Customer",
        fields=[
            "name",
            "customer_name",
            "customer_number",
            "primary_address",
            "customer_primary_address",
            "mobile_no",
            "email_id",
            "contact_persons",
            "hours_of_operation",
            "legacy_notes",
            "contacted_date",
            "follow_up_date",
            "last_pu_date",
            "legacy_record_number",
            "do_not_call",
            "prospect_status",
            "customer_type",
            "customer_group",
            "territory",
            "disabled",
        ],
        order_by="customer_name asc",
        limit_page_length=int(page_length),
        limit_start=int(start),
    )

    # Enrich with address and contact details
    for r in records:
        # Get address details — primary_address is display string,
        # customer_primary_address is the Link to the Address doc
        addr_name = r.get("customer_primary_address") or r.get("primary_address")
        # Try to find address via Dynamic Link if primary_address is display string
        if addr_name and not frappe.db.exists("Address", addr_name):
            # primary_address was a display string; find via dynamic link
            addr_links = frappe.get_all(
                "Dynamic Link",
                filters={"link_doctype": "Customer", "link_name": r["name"], "parenttype": "Address"},
                fields=["parent"],
                limit=1,
            )
            addr_name = addr_links[0].parent if addr_links else None

        if addr_name and frappe.db.exists("Address", addr_name):
            addr = frappe.db.get_value(
                "Address", addr_name,
                ["address_line1", "city", "state", "pincode", "phone"],
                as_dict=True,
            )
            if addr:
                r["address_line1"] = addr.address_line1 or ""
                r["city"] = addr.city or ""
                r["state"] = addr.state or ""
                r["zip"] = addr.pincode or ""
                r["address_phone"] = addr.phone or ""
            else:
                r["address_line1"] = ""
                r["city"] = ""
                r["state"] = ""
                r["zip"] = ""
                r["address_phone"] = ""
        else:
            r["address_line1"] = ""
            r["city"] = ""
            r["state"] = ""
            r["zip"] = ""
            r["address_phone"] = ""

        # Get contact details from linked contacts
        contacts = frappe.get_all(
            "Dynamic Link",
            filters={"link_doctype": "Customer", "link_name": r["name"], "parenttype": "Contact"},
            fields=["parent"],
        )
        contact_lines = []
        for c in contacts:
            contact = frappe.db.get_value(
                "Contact", c.parent, ["first_name", "last_name", "email_id", "phone", "mobile_no"],
                as_dict=True,
            )
            if contact:
                name = f"{contact.first_name or ''} {contact.last_name or ''}".strip()
                email = contact.email_id or ""
                phone = contact.phone or ""
                mobile = contact.mobile_no or ""
                parts = [name]
                if email:
                    parts.append(f"- {email}")
                if phone:
                    parts.append(f"- {phone}")
                elif mobile:
                    parts.append(f"- {mobile}")
                contact_lines.append(" ".join(parts))
        r["contact_details"] = "\n".join(contact_lines) if contact_lines else r.get("contact_persons", "")

    return records


@frappe.whitelist()
def get_record(name):
    """Fetch a single Customer record by name."""
    r = frappe.get_doc("Customer", name)
    result = {
        "name": r.name,
        "customer_name": r.customer_name or "",
        "customer_number": r.customer_number or "",
        "primary_address": r.primary_address or "",
        "mobile_no": r.mobile_no or "",
        "email_id": r.email_id or "",
        "contact_persons": r.contact_persons or "",
        "hours_of_operation": r.hours_of_operation or "",
        "legacy_notes": r.legacy_notes or "",
        "contacted_date": str(r.contacted_date) if r.contacted_date else "",
        "follow_up_date": str(r.follow_up_date) if r.follow_up_date else "",
        "last_pu_date": str(r.last_pu_date) if r.last_pu_date else "",
        "legacy_record_number": r.legacy_record_number or "",
        "do_not_call": r.do_not_call or 0,
        "prospect_status": r.prospect_status or "",
        "customer_type": r.customer_type or "",
        "customer_group": r.customer_group or "",
        "territory": r.territory or "",
        "disabled": r.disabled or 0,
    }

    # Get address — primary_address on Customer is the display string;
    # customer_primary_address is the actual Link to the Address doc
    addr_name = r.customer_primary_address
    if addr_name:
        addr = frappe.db.get_value(
            "Address", addr_name,
            ["address_line1", "city", "state", "pincode", "phone"],
            as_dict=True,
        )
        if addr:
            result["address_line1"] = addr.address_line1 or ""
            result["city"] = addr.city or ""
            result["state"] = addr.state or ""
            result["zip"] = addr.pincode or ""
            result["address_phone"] = addr.phone or ""
        else:
            result["address_line1"] = ""
            result["city"] = ""
            result["state"] = ""
            result["zip"] = ""
            result["address_phone"] = ""
    else:
        result["address_line1"] = ""
        result["city"] = ""
        result["state"] = ""
        result["zip"] = ""
        result["address_phone"] = ""

    # Get contacts
    contacts = frappe.get_all(
        "Dynamic Link",
        filters={"link_doctype": "Customer", "link_name": r.name, "parenttype": "Contact"},
        fields=["parent"],
    )
    contact_lines = []
    for c in contacts:
        contact = frappe.db.get_value(
            "Contact", c.parent, ["first_name", "last_name", "email_id", "phone", "mobile_no"],
            as_dict=True,
        )
        if contact:
            name = f"{contact.first_name or ''} {contact.last_name or ''}".strip()
            email = contact.email_id or ""
            phone = contact.phone or ""
            mobile = contact.mobile_no or ""
            parts = [name]
            if email:
                parts.append(f"- {email}")
            if phone:
                parts.append(f"- {phone}")
            elif mobile:
                parts.append(f"- {mobile}")
            contact_lines.append(" ".join(parts))
    result["contact_details"] = "\n".join(contact_lines) if contact_lines else r.contact_persons or ""

    return result


@frappe.whitelist()
def save_record(data):
    """Update an existing Customer record."""
    data = frappe.parse_json(data)
    name = data.get("name")
    if not name:
        return {"status": "error", "message": "No record name provided"}

    doc = frappe.get_doc("Customer", name)

    # Update basic fields
    if "customer_name" in data:
        doc.customer_name = data["customer_name"]
    if "email_id" in data:
        doc.email_id = data["email_id"]
    if "mobile_no" in data:
        doc.mobile_no = data["mobile_no"]
    if "contact_persons" in data:
        doc.contact_persons = data["contact_persons"]
    if "hours_of_operation" in data:
        doc.hours_of_operation = data["hours_of_operation"]
    if "legacy_notes" in data:
        doc.legacy_notes = data["legacy_notes"]
    if "contacted_date" in data:
        doc.contacted_date = data["contacted_date"] or None
    if "follow_up_date" in data:
        doc.follow_up_date = data["follow_up_date"] or None
    if "last_pu_date" in data:
        doc.last_pu_date = data["last_pu_date"] or None
    if "prospect_status" in data:
        doc.prospect_status = data["prospect_status"]
    if "do_not_call" in data:
        doc.do_not_call = 1 if data["do_not_call"] else 0

    # Update primary address if it exists
    addr_name = doc.customer_primary_address
    if addr_name:
        addr = frappe.get_doc("Address", addr_name)
        if "address_line1" in data:
            addr.address_line1 = data["address_line1"]
        if "city" in data:
            addr.city = data["city"]
        if "zip" in data:
            addr.pincode = data["zip"]
        if "address_phone" in data:
            addr.phone = data["address_phone"]
        addr.save(ignore_permissions=True)

    doc.save(ignore_permissions=True)
    frappe.db.commit()

    return {"status": "ok", "message": f"Saved {name}"}


@frappe.whitelist()
def delete_record(name):
    """Delete a Customer record."""
    if not name:
        return {"status": "error", "message": "No record name provided"}

    frappe.delete_doc("Customer", name, ignore_permissions=True)
    frappe.db.commit()
    return {"status": "ok", "message": f"Deleted {name}"}


@frappe.whitelist()
def search_records(field=None, value=None):
    """Search Customer records by field."""
    if not value:
        return []

    value_lower = value.lower()
    filters = []

    # Map UI field names to database fields
    field_map = {
        "address": "primary_address",
        "company_name": "customer_name",
        "contact_person": "contact_persons",
        "phone": "mobile_no",
        "email": "email_id",
        "city": None,  # Need join
        "zip": None,  # Need join
        "record_number": "customer_number",
    }

    # Search across multiple fields
    or_filters = []
    like_val = f"%{value}%"

    or_filters.append(["Customer", "customer_name", "like", like_val])
    or_filters.append(["Customer", "customer_number", "like", like_val])
    or_filters.append(["Customer", "primary_address", "like", like_val])
    or_filters.append(["Customer", "email_id", "like", like_val])
    or_filters.append(["Customer", "mobile_no", "like", like_val])
    or_filters.append(["Customer", "contact_persons", "like", like_val])
    or_filters.append(["Customer", "legacy_notes", "like", like_val])
    or_filters.append(["Customer", "hours_of_operation", "like", like_val])
    or_filters.append(["Customer", "legacy_record_number", "like", like_val])

    records = frappe.get_all(
        "Customer",
        or_filters=or_filters,
        fields=[
            "name",
            "customer_name",
            "customer_number",
            "primary_address",
            "mobile_no",
            "email_id",
            "contact_persons",
            "hours_of_operation",
            "legacy_notes",
            "contacted_date",
            "follow_up_date",
            "last_pu_date",
            "legacy_record_number",
            "do_not_call",
            "prospect_status",
            "customer_type",
            "customer_group",
            "territory",
            "disabled",
        ],
        order_by="customer_name asc",
        limit_page_length=100,
    )

    # Also search addresses for city/zip matches
    addr_matches = frappe.get_all(
        "Address",
        or_filters=[
            ["Address", "city", "like", like_val],
            ["Address", "pincode", "like", like_val],
            ["Address", "address_line1", "like", like_val],
        ],
        fields=["name", "address_line1", "city", "pincode"],
        limit_page_length=100,
    )

    # Get customer names linked to matching addresses
    existing_names = {r["name"] for r in records}
    for addr in addr_matches:
        # Find Customer linked to this address
        link = frappe.get_all(
            "Dynamic Link",
            filters={"parent": addr.name, "parenttype": "Address", "link_doctype": "Customer"},
            fields=["link_name"],
        )
        for l in link:
            if l.link_name not in existing_names:
                cust = frappe.get_all(
                    "Customer",
                    filters={"name": l.link_name},
                    fields=[
                        "name", "customer_name", "customer_number", "primary_address",
                        "mobile_no", "email_id", "contact_persons", "hours_of_operation",
                        "legacy_notes", "contacted_date", "follow_up_date", "last_pu_date",
                        "legacy_record_number", "do_not_call", "prospect_status",
                        "customer_type", "customer_group", "territory", "disabled",
                    ],
                )
                if cust:
                    records.append(cust[0])
                    existing_names.add(l.link_name)

    # Enrich with address details (same as get_records)
    for r in records:
        if r.get("primary_address"):
            addr = frappe.db.get_value(
                "Address", r["primary_address"],
                ["address_line1", "city", "state", "pincode", "phone"],
                as_dict=True,
            )
            if addr:
                r["address_line1"] = addr.address_line1 or ""
                r["city"] = addr.city or ""
                r["state"] = addr.state or ""
                r["zip"] = addr.pincode or ""
                r["address_phone"] = addr.phone or ""
            else:
                r["address_line1"] = ""
                r["city"] = ""
                r["state"] = ""
                r["zip"] = ""
                r["address_phone"] = ""
        else:
            r["address_line1"] = ""
            r["city"] = ""
            r["state"] = ""
            r["zip"] = ""
            r["address_phone"] = ""

        contacts = frappe.get_all(
            "Dynamic Link",
            filters={"link_doctype": "Customer", "link_name": r["name"], "parenttype": "Contact"},
            fields=["parent"],
        )
        contact_lines = []
        for c in contacts:
            contact = frappe.db.get_value(
                "Contact", c.parent, ["first_name", "last_name", "email_id", "phone", "mobile_no"],
                as_dict=True,
            )
            if contact:
                cname = f"{contact.first_name or ''} {contact.last_name or ''}".strip()
                email = contact.email_id or ""
                phone = contact.phone or ""
                mobile = contact.mobile_no or ""
                parts = [cname]
                if email:
                    parts.append(f"- {email}")
                if phone:
                    parts.append(f"- {phone}")
                elif mobile:
                    parts.append(f"- {mobile}")
                contact_lines.append(" ".join(parts))
        r["contact_details"] = "\n".join(contact_lines) if contact_lines else r.get("contact_persons", "")

    return records


@frappe.whitelist()
def get_total_count():
    """Return total number of Customer records."""
    return frappe.db.count("Customer", {"disabled": 0})