import json
import frappe
from frappe.utils import today, getdate, add_days
from datetime import timedelta

@frappe.whitelist()
def get_pickups(date=None):
    """Fetch scheduled pickups with optional date filter.
    Returns pickups, calendar (next 30 days), and weekly chart data."""
    filters = []
    if date:
        filters.append(["Scheduled Pickup", "pickup_date", "=", date])

    fields = [
        "name", "pickup_date", "pickup_type", "status", "truck", "stop_order",
        "customer_number", "company_name",
        "contact_name", "contact_phone", "contact_email",
        "address_line", "city", "state", "zip_code",
        "latitude", "longitude",
        "estimated_items", "estimated_weight", "load_contents",
        "num_labels", "data_status", "red_r2",
        "notes", "legacy_notes", "needs_aor", "needs_cod",
    ]

    pickups = frappe.get_list("Scheduled Pickup",
        fields=fields,
        filters=filters if filters else None,
        order_by="pickup_date asc, stop_order asc",
        limit_page_length=500,
    )

    # Build calendar data (next 30 days)
    from_date = getdate(today())
    to_date = add_days(from_date, 30)

    all_pickups = frappe.get_list("Scheduled Pickup",
        fields=["pickup_date"],
        filters=[["Scheduled Pickup", "pickup_date", ">=", str(from_date)],
                 ["Scheduled Pickup", "pickup_date", "<=", str(to_date)]],
        limit_page_length=500,
    )

    pickup_counts = {}
    for p in all_pickups:
        d = p.get("pickup_date", "")
        if d:
            pickup_counts[d] = pickup_counts.get(d, 0) + 1

    calendar = []
    for i in range(30):
        d = add_days(from_date, i)
        ds = str(d)
        calendar.append({"date": ds, "count": pickup_counts.get(ds, 0)})

    # Build weekly chart data (last 12 weeks)
    weekly = []
    for i in range(11, -1, -1):
        week_start = add_days(from_date, -(from_date.weekday() + 7 * i))
        week_end = add_days(week_start, 6)
        count = 0
        for d_str, c in pickup_counts.items():
            try:
                d = getdate(d_str)
                if week_start <= d <= week_end:
                    count += c
            except (ValueError, TypeError):
                pass
        weekly.append({"label": week_start.strftime("%m/%d"), "count": count})

    return {
        "pickups": pickups,
        "calendar": calendar,
        "weekly": weekly,
    }


