from curses import meta
import os
import subprocess
import sys
import frappe
from .utils import create_module
import holidays
from datetime import date, timedelta
from . import custom_fields

def after_install():
    create_module()
    # add_custom_fields(custom_fields.custom_fields)
    frappe.db.commit()

    # # Proper way to refresh metadata
    # frappe.clear_cache(doctype="Address")
    # frappe.reload_doctype("Address")
    # frappe.clear_cache(doctype="On-Site Meeting")
    # frappe.reload_doctype("On-Site Meeting")
    # update_onsite_meeting_fields()
    # update_address_fields()
    # check_and_create_holiday_list()
    # create_project_templates()
    # create_task_types()
    # # create_tasks()
    # create_bid_meeting_note_form_templates()
    # build_frontend()
    print("Custom UI After Install hook finished successfully!")


def after_uninstall():
    remove_custom_fields(custom_fields.custom_fields)


def after_migrate():
    add_custom_fields(custom_fields.custom_fields)
    update_onsite_meeting_fields()
    frappe.db.commit()

    # Proper way to refresh metadata for all doctypes with custom fields
    doctypes_to_refresh = ["Lead", "Address", "Contact", "On-Site Meeting", "Quotation", "Sales Order", "Project Template"]
    for doctype in doctypes_to_refresh:
        frappe.clear_cache(doctype=doctype)
        frappe.reload_doctype(doctype)

    check_and_create_holiday_list()
    # create_project_templates()
    create_task_types()
    # create_tasks()
    create_companies()
    create_accounts()
    create_bid_meeting_note_form_templates()
    # init_stripe_accounts()

    # update_address_fields()
    # build_frontend()


def build_frontend():
    app_package_path = frappe.get_app_path("custom_ui")
    app_root = os.path.dirname(app_package_path)
    candidates = [
        os.path.join(app_root, "frontend"),
        os.path.join(app_package_path, "frontend")
    ]

    frontend_path = None
    for p in candidates:
        if os.path.exists(p):
            frontend_path = p
            break

    if not frontend_path:
        frappe.log_error(message="No frontend directory found for custom_ui", title="Frontend Build Skipped")
        print(f"⚠️ Frontend directory does not exist. Skipping build. Path was {frontend_path}")
        return

    dist_path  = os.path.join(app_root, "custom_ui", "public", "dist")
    should_build = True

    if should_build:
        print("\n📦 Building frontend for custom_ui...\n")
        try:
            subprocess.check_call(["npm", "install"], cwd=frontend_path)
            subprocess.check_call(["npm", "run", "build"], cwd=frontend_path)
            print("\n✅ Frontend build completed successfully.\n")
        except subprocess.CalledProcessError as e:
            frappe.log_error(message=str(e), title="Frontend Build Failed")
            print(f"\n❌ Frontend build failed: {e}\n")


def remove_custom_fields(custom_fields):
    for doctype, fields_list in custom_fields.items():
        for field in fields_list:
            name = f"{doctype}-{field['fieldname']}"
            if frappe.db.exists("Custom Field", name):
                frappe.delete_doc("Custom Field", name)
                frappe.db.commit()
                print(f"Deleted {name}")
    print("Deleted custom fields from database")


