"""UAT harness for Vendor Masters bulk import. Run INSIDE ams-shiva-api-1."""
import io, sys, httpx, openpyxl

BASE = "http://localhost:8000/api/v1"
TEN = {"X-Tenant-Slug": "demo-enterprise"}
XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
P, F = 0, 0


def ok(name, cond, extra=""):
    global P, F
    if cond:
        P += 1; print(f"  PASS {name} {extra}")
    else:
        F += 1; print(f"  FAIL {name} {extra}")


def login(email, pw):
    r = httpx.post(f"{BASE}/auth/login", json={"email": email, "password": pw}, headers=TEN, timeout=30)
    r.raise_for_status()
    tok = r.json().get("access_token") or r.json().get("data", {}).get("access_token")
    return {**TEN, "Authorization": f"Bearer {tok}"}


def build_xlsx(rows, sheet="Vendors", headers=None):
    """rows: list of dicts keyed by field_name. Uses template column order."""
    from ams.services.vendor_import import TEMPLATE_COLUMNS
    cols = [c[0] for c in TEMPLATE_COLUMNS]
    wb = openpyxl.Workbook(); ws = wb.active; ws.title = sheet
    ws.append(headers or [c[1] for c in TEMPLATE_COLUMNS])
    for row in rows:
        ws.append([row.get(c, "") for c in cols])
    buf = io.BytesIO(); wb.save(buf); return buf.getvalue()


def do_import(hdr, data, skip=True):
    files = {"file": ("vendors.xlsx", data, XLSX)}
    return httpx.post(f"{BASE}/vendors/import", params={"skip_errors": skip}, files=files, headers=hdr, timeout=60)


def main():
    admin = login("admin@demo-enterprise.in", "demo1234")

    # 1. Template download
    print("\n[1] Template download (vendor:read)")
    r = httpx.get(f"{BASE}/vendors/import/template", headers=admin, timeout=30)
    ok("status 200", r.status_code == 200, r.status_code)
    ok("content-type xlsx", XLSX in r.headers.get("content-type", ""), r.headers.get("content-type"))
    ok("zip magic (PK)", r.content[:2] == b"PK")
    tmpl_bytes = r.content
    wb = openpyxl.load_workbook(io.BytesIO(tmpl_bytes))
    ok("has Vendors sheet", "Vendors" in wb.sheetnames)
    ok("has Valid Values sheet", "Valid Values" in wb.sheetnames)
    ok("has Instructions sheet", "Instructions" in wb.sheetnames)
    ws = wb["Vendors"]
    sample = [ws.cell(row=r_, column=1).value for r_ in (2, 3, 4)]
    ok("3 sample rows present", all(sample), sample)
    ok("defined names for dropdowns", any(n.startswith("opts_") for n in wb.defined_names.keys()),
       list(wb.defined_names.keys()))
    ok("date col typed yyyy-mm-dd", ws.cell(row=2, column=15).number_format == "yyyy-mm-dd",
       ws.cell(row=2, column=15).number_format)

    # 2. Happy path — import 3 unique rows
    print("\n[2] Import valid rows")
    rows = [
        {"name": "UAT Alpha Traders", "vendor_type": "supplier", "contact_email": "a@uat.in"},
        {"name": "UAT Beta Services", "vendor_type": "service_provider", "contact_phone": "9000000001"},
        {"name": "UAT Gamma OEM", "vendor_type": "oem"},
    ]
    r = do_import(admin, build_xlsx(rows))
    ok("status 200", r.status_code == 200, r.status_code)
    body = r.json().get("data", r.json())
    ok("imported 3", body.get("imported") == 3, body)
    ok("skipped 0", body.get("skipped") == 0)
    ok("total_rows 3", body.get("total_rows") == 3)

    # 3. Per-row errors — one row missing name, one blank row skipped
    print("\n[3] Per-row validation (skip_errors=true)")
    rows = [
        {"name": "UAT Delta Ltd", "vendor_type": "supplier"},
        {"name": "", "vendor_type": "supplier", "contact_email": "noname@uat.in"},  # missing name
    ]
    r = do_import(admin, build_xlsx(rows))
    body = r.json().get("data", r.json())
    ok("status 200", r.status_code == 200, r.status_code)
    ok("imported 1", body.get("imported") == 1, body)
    ok("skipped 1", body.get("skipped") == 1)
    ok("error names the row", any("name" in (e.get("message", "") + e.get("field", "")).lower()
                                  for e in body.get("errors", [])), body.get("errors"))

    # 4. Invalid GSTIN rejected per row
    print("\n[4] Invalid GSTIN row rejected")
    rows = [{"name": "UAT BadGST", "vendor_type": "supplier", "gstin": "NOTAREALGSTIN"}]
    r = do_import(admin, build_xlsx(rows))
    body = r.json().get("data", r.json())
    ok("imported 0", body.get("imported") == 0, body)
    ok("skipped 1", body.get("skipped") == 1)

    # 5. all-or-nothing (skip_errors=false) aborts on first bad row
    print("\n[5] skip_errors=false is all-or-nothing")
    rows = [
        {"name": "UAT Good1", "vendor_type": "supplier"},
        {"name": "", "vendor_type": "supplier"},  # bad → should abort whole batch
    ]
    r = do_import(admin, build_xlsx(rows), skip=False)
    ok("status 422", r.status_code == 422, r.status_code)
    # Verify the good row was NOT persisted
    lst = httpx.get(f"{BASE}/vendors", params={"page_size": 200}, headers=admin, timeout=30).json()
    items = lst.get("data", lst).get("items", [])
    ok("good row rolled back", not any(v.get("name") == "UAT Good1" for v in items))

    # 6. Empty file rejected
    print("\n[6] Empty file → 422")
    r = do_import(admin, build_xlsx([]))
    ok("status 422", r.status_code == 422, r.status_code)

    # 7. Non-xlsx rejected
    print("\n[7] Non-xlsx → 422")
    files = {"file": ("vendors.csv", b"name,type\nx,y", "text/csv")}
    r = httpx.post(f"{BASE}/vendors/import", files=files, headers=admin, timeout=30)
    ok("status 422", r.status_code == 422, r.status_code)

    # 8. RBAC — unauthenticated blocked
    print("\n[8] RBAC")
    r = httpx.get(f"{BASE}/vendors/import/template", headers=TEN, timeout=30)
    ok("template unauth 401/403", r.status_code in (401, 403), r.status_code)
    r = do_import(dict(TEN), build_xlsx([{"name": "x"}]))
    ok("import unauth 401/403", r.status_code in (401, 403), r.status_code)

    print(f"\n==== {P} passed, {F} failed ====")
    sys.exit(1 if F else 0)


if __name__ == "__main__":
    main()