@frappe.whitelist()
def auto_route(date=None):
    """Auto-assign pickups to trucks based on capacity and proximity."""
    if not date:
        date = today()

    pickups = frappe.get_list("Scheduled Pickup",
        filters={"pickup_date": date},
        fields=["name", "company_name", "estimated_items", "estimated_weight",
                "latitude", "longitude", "pickup_type"],
        limit_page_length=200,
    )

    if not pickups:
        return {"success": True, "assigned": 0}

    trucks = ["Truck 1", "Truck 2", "Truck 3"]
    sorted_p = sorted(pickups, key=lambda p: (float(p.get("latitude") or 0), float(p.get("longitude") or 0)))
    n = len(sorted_p)
    assigned = 0

    for i, p in enumerate(sorted_p):
        if p.get("pickup_type") == "Drop-off":
            truck = ""
        else:
            truck = trucks[i % 3] if n <= 3 else trucks[min(i * 3 // n, 2)]

        doc = frappe.get_doc("Scheduled Pickup", p["name"])
        doc.truck = truck
        doc.status = "Routed" if truck else "Scheduled"
        doc.stop_order = i + 1
        doc.save()
        assigned += 1

    frappe.db.commit()
    return {"success": True, "assigned": assigned}


@frappe.whitelist()
def get_checkins():
    """Fetch completed check-ins — returns Loads with their Pallets."""
    loads = frappe.get_list("Load",
        fields=["name", "load_number", "incoming_date", "customer", "customer_name",
                 "total_devices", "total_weight", "data_status", "red_r2"],
        order_by="incoming_date desc",
        limit_page_length=100,
    )

    for load in loads:
        pallets = frappe.get_list("Pallet",
            filters={"load": load.name},
            fields=["name", "pallet_number", "received_date", "inbound_weight",
                     "total_items", "data_status", "red_r2", "description", "status"],
            limit_page_length=50,
        )
        load["pallets"] = pallets
        load["pallet_count"] = len(pallets)

    return {"checkins": loads}


@frappe.whitelist()
def checkin_load(pickup_name, received_date, actual_pallets, total_weight, load_contents, data_status=None, red_r2=None):
    """Check in a load: create Load + Pallets, mark pickup Complete."""
    # Get the pickup
    pickup = frappe.get_doc("Scheduled Pickup", pickup_name)

    if not actual_pallets or int(actual_pallets) < 1:
        frappe.throw("Actual pallet count must be at least 1")

    actual_pallets = int(actual_pallets)

    # Resolve customer - customer_number on pickup is a Link to Customer
    customer_id = pickup.customer_number
    if not customer_id or not frappe.db.exists("Customer", customer_id):
        frappe.throw("Customer {} not found. Please verify the customer on the pickup.".format(customer_id))

    # Generate Load name: MMDDYYYY-CustomerNumber format
    from datetime import datetime
    try:
        dt = datetime.strptime(received_date, "%Y-%m-%d")
        date_part = dt.strftime("%m%d%Y")
    except (ValueError, TypeError):
        date_part = received_date.replace("-", "")
    
    cust_num = customer_id
    load_name = "{}-{}".format(date_part, cust_num)
    
    # Make unique if name already exists
    base_name = load_name
    counter = 1
    while frappe.db.exists("Load", load_name):
        load_name = "{}-{}".format(base_name, counter)
        counter += 1

    # Create Load
    load = frappe.get_doc({
        "doctype": "Load",
        "name": load_name,
        "load_number": load_name,
        "incoming_date": received_date,
        "customer": customer_id,
        "customer_name": pickup.company_name or "",
        "customer_number": customer_id,
        "data_status": data_status or pickup.data_status or "",
        "red_r2": red_r2 or pickup.red_r2 or "",
        "total_weight": float(total_weight) if total_weight else 0,
        "total_devices": actual_pallets,
        "material_items": [{
            "material_type": "# Of Pallets",
            "total_count": actual_pallets,
            "weight": float(total_weight) if total_weight else 0,
            "initial_data_status": data_status or pickup.data_status or "D0",
        }],
    })
    load.insert()
    frappe.db.commit()

    # Create Pallets — autoname=pallet_number, so set name=pallet_number
    for i in range(actual_pallets):
        pallet_num = "{}-P{}".format(load_name, i + 1)
        pallet = frappe.get_doc({
            "doctype": "Pallet",
            "name": pallet_num,
            "pallet_number": pallet_num,
            "received_date": received_date,
            "load": load.name,
            "company_name": pickup.company_name or "",
            "inbound_weight": str(round(float(total_weight) / actual_pallets, 1)) if total_weight and actual_pallets else "",
            "description": load_contents or "",
            "data_status": data_status or pickup.data_status or "",
            "red_r2": red_r2 or pickup.red_r2 or "",
            "contact_name": pickup.contact_name or "",
            "contact_number": pickup.contact_phone or "",
            "contact_email": pickup.contact_email or "",
            "address_line": (pickup.address_line or "") + ((", " + pickup.city) if pickup.city else "") + ((", " + pickup.state) if pickup.state else ""),
            "needs_aor": pickup.needs_aor or 0,
            "needs_cod": pickup.needs_cod or 0,
            "notes": pickup.notes or "",
            "pickup": pickup.pickup_type or "",
            "status": "Received",
        })
        pallet.insert()

    frappe.db.commit()

    # Update pickup status
    pickup.status = "Complete"
    pickup.save()
    frappe.db.commit()

    return {
        "success": True,
        "load": load.name,
        "pallets_created": actual_pallets,
    }


@frappe.whitelist()
def get_pickup_details(pickup_name):
    """Get full details of a Scheduled Pickup for the check-in form."""
    pickup = frappe.get_doc("Scheduled Pickup", pickup_name)
    return {
        "name": pickup.name,
        "pickup_date": pickup.pickup_date,
        "pickup_type": pickup.pickup_type,
        "customer_number": pickup.customer_number,
        "company_name": pickup.company_name,
        "contact_name": pickup.contact_name,
        "contact_phone": pickup.contact_phone,
        "contact_email": pickup.contact_email,
        "address_line": pickup.address_line,
        "city": pickup.city,
        "state": pickup.state,
        "zip_code": pickup.zip_code,
        "estimated_items": pickup.estimated_items,
        "estimated_weight": pickup.estimated_weight,
        "data_status": pickup.data_status,
        "red_r2": pickup.red_r2,
        "needs_aor": pickup.needs_aor,
        "needs_cod": pickup.needs_cod,
        "notes": pickup.notes,
    }


@frappe.whitelist()
def cor_report():
    """Generate Certificate of Recycling report."""
    pickups = frappe.get_list("Scheduled Pickup",
        filters={"status": "Complete"},
        fields=["name", "pickup_date", "company_name", "customer_number",
                "estimated_items", "estimated_weight", "load_contents",
                "data_status", "red_r2", "needs_aor", "needs_cod"],
        order_by="pickup_date desc",
        limit_page_length=200,
    )

    html = "<!DOCTYPE html><html><head><title>CoR Report</title>"
    html += "<style>body{font-family:Arial,sans-serif;margin:40px;}"
    html += "table{border-collapse:collapse;width:100%;}"
    html += "th,td{border:1px solid #ddd;padding:8px;text-align:left;font-size:13px;}"
    html += "th{background:#2F5496;color:#fff;}h1{color:#2F5496;}</style></head><body>"
    html += "<h1>Certificate of Recycling (CoR) Report</h1>"
    html += "<p>Generated: " + frappe.utils.now() + "</p>"
    html += "<p>Total completed loads: " + str(len(pickups)) + "</p>"

    if pickups:
        html += "<table><tr><th>Date</th><th>Customer</th><th>Items</th><th>Weight</th>"
        html += "<th>Contents</th><th>Data Status</th><th>RED/R2</th><th>AoR</th><th>CoD</th></tr>"
        for p in pickups:
            html += "<tr><td>" + str(p.get("pickup_date", "")) + "</td>"
            html += "<td>" + str(p.get("company_name", "")) + "</td>"
            html += "<td>" + str(p.get("estimated_items", "")) + "</td>"
            html += "<td>" + str(p.get("estimated_weight", "")) + "</td>"
            html += "<td>" + str(p.get("load_contents", "")) + "</td>"
            html += "<td>" + str(p.get("data_status", "")) + "</td>"
            html += "<td>" + str(p.get("red_r2", "")) + "</td>"
            html += "<td>" + ("✓" if p.get("needs_aor") else "") + "</td>"
            html += "<td>" + ("✓" if p.get("needs_cod") else "") + "</td></tr>"
        html += "</table>"
    else:
        html += "<p>No completed loads found.</p>"

    html += "</body></html>"
    frappe.local.response["type"] = "html"
    frappe.local.response["page_content"] = html


@frappe.whitelist()
def print_route_sheet(date=None):
    """Generate printable route sheet."""
    if not date:
        date = today()

    filters = {"pickup_date": date} if date else {}
    pickups = frappe.get_list("Scheduled Pickup",
        filters=filters,
        fields=["name", "pickup_date", "pickup_type", "status", "truck", "stop_order",
                "company_name", "contact_name", "contact_phone", "contact_email",
                "address_line", "city", "state", "zip_code",
                "estimated_items", "estimated_weight", "load_contents",
                "data_status", "red_r2", "needs_aor", "needs_cod", "notes"],
        order_by="truck asc, stop_order asc",
        limit_page_length=200,
    )

    trucks = {}
    unassigned = []
    for p in pickups:
        t = p.get("truck", "")
        if t and t != "Unassigned":
            trucks.setdefault(t, []).append(p)
        else:
            unassigned.append(p)

    html = "<!DOCTYPE html><html><head><title>Route Sheet</title>"
    html += "<style>body{font-family:Arial,sans-serif;margin:30px;}"
    html += "table{border-collapse:collapse;width:100%;margin-bottom:12px;}"
    html += "th,td{border:1px solid #999;padding:6px 10px;text-align:left;font-size:12px;}"
    html += "th{background:#2F5496;color:#fff;}h1{color:#2F5496;font-size:20px;}"
    html += ".truck-header{background:#f0f0f0;padding:8px;font-weight:700;font-size:14px;border:1px solid #ccc;}"
    html += "@media print{body{margin:10px;}}</style></head><body>"
    html += "<h1>Route Sheet — " + str(date or "Today") + "</h1>"

    for truck_name, stops in sorted(trucks.items()):
        html += '<div class="truck-header">🚛 ' + truck_name + " — " + str(len(stops)) + " stops</div>"
        html += "<table><tr><th>#</th><th>Customer</th><th>Address</th><th>Contact</th>"
        html += "<th>Items</th><th>Weight</th><th>Data</th><th>RED/R2</th><th>AoR</th><th>CoD</th><th>Notes</th></tr>"
        for i, s in enumerate(stops, 1):
            addr = str(s.get("address_line", "")) + ", " + str(s.get("city", "")) + ", " + str(s.get("state", "")) + " " + str(s.get("zip_code", ""))
            html += "<tr><td>" + str(i) + "</td><td>" + str(s.get("company_name", "")) + "</td>"
            html += "<td>" + addr + "</td><td>" + str(s.get("contact_name", "")) + "<br>" + str(s.get("contact_phone", "")) + "</td>"
            html += "<td>" + str(s.get("estimated_items", "")) + "</td><td>" + str(s.get("estimated_weight", "")) + "</td>"
            html += "<td>" + str(s.get("data_status", "")) + "</td><td>" + str(s.get("red_r2", "")) + "</td>"
            html += "<td>" + ("✓" if s.get("needs_aor") else "") + "</td>"
            html += "<td>" + ("✓" if s.get("needs_cod") else "") + "</td>"
            html += "<td>" + str(s.get("notes", "")) + "</td></tr>"
        html += "</table>"

    if unassigned:
        html += "<h2>Unassigned</h2><table><tr><th>Customer</th><th>Address</th><th>Notes</th></tr>"
        for s in unassigned:
            html += "<tr><td>" + str(s.get("company_name", "")) + "</td>"
            html += "<td>" + str(s.get("address_line", "")) + "</td>"
            html += "<td>" + str(s.get("notes", "")) + "</td></tr>"
        html += "</table>"

    html += "</body></html>"
    frappe.local.response["type"] = "html"
    frappe.local.response["page_content"] = html


@frappe.whitelist()
def print_green_sheet(date=None):
    """Generate Green Sheet printout for each pallet.
    Shows customer info, service level banner, driver instructions, RED LINE instructions."""
    if not date:
        date = today()

    # Get completed loads for this date
    loads = frappe.get_list("Load",
        filters={"incoming_date": date},
        fields=["name", "load_number", "customer", "customer_name",
                 "incoming_date", "total_weight", "data_status", "red_r2"],
        order_by="name asc",
        limit_page_length=200,
    )

    html = "<!DOCTYPE html><html><head><title>Green Sheets</title>"
    html += "<style>body{font-family:Arial,sans-serif;margin:30px;}"
    html += ".green-sheet{border:2px solid #2E7D32;border-radius:6px;padding:16px;margin:20px 0;page-break-after:always;}"
    html += ".gs-title{color:#2E7D32;font-size:18px;font-weight:700;border-bottom:2px solid #2E7D32;padding-bottom:4px;}"
    html += ".gs-customer{background:#E8F5E9;border:1px solid #66BB6A;border-radius:4px;padding:8px;margin:8px 0;}"
    html += ".gs-service-banner{background:#C62828;color:#fff;font-size:16px;font-weight:700;text-align:center;padding:8px;border-radius:4px;margin:8px 0;}"
    html += ".gs-driver{background:#F5F5F5;border:1px solid #999;border-radius:4px;padding:8px;margin:8px 0;}"
    html += ".gs-redline{background:#FFCDD2;border:2px solid #C62828;border-radius:4px;padding:8px;margin:8px 0;}"
    html += ".gs-r2warning{background:#FFF9C4;border:1px solid #F9A825;border-radius:4px;padding:8px;margin:8px 0;font-size:12px;}"
    html += "table{border-collapse:collapse;width:100%;margin:8px 0;}"
    html += "th,td{border:1px solid #999;padding:6px;text-align:left;font-size:12px;}"
    html += "th{background:#2E7D32;color:#fff;}"
    html += ".gs-footer{margin-top:12px;font-size:11px;color:#666;border-top:1px solid #ccc;padding-top:8px;}"
    html += "@media print{body{margin:10px;}.green-sheet{page-break-after:always;}}</style></head><body>"

    for load in loads:
        pallets = frappe.get_list("Pallet",
            filters={"load": load.name},
            fields=["name", "pallet_number", "inbound_weight", "total_items",
                     "data_status", "red_r2", "description", "needs_aor", "needs_cod", "notes", "status"],
            limit_page_length=50,
        )

        for pallet in pallets:
            html += '<div class="green-sheet">'
            html += '<div class="gs-title">🟢 GREEN SHEET — Data-Bearing Equipment Tracking</div>'
            html += '<div style="text-align:right;font-size:12px;">Pallet # ' + str(pallet.get("pallet_number", "")) + ' | Load # ' + str(load.get("name", "")) + ' | ' + str(load.get("incoming_date", "")) + '</div>'

            # Customer block
            html += '<div class="gs-customer">'
            service_level = ""
            if pallet.get("red_r2"):
                service_level = pallet.get("red_r2", "")
            html += '<strong>(' + str(load.get("customer", "")) + ') — ' + str(service_level) + ' — ' + str(load.get("customer_name", "")) + '</strong>'
            html += '</div>'

            # Service level banner (only for RED/NIST)
            rr = pallet.get("red_r2", "")
            if rr and rr != "Neither":
                html += '<div class="gs-service-banner">SERVICE LEVEL: ' + str(rr).upper() + '</div>'

            # Driver instructions (notes)
            if pallet.get("notes"):
                html += '<div class="gs-driver"><strong>Driver Instructions:</strong><br>' + str(pallet.get("notes", "")) + '</div>'

            # RED LINE instructions (for RED/NIST)
            if rr and rr not in ("", "Neither", "R2"):
                html += '<div class="gs-redline"><strong>⚠ RED LINE INSTRUCTIONS</strong><br>All data-bearing equipment must be tracked. Destruction method per customer specification.</div>'

            # Pallet details table
            html += '<table><tr><th>Pallet Designation</th><th>Data Status</th></tr>'
            html += '<tr><td>' + str(pallet.get("status", "Received")) + '</td><td>' + str(pallet.get("data_status", "")) + '</td></tr>'
            html += '<tr><th>Inbound Weight</th><th>Total Items</th></tr>'
            html += '<tr><td>' + str(pallet.get("inbound_weight", "")) + '</td><td>' + str(pallet.get("total_items", "")) + '</td></tr>'
            html += '<tr><th>AoR/CoR</th><th>Contents</th></tr>'
            aor_cor = ""
            if pallet.get("needs_aor"): aor_cor += "✓ AoR "
            if pallet.get("needs_cod"): aor_cor += "✓ CoD"
            html += '<tr><td>' + (aor_cor or "None") + '</td><td>' + str(pallet.get("description", "")) + '</td></tr>'
            html += '</table>'

            # Material tracking (hand-write on paper)
            html += '<table><tr><th>Material</th><th>%</th><th>Weight</th><th>Sign Off</th><th>Date</th></tr>'
            for _ in range(4):
                html += '<tr><td>&nbsp;</td><td></td><td></td><td></td><td></td></tr>'
            html += '</table>'

            # R2 warning
            html += '<div class="gs-r2warning">⚠ R2 REQUIREMENT: This pallet contains data-bearing equipment. All devices must be tracked through erasure with 5% verification audit.</div>'

            # Signatures
            html += '<table><tr><th>Received By</th><th>Inspected By</th><th>Verified By</th></tr>'
            html += '<tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr></table>'

            # Footer
            html += '<div class="gs-footer">Westech Electronics • Green Sheet — Pallet # ' + str(pallet.get("pallet_number", "")) + ' • Printed ' + str(frappe.utils.nowdate()) + ' • KEEP WITH PALLET AT ALL TIMES</div>'
            html += '</div>'

    html += "</body></html>"
    frappe.local.response["type"] = "html"
    frappe.local.response["page_content"] = html


@frappe.whitelist()
def print_labels(date=None):
    """Generate printable labels."""
    if not date:
        date = today()

    filters = {"pickup_date": date} if date else {}
    pickups = frappe.get_list("Scheduled Pickup",
        filters=filters,
        fields=["name", "company_name", "pickup_date", "num_labels", "data_status", "red_r2"],
        limit_page_length=200,
    )

    html = "<!DOCTYPE html><html><head><title>Labels</title>"
    html += "<style>body{font-family:Arial,sans-serif;margin:10px;}"
    html += ".label{border:2px solid #000;width:3in;height:1.5in;display:inline-block;margin:4px;padding:6px;font-size:11px;page-break-inside:avoid;}"
    html += ".label-co{font-weight:700;font-size:14px;}.label-date{font-size:10px;color:#666;}"
    html += ".label-status{font-size:10px;margin-top:2px;}"
    html += "@media print{body{margin:0;}}</style></head><body>"

    for p in pickups:
        n = p.get("num_labels") or 1
        for _ in range(n):
            html += '<div class="label">'
            html += '<div class="label-co">' + str(p.get("company_name", "")) + '</div>'
            html += '<div class="label-date">' + str(p.get("pickup_date", "")) + '</div>'
            html += '<div class="label-status">' + str(p.get("data_status", "")) + " | " + str(p.get("red_r2", "")) + '</div>'
            html += '</div>'

    html += "</body></html>"
    frappe.local.response["type"] = "html"
    frappe.local.response["page_content"] = html