def add_custom_fields(custom_fields):
    from frappe.custom.doctype.custom_field.custom_field import create_custom_fields

    print("\n🔧 Adding custom fields to doctypes...")

    try:
        address_meta = frappe.get_meta("Address")
        address_type_params = address_meta.get_field("address_type")
        if address_type_params and "Service" not in (address_type_params.options or ""):
            print("   Adding 'Service' to Address type options...")
            from frappe.custom.doctype.property_setter.property_setter import make_property_setter
            make_property_setter("Address", "address_type", "options", (address_type_params.options or "") + "\nService", "DocField")
            print("   ✅ Added 'Service' to Address address_type options.")
    except Exception as e:
        print(f"   ⚠️ Failed to update Address address_type: {e}")

    print("🔧 Custom fields to check per doctype:")
    for key, value in custom_fields.items():
        print(f"   • {key}: {len(value)} fields")
    print(f"   Total fields to check: {sum(len(v) for v in custom_fields.values())}\n")

    missing_fields = []
    fields_to_update = []

    for doctype, field_options in custom_fields.items():
        meta = frappe.get_meta(doctype)
        for field_spec in field_options:
            fieldname = field_spec["fieldname"]
            if not meta.has_field(fieldname):
                missing_fields.append(f"{doctype}: {fieldname}")
            else:
                # Field exists, check if specs match
                custom_field_name = f"{doctype}-{fieldname}"
                if frappe.db.exists("Custom Field", custom_field_name):
                    custom_field_doc = frappe.get_doc("Custom Field", custom_field_name)
                    needs_update = False

                    # Compare important properties
                    for key, desired_value in field_spec.items():
                        if key == "fieldname":
                            continue
                        current_value = getattr(custom_field_doc, key, None)
                        if current_value != desired_value:
                            needs_update = True
                            break

                    if needs_update:
                        fields_to_update.append((doctype, fieldname, field_spec))

    if missing_fields:
        print("\n❌ Missing custom fields:")
        for entry in missing_fields:
            print(f"   • {entry}")
        print("\n🔧 Creating missing custom fields...")
        missing_field_specs = build_missing_field_specs(custom_fields, missing_fields)
        create_custom_fields(missing_field_specs)
        print("✅ Missing custom fields created.")

    if fields_to_update:
        print("\n🔧 Updating custom fields with mismatched specs:")
        for doctype, fieldname, field_spec in fields_to_update:
            print(f"   • {doctype}: {fieldname}")
            custom_field_name = f"{doctype}-{fieldname}"
            custom_field_doc = frappe.get_doc("Custom Field", custom_field_name)

            # Update all properties from field_spec
            for key, value in field_spec.items():
                if key != "fieldname":
                    setattr(custom_field_doc, key, value)

            custom_field_doc.save(ignore_permissions=True)

        frappe.db.commit()
        print("✅ Custom fields updated.")

    if not missing_fields and not fields_to_update:
        print("✅ All custom fields verified.")


def update_onsite_meeting_fields():
    """Update On-Site Meeting doctype fields to make start_time and end_time optional."""
    print("\n🔧 Updating On-Site Meeting doctype fields...")

    try:
        # Get the doctype
        doctype = frappe.get_doc("DocType", "On-Site Meeting")

        # Find and update start_time and end_time fields
        updated_fields = []
        for field in doctype.fields:
            if field.fieldname in ['start_time', 'end_time']:
                if field.reqd == 1:
                    field.reqd = 0
                    updated_fields.append(field.fieldname)

        if updated_fields:
            # Save the doctype
            doctype.save(ignore_permissions=True)
            print(f"✅ Updated fields: {', '.join(updated_fields)} (set to not required)")
        else:
            print("✅ Fields already configured correctly")

        print("🔧 On-Site Meeting field update complete.\n")
    except Exception as e:
        print(f"❌ Error updating On-Site Meeting fields: {str(e)}")
        frappe.log_error(message=str(e), title="On-Site Meeting Field Update Failed")
        # Don't raise - this is not critical enough to stop migration

