"""Alcance de ``GET /uploads/url``: qué objetos puede firmar este endpoint y cuáles no.

**Cierra una fuga real.** Antes bastaba con que la key empezara por
``tenants/{tid}/companies/{cid}/`` para firmar una URL de lectura, lo que permitía firmar
**cualquier** objeto de esa company —incluidos los certificados de la FIEL— con solo el permiso de
módulo ``crm.access``. El alcance de este endpoint es «los archivos que el CRM subió», no «todo el
almacén de la company».
"""

import pytest
from fastapi import HTTPException

from api.v1.modules.crm.uploads.routes import get_upload_url, validar_extension
from tests.conftest import COMPANY_ID, TENANT_ID

USUARIO = {"tenant_id": TENANT_ID, "sub": "user-1"}
PREFIJO = f"tenants/{TENANT_ID}/companies/{COMPANY_ID}/"


@pytest.fixture(autouse=True)
def _sin_s3(monkeypatch):
    import api.v1.modules.crm.uploads.routes as uploads

    monkeypatch.setattr(uploads, "presigned_get_url", lambda key, **k: f"https://firmada/{key}")


@pytest.mark.parametrize(
    "sufijo",
    [
        "certificates/fiel_20260101.key",   # llave privada de la FIEL
        "certificates/fiel_20260101.cer",
        "invoices/9/cove/cove.xml",
        "imports/csv/invoice/job-1.csv",
        "branding/logo.png",
        "doda/1/report/doda_report.pdf",
        "signatures/1/photo_x.png",
    ],
)
def test_no_se_puede_firmar_nada_fuera_de_los_documentos_del_crm(sufijo):
    with pytest.raises(HTTPException) as exc:
        get_upload_url(PREFIJO + sufijo, COMPANY_ID, USUARIO)
    assert exc.value.status_code == 403


@pytest.mark.parametrize(
    "sufijo",
    [
        "crm-docs/abc123/contrato.pdf",
        "expedientes/1/documents/abc123_guia.pdf",
    ],
)
def test_los_documentos_del_crm_si_se_pueden_firmar(sufijo):
    resp = get_upload_url(PREFIJO + sufijo, COMPANY_ID, USUARIO)
    assert resp["url"].endswith(sufijo)


def test_no_se_puede_firmar_nada_de_otro_tenant_ni_de_otra_company():
    """El aislamiento previo sigue en pie: es una guarda adicional, no un reemplazo."""
    for key in (
        "tenants/999/companies/1/crm-docs/a/b.pdf",
        f"tenants/{TENANT_ID}/companies/999/crm-docs/a/b.pdf",
    ):
        with pytest.raises(HTTPException) as exc:
            get_upload_url(key, COMPANY_ID, USUARIO)
        assert exc.value.status_code == 403


def test_una_key_que_solo_CONTIENE_el_prefijo_no_pasa():
    """La comprobación es de prefijo, no de subcadena: ``startswith`` y no ``in``."""
    with pytest.raises(HTTPException) as exc:
        get_upload_url(f"otro/{PREFIJO}crm-docs/a/b.pdf", COMPANY_ID, USUARIO)
    assert exc.value.status_code == 403


def test_la_allowlist_de_extensiones_rechaza_lo_ejecutable():
    for nombre in ("virus.exe", "script.sh", "macro.bat", "lib.dll", "sin_extension"):
        with pytest.raises(HTTPException) as exc:
            validar_extension(nombre)
        assert exc.value.status_code == 422
        assert exc.value.detail == "Ese tipo de archivo no está permitido."


def test_la_allowlist_acepta_los_formatos_de_documento():
    for nombre in ("guia.pdf", "factura.XML", "foto.JPG", "hoja.xlsx", "carta.docx", "paquete.zip"):
        validar_extension(nombre)  # no lanza
