"""
Practice: the two boundaries of the acme-crm-mcp demo, in Python.
  - Postgres row-level security, as the demo configures it (db/01_schema.sql)
  - what a client should do with each denial (src/pipeline.ts's challenges)

Fill in the four TODOs, then run the tests:
    pytest test_auth_practice.py        (locally)
or press "Run tests" on the chapter page.
"""
import re


def visible_rows(rows: list[dict], is_owner: bool, forced: bool, tenant: str | None) -> list[dict]:
    """Which rows a SELECT returns under the demo's policy:
        USING (tenant_id = current_setting('app.tenant_id', true))
    - A table owner bypasses row-level security, unless it's FORCEd: then the owner is filtered too.
    - Otherwise only rows whose tenant_id equals `tenant` are visible.
    - An unset tenant (None) is NULL, and NULL equals nothing: no rows, not all rows.

    TODO 1
    """
    return rows


def insert_allowed(row_tenant: str, tenant: str | None) -> bool:
    """WITH CHECK (tenant_id = current_setting('app.tenant_id', true)): may the app insert a row with
    tenant_id = row_tenant while the transaction's tenant is `tenant`? (None: unset, never allowed.)

    TODO 2
    """
    return True


def parse_challenge(www_authenticate: str) -> dict:
    """The key="value" parameters of a Bearer challenge, as a dict.
    'Bearer error="insufficient_scope", scope="crm:write", resource_metadata="http://…"'
      -> {"error": "insufficient_scope", "scope": "crm:write", "resource_metadata": "http://…"}

    TODO 3
    """
    return {}


def next_step(status: int, www_authenticate: str = "") -> str:
    """What a client should do with a response:
      - 401 without an error  -> "sign in"               (no token yet: follow resource_metadata)
      - 401 with invalid_token -> "get a new token"       (expired, wrong audience, forged)
      - 403 insufficient_scope -> "ask for <scope>"       (step-up authorization for that scope)
      - anything else          -> "ok" for 2xx, otherwise "fail"

    TODO 4
    """
    return "ok"
