from sqlalchemy import select

from flyway.auth.passwords import verify_password
from flyway.models import ClientAccount, ClientAccountRole, ClientRole


def test_client_account_crud(admin_api, factory):
    cid = admin_api.post("/api/clients", json={"name": "Acme"}).json()["id"]
    r = admin_api.post("/api/client-accounts", json={"client_id": cid, "username": "acme", "password": "secret-1"})
    assert r.status_code == 200, r.text
    acc = r.json()
    assert (acc["username"], acc["client_name"]) == ("acme", "Acme")
    assert admin_api.post("/api/client-accounts", json={"client_id": cid, "username": "ACME", "password": "x" * 8}
                          ).json()["field"] == "username"
    admin_api.put(f"/api/client-accounts/{acc['id']}", json={"client_id": cid, "username": "acme2", "password": ""})
    with factory() as s:
        a = s.get(ClientAccount, acc["id"])
        assert a.user_name == "acme2" and verify_password(a.password_hash, "secret-1")
        role = s.scalar(select(ClientRole).where(ClientRole.name == "Clients"))
        assert s.get(ClientAccountRole, (a.id, role.id)) is not None
    page = admin_api.get("/api/client-accounts", params={"client_id": cid, "keyword": "acme"}).json()
    assert page["total"] == 1
    assert admin_api.post("/api/client-accounts/delete", json={"ids": [acc["id"]]}).status_code == 204
    assert admin_api.get("/api/client-accounts").json()["total"] == 0


def test_client_product_crud(admin_api):
    cid = admin_api.post("/api/clients", json={"name": "Acme"}).json()["id"]
    pid = admin_api.post("/api/products", json={"title": "Kiwi"}).json()["id"]
    body = {"client_id": cid, "product_id": pid, "opening_stock": 5, "opening_date": "2026-01-01",
            "closing_stock": 3, "closing_date": "2026-02-01"}
    cp = admin_api.post("/api/client-products", json=body).json()
    assert (cp["client_name"], cp["product_title"], cp["closing_stock"]) == ("Acme", "Kiwi", 3)
    assert admin_api.get("/api/client-products", params={"client_id": cid}).json()["total"] == 1
    assert admin_api.post("/api/client-products/delete", json={"ids": [cp["id"]]}).status_code == 204


def test_staff_forbidden(staff_api):
    assert staff_api.get("/api/client-accounts").status_code == 403
    assert staff_api.get("/api/client-products").status_code == 403