def update_address_fields():
    quotations = frappe.get_all("Quotation", pluck="name")
    addresses = frappe.get_all("Address", pluck="name")
    sales_orders = frappe.get_all("Sales Order", pluck="name")
    tasks = frappe.get_all("Task", pluck="name")
    total_addresses = len(addresses)
    total_quotations = len(quotations)
    total_sales_orders = len(sales_orders)
    total_tasks = len(tasks)
    total_doctypes = total_addresses + total_quotations + total_sales_orders + total_tasks
    combined_doctypes = []
    for sales_order in sales_orders:
        combined_doctypes.append({"doctype": "Sales Order", "name": sales_order})
    for quotation in quotations:
        combined_doctypes.append({"doctype": "Quotation", "name": quotation})
    for address in addresses:
        combined_doctypes.append({"doctype": "Address", "name": address})
    for task in tasks:
        combined_doctypes.append({"doctype": "Task", "name": task})

    print(f"\n📍 Updating field values for {total_addresses} addresses, {total_quotations} quotations, {total_sales_orders} sales orders, and {total_tasks} tasks...")

    # Field update counters
    field_counters = {
        'quotation_addresses_updated': 0,
        'quotation_project_templates_updated': 0,
        'sales_order_addresses_updated': 0,
        'sales_order_project_templates_updated': 0,
        'full_address': 0,
        'custom_onsite_meeting_scheduled': 0,
        'custom_estimate_sent_status': 0,
        'custom_job_status': 0,
        'custom_payment_received_status': 0,
        'address_linked_to_customer': 0,
        'total_field_updates': 0,
        'addresses_updated': 0,
        'quotations_updated': 0,
        'sales_orders_updated': 0,
        'customers_updated': 0,
        'contacts_updated': 0,
        'tasks_updated': 0
    }

    onsite_meta = frappe.get_meta("On-Site Meeting")
    onsite_status_field = "custom_status" if onsite_meta.has_field("custom_status") else "status"

    for index, doc in enumerate(combined_doctypes, 1):
        # Calculate progress
        progress_percentage = int((index / total_doctypes) * 100)
        bar_length = 30
        filled_length = int(bar_length * index // total_doctypes)
        bar = '█' * filled_length + '░' * (bar_length - filled_length)

        # Print a three-line, refreshing progress block without adding new lines each loop
        progress_line = f"📊 Progress: [{bar}] {progress_percentage:3d}% ({index}/{total_doctypes})"
        counters_line = f"   Fields updated: {field_counters['total_field_updates']} | DocTypes updated: {field_counters['addresses_updated'] + field_counters['quotations_updated'] + field_counters['sales_orders_updated'] + field_counters['customers_updated']}"
        detail_line = f"   Processing: {doc['name'][:40]}..."

        if index == 1:
            # First render: write the three lines
            sys.stdout.write(
                f"\r\033[K{progress_line}\n"
                f"\033[K{counters_line}\n"
                f"\033[K{detail_line}"
            )
        else:
            # Move cursor up 3 lines, then rewrite each line in place
            sys.stdout.write("\033[2F")
            sys.stdout.write(f"\r\033[K{progress_line}\n")
            sys.stdout.write(f"\033[K{counters_line}\n")
            sys.stdout.write(f"\033[K{detail_line}")

        if index == total_doctypes:
            sys.stdout.write("\n")

        sys.stdout.flush()

        if doc['doctype'] == "Quotation" or doc['doctype'] == "Sales Order":
            dict_field = doc['doctype'].lower().replace(" ", "_")
            quotation_doc = frappe.get_doc(doc['doctype'], doc['name'])
            custom_installation_address = getattr(quotation_doc, 'custom_installation_address', None)
            custom_job_address = getattr(quotation_doc, 'custom_job_address', None)
            custom_project_template = getattr(quotation_doc, 'custom_project_template', None)

            updates = {}
            if custom_installation_address and not custom_job_address:
                updates['custom_job_address'] = custom_installation_address
                field_counters[f"{dict_field}_addresses_updated"] += 1
                field_counters['total_field_updates'] += 1
            if custom_installation_address and not custom_project_template:
                updates['custom_project_template'] = "SNW Install"
                field_counters[f"{dict_field}_project_templates_updated"] += 1
                field_counters['total_field_updates'] += 1

            if updates:
                frappe.db.set_value(doc['doctype'], doc['name'], updates)
                field_counters[f"{dict_field}s_updated"] += 1

        if doc['doctype'] == "Address":
            address_doc = frappe.get_doc("Address", doc['name'])
            updates = {}

            # Use getattr with default values instead of direct attribute access
            if not getattr(address_doc, 'full_address', None):
                address_parts_1 = [
                    address_doc.address_line1 or "",
                    address_doc.address_line2 or "",
                    address_doc.city or "",
                ]
                address_parts_2 = [
                    address_doc.state or "",
                    address_doc.pincode or "",
                ]

                full_address = ", ".join([
                    " ".join(filter(None, address_parts_1)),
                    " ".join(filter(None, address_parts_2))
                    ]).strip()
                updates['full_address'] = full_address
                field_counters['full_address'] += 1
                field_counters['total_field_updates'] += 1

            onsite_meeting = "Not Started"
            estimate_sent = "Not Started"
            job_status = "Not Started"
            payment_received = "Not Started"


            onsite_meetings = frappe.get_all("On-Site Meeting", fields=[onsite_status_field], filters={"address": address_doc.address_title})
            if onsite_meetings and onsite_meetings[0]:
                status_value = onsite_meetings[0].get(onsite_status_field)
                onsite_meeting = "Completed" if status_value == "Completed" else "In Progress"

            estimates = frappe.get_all("Quotation", fields=["custom_sent", "docstatus", "custom_response"], filters={"custom_job_address": address_doc.address_title})
            if estimates and estimates[0] and estimates[0]["custom_sent"] == 1 and estimates[0]["custom_response"]:
                estimate_sent = "Completed"
            elif estimates and estimates[0] and not (estimates[0]["custom_sent"] == 1 and estimates[0]["custom_response"]):
                estimate_sent = "In Progress"

            jobs = frappe.get_all("Project", fields=["status"], filters={"custom_installation_address": address_doc.address_title, "project_template": "SNW Install"})
            if jobs and jobs[0] and jobs[0]["status"] == "Completed":
                job_status = "Completed"
            elif jobs and jobs[0]:
                job_status = "In Progress"

            sales_invoices = frappe.get_all("Sales Invoice", fields=["outstanding_amount"], filters={"custom_installation_address": address_doc.address_title})
            # payments = frappe.get_all("Payment Entry", filters={"custom_installation_address": address_doc.address_title})
            if sales_invoices and sales_invoices[0] and sales_invoices[0]["outstanding_amount"] == 0:
                payment_received = "Completed"
            elif sales_invoices and sales_invoices[0]:
                payment_received = "In Progress"

            customer_name = getattr(address_doc, 'custom_customer_to_bill', None)
            links = address_doc.get("links", [])
            customer_links = [link for link in links if link.link_doctype == "Customer"]
            needs_link_update = False

            if customer_name and frappe.db.exists("Customer", customer_name):
                customer_doc = frappe.get_doc("Customer", customer_name)

                # Check if address needs link update
                if not customer_links:
                    needs_link_update = True

                if not address_doc.name in [link.address_name for link in customer_doc.get("custom_select_address", [])]:
                    customer_doc.append("custom_select_address", {
                        "address_name": address_doc.name
                    })
                    customer_doc.save(ignore_permissions=True)
                    field_counters['customers_updated'] += 1
                    field_counters['total_field_updates'] += 1

            if getattr(address_doc, 'custom_onsite_meeting_scheduled', None) != onsite_meeting:
                updates['custom_onsite_meeting_scheduled'] = onsite_meeting
                field_counters['custom_onsite_meeting_scheduled'] += 1
                field_counters['total_field_updates'] += 1
            if getattr(address_doc, 'custom_estimate_sent_status', None) != estimate_sent:
                updates['custom_estimate_sent_status'] = estimate_sent
                field_counters['custom_estimate_sent_status'] += 1
                field_counters['total_field_updates'] += 1
            if getattr(address_doc, 'custom_job_status', None) != job_status:
                updates['custom_job_status'] = job_status
                field_counters['custom_job_status'] += 1
                field_counters['total_field_updates'] += 1
            if getattr(address_doc, 'custom_payment_received_status', None) != payment_received:
                updates['custom_payment_received_status'] = payment_received
                field_counters['custom_payment_received_status'] += 1
                field_counters['total_field_updates'] += 1

            if updates:
                frappe.db.set_value("Address", doc['name'], updates)
                field_counters['addresses_updated'] += 1

            # Handle address links after db.set_value to avoid timestamp mismatch
            if needs_link_update:
                # Reload the document to get the latest version
                address_doc = frappe.get_doc("Address", doc['name'])
                address_doc.append("links", {
                    "link_doctype": "Customer",
                    "link_name": customer_name
                })
                address_doc.save(ignore_permissions=True)
                field_counters['address_linked_to_customer'] += 1
                field_counters['total_field_updates'] += 1
        if doc['doctype'] == "Task":
            property = frappe.get_value("Task", doc["name"], "custom_property")
            project = frappe.get_value("Task", doc["name"], "project")
            project_address = frappe.get_value("Project", project, "custom_installation_address")
            alt_project_address = frappe.get_value("Project", project, "custom_address")
            if (project_address or alt_project_address) and not property:
                frappe.db.set_value("Task", doc["name"], "custom_property", project_address if project_address else alt_project_address)
                field_counters['tasks_updated'] += 1
                field_counters['total_field_updates'] += 1



        # Commit every 100 records to avoid long transactions
        if index % 100 == 0:
            frappe.db.commit()

    # Print completion summary
    print(f"\n\n✅ DocType field value update completed!")
    print(f"📊 Summary:")
    print(f"   • Total DocTypes processed: {total_doctypes:,}")
    print(f"   • Addresses updated: {field_counters['addresses_updated']:,}")
    print(f"   • Quotations updated: {field_counters['quotations_updated']:,}")
    print(f"   • Sales Orders updated: {field_counters['sales_orders_updated']:,}")
    print(f"   • Customers updated: {field_counters['customers_updated']:,}")
    print(f"   • Total field updates: {field_counters['total_field_updates']:,}")
    print(f"   • Tasks Updated: {field_counters['tasks_updated']:,}")
    print(f"\n📝 Field-specific updates:")
    print(f"   • Full Address: {field_counters['full_address']:,}")
    print(f"   • On-Site Meeting Status: {field_counters['custom_onsite_meeting_scheduled']:,}")
    print(f"   • Estimate Sent Status: {field_counters['custom_estimate_sent_status']:,}")
    print(f"   • Job Status: {field_counters['custom_job_status']:,}")
    print(f"   • Payment Received Status: {field_counters['custom_payment_received_status']:,}")
    print(f"   • Quotation Addresses Updated: {field_counters['quotation_addresses_updated']:,}")
    print(f"   • Quotation Project Templates Updated: {field_counters['quotation_project_templates_updated']:,}")
    print(f"   • Sales Order Addresses Updated: {field_counters['sales_order_addresses_updated']:,}")
    print(f"   • Sales Order Project Templates Updated: {field_counters['sales_order_project_templates_updated']:,}")
    print("📍 DocType field value updates complete.\n")

def build_missing_field_specs(custom_fields, missing_fields):
    missing_field_specs = {}
    for entry in missing_fields:
        doctype, fieldname = entry.split(": ")
        missing_field_specs.setdefault(doctype, [])
        for field_spec in custom_fields.get(doctype, []):
            if field_spec["fieldname"] == fieldname:
                missing_field_specs[doctype].append(field_spec)
                break

    return missing_field_specs

def check_and_create_holiday_list(year=2026, country="US", weekly_off="Sunday"):
    """Check if Holiday List for the given year exists, if not create it."""
    print(f"\n🔧 Checking for Holiday List for {country} in {year}...")
    holiday_list_name = f"{country} Holidays {year}"

    if frappe.db.exists("Holiday List", holiday_list_name):
        print(f"✅ Holiday List '{holiday_list_name}' already exists.")
        return
    else:
        print(f"❌ Holiday List '{holiday_list_name}' does not exist. Creating...")
        us_holidays = holidays.US(years=[year])
        sundays = get_all_sundays(year)
        hl = frappe.get_doc({
            "doctype": "Holiday List",
            "holiday_list_name": holiday_list_name,
            "country": country,
            "year": year,
            "from_date": f"{year}-01-01",
            "to_date": f"{year}-12-31",
            "weekly_off": weekly_off,
            "holidays": [
                {
                    "holiday_date": holiday_date,
                    "description": holiday_name
                } for holiday_date, holiday_name in us_holidays.items()
            ]
        })
        for sunday in sundays:
            hl.append("holidays", {
                "holiday_date": sunday,
                "description": "Sunday"
            })
        hl.insert()
        # hl.make_holiday_entries()
        frappe.db.commit()
        print(f"✅ Holiday List '{holiday_list_name}' created successfully.")

def get_all_sundays(year):
    sundays = []
    d = date(year, 1, 1)

    while d.weekday() != 6:
        d += timedelta(days=1)

    while d.year == year:
        sundays.append(d)
        d += timedelta(days=7)

    return sundays

def create_task_types():
    task_types = [
        {
            "title": "811/Locate",
            "name": "811/Locate",
            "description": "Utility locate request prior to installation start.",
            "base_date": "Start",
            "offset_days": 7,
            "offset_direction": "Before",
            "calculate_from": "Service Address 2",
            "trigger": "Scheduled",
            "triggering_doctype": "Service Address 2",
        },
        {
            "title": "Permit",
            "name": "Permit",
            "description": "Permits required prior to installation start.",
            "base_date": "Start",
            "offset_days": 7,
            "offset_direction": "Before",
            "calculate_from": "Service Address 2",
            "trigger": "Scheduled",
            "triggering_doctype": "Service Address 2",
        },
        {
            "title": "1/2 Down Payment",
            "name": "1/2 Down Payment",
            "description": "Collect half down payment on project creation.",
            "calculate_from": "Project",
            "trigger": "Created",
            "triggering_doctype": "Project",
            "no_due_date": 1,
        },
        {
            "title": "Machine Staging",
            "name": "Machine Staging",
            "description": "Stage machinery one day before installation start.",
            "base_date": "Start",
            "offset_days": 1,
            "offset_direction": "Before",
            "calculate_from": "Service Address 2",
            "triggering_doctype": "Service Address 2",
            "trigger": "Scheduled",
        },
        {
            "title": "Final Invoice",
            "name": "Final Invoice",
            "description": "Send final invoice within 5 days of job completion.",
            "base_date": "Completion",
            "offset_days": 5,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "triggering_doctype": "Service Address 2",
            "trigger": "Completed",
        },
        {
            "title": "Backflow Test",
            "name": "Backflow Test",
            "description": "Backflow test after job completion if quoted.",
            "base_date": "Completion",
            "offset_days": 0,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "triggering_doctype": "Service Address 2",
            "trigger": "Completed",
        },
        {
            "title": "Schedule Permit Inspection",
            "name": "Schedule Permit Inspection",
            "description": "Schedule permit inspection 5 days after completion.",
            "base_date": "Completion",
            "offset_days": 5,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"
        },
        {
            "title": "15 Day Warranty Follow-Up",
            "name": "15 Day Warranty Follow-Up",
            "description": "15-day warranty follow-up after completion.",
            "base_date": "Completion",
            "offset_days": 15,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"
        },
        {
            "title": "30 Day Warranty Check",
            "name": "30 Day Warranty Check",
            "description": "30-day warranty check after completion.",
            "base_date": "Completion",
            "offset_days": 30,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "triggering_doctype": "Service Address 2",
            "trigger": "Completed",
        },
        {
            "title": "30 Day Payment Reminder",
            "name": "30 Day Payment Reminder",
            "description": "Payment reminder sent 30 days after completion.",
            "base_date": "Completion",
            "offset_days": 30,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"
        },
        {
            "title": "60 Day Late Payment Notice",
            "name": "60 Day Late Payment Notice",
            "description": "Late payment notification at 60 days post completion.",
            "base_date": "Completion",
            "offset_days": 60,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"

        },
        {
            "title": "80 Day Lien Notice",
            "name": "80 Day Lien Notice",
            "description": "Lien notice if payment is still late after 80 days.",
            "base_date": "Completion",
            "offset_days": 80,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"
        },
        {
            "title": "365 Day Warranty Call / Walk",
            "name": "365 Day Warranty Call / Walk",
            "description": "One-year warranty call or walk-through.",
            "base_date": "Completion",
            "offset_days": 365,
            "offset_direction": "After",
            "calculate_from": "Service Address 2",
            "trigger": "Completed",
            "triggering_doctype": "Service Address 2"
        },
    ]

    for task_type in task_types:
        # Idempotency check
        if frappe.db.exists("Task Type", task_type["name"]):
            continue

        doc = frappe.get_doc({
            "doctype": "Task Type",
            "title": task_type["title"],
            "name": task_type["name"],
            "description": task_type["description"],
            "base_date": task_type.get("base_date"),
            "offset_days": task_type.get("offset_days", 0),
            "offset_direction": task_type.get("offset_direction"),
            "calculate_from": task_type.get("calculate_from", "Service Address 2"),
            "trigger": task_type["trigger"],
            "no_due_date": task_type.get("no_due_date", 0),
            "triggering_doctype": task_type.get("triggering_doctype", "Service Address 2")
        })

        doc.insert(ignore_permissions=True)


    frappe.db.commit()

def create_tasks():
    print("\n🔧 Creating default Tasks if they do not exist...")
    default_tasks = [
        {
            "task_name": "Initial Consultation",
            "description": "Conduct an initial consultation with the client to discuss project requirements.",
            "status": "Open",
            "priority": "High",
            "type": "Consultation"
        },
        {
            "task_name": "Site Survey",
            "description": "Perform a site survey to assess conditions and gather necessary data.",
            "status": "Open",
            "priority": "Medium"
        },
        {
            "task_name": "Design Proposal",
            "description": "Prepare and present a design proposal based on client needs and site survey findings.",
            "status": "Open",
            "priority": "High"
        }
    ]

    for task in default_tasks:
        if frappe.db.exists("Task", task["task_name"]):
            continue
        doc = frappe.get_doc({
            "doctype": "Task",
            "is_template": 1,
            "task_name": task["task_name"],
            "description": task["description"],
            "status": task["status"],
            "priority": task["priority"],
            "type": task["type"]
        })
        doc.insert(ignore_permissions=True)

def create_project_templates():
    """Create default Project Templates if they do not exist."""
    print("\n🔧 Checking for default Project Templates...")
    templates = {
        "Sprinklers Northwest": [
            {
                "name": "SNW Install",
                "project_type": "Service",
                "calendar_color": "#FF5733",  # Example color
                "item_groups": "SNW-I, SNW-S, SNW-LS"
            }
        ]
    }

    for company, template_list in templates.items():
        for template in template_list:
            if frappe.db.exists("Project Template", template["name"]):
                continue

            doc = frappe.get_doc(template)
            doc.insert(ignore_permissions=True)


def create_bid_meeting_note_form_templates():
    """Create Bid Meeting Note Forms if they do not exist."""
    print("\n🔧 Checking for Bid Meeting Note Forms...")

    forms = {
        "Sprinklers Northwest": [
            {
                "title": "SNW Install Bid Meeting Notes",
                "description": "Notes form for SNW Install bid meetings.",
                "project_template": "SNW Install",
                "fields": [
                    {
                        "label": "Locate Needed",
                        "type": "Check",
                        "required": 1,
                        "help_text": "Indicate if a locate is needed for this project.",
                        "row": 1,
                        "column": 1,
                    },
                    {
                        "label": "Permit Needed",
                        "type": "Check",
                        "required": 1,
                        "help_text": "Indicate if a permit is needed for this project.",
                        "row": 1,
                        "column": 2,
                    },
                    {
                        "label": "Back Flow Test Required",
                        "type": "Check",
                        "required": 1,
                        "help_text": "Indicate if a backflow test is required after installation.",
                        "row": 1,
                        "column": 3,
                    },
                    {
                        "label": "Machine Access",
                        "type": "Check",
                        "required": 1,
                        "row": 2,
                        "column": 1,
                    },
                    {
                        "label": "Machines",
                        "type": "Multi-Select",
                        "options": "MT, Skip Steer, Excavator-E-50, Link Belt, Tre?, Forks, Auger, Backhoe, Loader, Duzer",
                        "include_options": 1,
                        "conditional_on_field": "Machine Access",
                        "row": 2,
                        "column": 2,
                    },
                    {
                        "label": "Materials Required",
                        "type": "Check",
                        "required": 1,
                        "row": 3,
                        "column": 0,
                    },
                    {
                        "label": "Materials",
                        "type": "Multi-Select w/ Quantity",
                        "doctype_for_select": "Item",
                        "doctype_label_field": "itemName",
                        "conditional_on_field": "Materials Required",
                        "row": 4,
                        "column": 0,
                    },
                ],
            }
        ]
    }

    for company, form_list in forms.items():
        for form in form_list:
            # Idempotency check
            bid_meeting_filter = {"title": form["title"], "company": company}
            # Get the id of the Bid Meeting Note Form if it exists
            bid_meeting_notes_id = frappe.db.exists("Bid Meeting Note Form", bid_meeting_filter)
            if bid_meeting_notes_id:
                # Check if the project template is connected to this Bid Meetings Note Form
                template_connection = frappe.db.get_value("Project Template",
                                                          form["project_template"], "bid_meeting_note_form")
                if not template_connection:
                    # Connect the Bid Meeting Note Form and Project Template
                    frappe.db.set_value("Project Template", form["project_template"],
                                        "bid_meeting_note_form", bid_meeting_notes_id)
                continue

            doc = frappe.new_doc("Bid Meeting Note Form")
            doc.company = company
            doc.title = form["title"]
            doc.description = form.get("description")
            doc.project_template = form.get("project_template")

            for idx, field in enumerate(form.get("fields", []), start=1):
                doc.append(
                    "fields",
                    {
                        "label": field["label"],
                        "type": field["type"],
                        "options": field.get("options"),
                        "required": field.get("required", 0),
                        "default_value": field.get("default_value"),
                        "read_only": field.get("read_only", 0),
                        "order": field.get("order", 0),
                        "help_text": field.get("help_text"),
                        "doctype_for_select": field.get("doctype_for_select"),
                        "include_options": field.get("include_options", 0),
                        "conditional_on_field": field.get("conditional_on_field"),
                        "conditional_on_value": field.get("conditional_on_value"),
                        "doctype_label_field": field.get("doctype_label_field"),
                        "row": field.get("row"),
                        "column": field.get("column"),
                        "idx": idx,
                    },
                )

            doc.insert(ignore_permissions=True)
            frappe.db.set_value("Project Template", form["project_template"],
                                "bid_meeting_note_form", doc.name)


def create_companies():
    """Create necessary companies if they do not exist."""
    print("\n🔧 Checking for necessary companies...")

    companies = [
        {
            'company_name': 'Veritas Stone',
            'abbr': 'VS',
            'default_currency': 'USD',
            'country': 'United States',
            'is_group': 0,
            'parent_company': None,
            'create_chart_of_accounts_based_on': 'Standard Template',
            'chart_of_accounts': 'Standard',
            'enable_perpetual_inventory': 1
        },
        {
            'company_name': 'Daniels Landscape Supplies',
            'abbr': 'DL',
            'default_currency': 'USD',
            'country': 'United States',
            'is_group': 0,
            'parent_company': None,
            'create_chart_of_accounts_based_on': 'Standard Template',
            'chart_of_accounts': 'Standard',
            'enable_perpetual_inventory': 1
        },
        {
            'company_name': 'Lowe Fencing',
            'abbr': 'LF',
            'default_currency': 'USD',
            'country': 'United States',
            'is_group': 0,
            'parent_company': None,
            'create_chart_of_accounts_based_on': 'Standard Template',
            'chart_of_accounts': 'Standard',
            'enable_perpetual_inventory': 1
        },
        {
            'company_name': 'Nuco Yard Care',
            'abbr': 'NYC',
            'default_currency': 'USD',
            'country': 'United States',
            'is_group': 0,
            'parent_company': None,
            'create_chart_of_accounts_based_on': 'Standard Template',
            'chart_of_accounts': 'Standard',
            'enable_perpetual_inventory': 1
        },
        {
            'company_name': 'Sprinklers Northwest',
            'abbr': 'S',
            'default_currency': 'USD',
            'country': 'United States',
            'is_group': 0,
            'parent_company': None,
            'create_chart_of_accounts_based_on': 'Standard Template',
            'chart_of_accounts': 'Standard',
            'enable_perpetual_inventory': 1
        }
    ]
    for company in companies:
        if frappe.db.exists("Company", company["company_name"]):
            continue
        data = {
            "doctype": "Company"
            }
        data.update(company)
        doc = frappe.get_doc(data)
        doc.insert(ignore_permissions=True)
        set_default_accounts(doc)

def set_default_accounts(company_doc):
    """Set default accounts for a company after creation."""
    abbr = company_doc.abbr
    company_doc.default_cash_account = f"Cash - {abbr}"
    company_doc.default_receivable_account = f"Debtors - {abbr}"
    company_doc.default_payable_account = f"Creditors - {abbr}"
    company_doc.default_income_account = f"Sales - {abbr}"
    company_doc.default_expense_account = f"Cost of Goods Sold - {abbr}"
    company_doc.cost_center = f"Main - {abbr}"
    company_doc.save(ignore_permissions=True)




def create_accounts():
    """Create necessary accounts if they do not exist."""
    print("\n🔧 Checking for necessary accounts...")

    accounts = [
        {
            "Sprinklers Northwest": [
                {
                    "account_name": "Stripe Clearing - Sprinklers Northwest",
                    "account_type": "Bank",
                    "parent_account": "Bank Accounts - S",
                    "company": "Sprinklers Northwest"
                }
            ]
        }
    ]

    for company_accounts in accounts:
        for company, account_list in company_accounts.items():
            for account in account_list:
                # Idempotency check
                if frappe.db.exists("Account", {"account_name": account["account_name"], "company": account["company"]}):
                    continue
            doc = frappe.get_doc({
                "doctype": "Account",
                "account_name": account["account_name"],
                "account_type": account["account_type"],
                "company": account["company"],
                "parent_account": account["parent_account"],
                "is_group": 0
            })
            doc.insert(ignore_permissions=True, ignore_if_duplicate=True)

    frappe.db.commit()

def init_stripe_accounts():
    """Initializes the bare configurations for each Stripe Settings doctypes."""
    print("\n🔧 Initializing Stripe Settings for companies...")

    companies = ["Sprinklers Northwest"]

    for company in companies:
        if not frappe.db.exists("Stripe Settings", {"company": company}):
            doc = frappe.get_doc({
                "doctype": "Stripe Settings",
                "company": company,
                "api_key": "",
                "publishable_key": "",
                "webhook_secret": "",
                "account": f"Stripe Clearing - {company}"
            })
            doc.insert(ignore_permissions=True)

    frappe.db.commit()
