import datetime as dt

import pytest

from flyway.services.reports import nz_window
from tests.api_client import NZ_15, make_client_product, make_load_in


def _load_out(api, cid, qty, code="LO-1", date=NZ_15, complete=True):
    src = api.get("/api/load-outs/sources", params={"client_id": cid}).json()[0]["id"]
    lo = api.post("/api/load-outs", json={"client_id": cid, "code": code, "date": date, "to_location": "Port",
                                          "to_rmp": "R9", "lines": [{"source_item_id": src, "quantity": qty, "unit": 2}]}).json()
    if complete:
        api.post(f"/api/load-outs/{lo['id']}/complete")
    return lo


@pytest.fixture
def data(admin_api):
    cid, pid = make_client_product(admin_api, default_unit=2, available_unit="4")
    li = make_load_in(admin_api, cid, pid, 10, unit=2)  # 20
    lo = _load_out(admin_api, cid, 3, date="2026-03-03T10:00:00+13:00")  # -6
    _load_out(admin_api, cid, 1, code="LO-D", date="2026-03-04T10:00:00+13:00", complete=False)  # 草稿
    return cid, pid, li, lo


def test_product_transactions_have_running_balance(admin_api, data):
    cid, pid, li, lo = data
    r = admin_api.get("/api/transactions", params={"client_id": cid, "product_id": pid}).json()
    assert r["show_balance"] and r["title"] == "Acme's Transactions for Kiwi"
    assert [(i["code"], i["quantity"], i["balance"]) for i in r["items"]] == \
        [("LI-1", 20, 20), ("LO-1", -6, 14), ("LO-D", -2, 14)]
    assert r["items"][0]["path"] == f"/load-ins/{li['id']}"
    html = admin_api.get("/api/print/transactions", params={"client_id": cid, "product_id": pid}).text
    assert "<td>14</td>" in html and "Acme&#x27;s Transactions for Kiwi" in html
    html = admin_api.get("/api/print/transactions", params={"client_id": cid, "product_id": pid, "keyword": "LO-D"}).text
    assert "LO-D" in html and "LI-1" not in html


def test_client_documents_exclude_drafts(admin_api, data):
    cid = data[0]
    docs = admin_api.get(f"/api/clients/{cid}/documents").json()
    assert [(d["kind"], d["code"]) for d in docs["items"]] == [("Load-Out", "LO-1"), ("Load-In", "LI-1")]
    assert "LO-1" in admin_api.get(f"/api/print/clients/{cid}/documents").text


def test_inventory_count_matrix(admin_api, data):
    cid = data[0]
    html = admin_api.get(f"/api/print/clients/{cid}/inventory-count",
                         params={"from_date": "2026-03-01", "to_date": "2026-03-31"}).text
    assert "Inventory Count for Acme" in html
    assert "FROM Farm" in html and "TO Port (R9)" in html and "LO-1</a>, <a" in html
    # 默认单位 2：入库 +10 箱，出库 -3 箱，结余 7
    assert ">10<" in html and ">-3<" in html and ">7<" in html and "LO-D" not in html
    before = admin_api.get(f"/api/print/clients/{cid}/inventory-count",
                           params={"from_date": "2026-03-03", "to_date": "2026-03-31"}).text
    assert "FROM Farm" not in before and ">7<" in before  # 期初结余 10 带入


def test_stock_print_and_batch_report(admin_api, data):
    cid, pid = data[0], data[1]
    assert "14 / 2 = 7" in admin_api.get(f"/api/print/clients/{cid}/stock").text
    bid = admin_api.get("/api/batches", params={"product_id": pid}).json()["items"][0]["id"]
    html = admin_api.get("/api/print/batches/report", params={"ids": [bid]}).text
    assert "Product Batch Report" in html and "7 (14/2)" in html and "-3 (-6/2)" in html


def test_email_requires_configuration(admin_api, data):
    cid = data[0]
    assert admin_api.post(f"/api/clients/{cid}/inventory-count/email", json={}).json()["field"] == "email"
    admin_api.put(f"/api/clients/{cid}", json={"name": "Acme", "email": "a@example.com"})
    r = admin_api.post(f"/api/clients/{cid}/inventory-count/email", json={})
    assert r.status_code == 400 and "not configured" in r.json()["message"]


def test_email_sends_html(admin_api, data, monkeypatch):
    from flyway.api import routes_reports
    sent = {}
    monkeypatch.setattr(routes_reports, "send_email", lambda *a: sent.setdefault("args", a))
    cid = data[0]
    admin_api.put(f"/api/clients/{cid}", json={"name": "Acme", "email": "a@example.com"})
    r = admin_api.post(f"/api/clients/{cid}/inventory-count/email", json={"subject": "March"})
    assert r.status_code == 200, r.text
    to, name, subject, html = sent["args"]
    assert (to, name, subject) == ("a@example.com", "Acme", "March") and "<a " not in html


def test_nz_window_defaults_to_last_month():
    assert nz_window(None, None, dt.date(2026, 3, 31)) == (dt.date(2026, 2, 28), dt.date(2026, 3, 31))
    assert nz_window(None, dt.date(2026, 1, 15), dt.date(2026, 3, 1)) == (dt.date(2025, 12, 15), dt.date(2026, 1, 15))
