from unittest.mock import patch

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session

from api.v1.modules.a76.general_catalogs.doda.fingerprint import build_doda_fingerprint
from api.v1.modules.a76.general_catalogs.doda.models import Doda
from api.v1.modules.a76.general_catalogs.doda import routes as doda_routes
from core import storage_s3
from core.config import settings
from core.database import get_core_db
from core.s3_keys import doda_report_pdf_key
from core.security import get_current_user
from tests.conftest import allocate_ephemeral_tenant_company_ids, ensure_tenant_company


@pytest.mark.usefixtures("db_session")
def test_doda_fingerprint_changes_when_field_changes(db_session: Session):
    tid, cid = allocate_ephemeral_tenant_company_ids(db_session)
    ensure_tenant_company(db_session, tenant_id=tid, company_id=cid)
    d = Doda(
        tenant_id=tid,
        company_id=cid,
        integration_number="A1",
        sat_digital_seal="x",
    )
    db_session.add(d)
    db_session.commit()
    fp1 = build_doda_fingerprint(db_session, d.id)
    d.patent = "1234"
    db_session.commit()
    fp2 = build_doda_fingerprint(db_session, d.id)
    assert fp1 != fp2


def _print_client(db_session: Session, test_tenant) -> TestClient:
    app = FastAPI()
    app.include_router(doda_routes.router)

    def _override_get_db():
        yield db_session

    async def _user():
        return {"sub": "test", "tenant_id": test_tenant.tenant_id}

    app.dependency_overrides[get_core_db] = _override_get_db
    app.dependency_overrides[get_current_user] = _user
    return TestClient(app)


@patch.object(
    doda_routes,
    "validate_access_to_resource",
    lambda db, company_id, current_user, required_permissions=None, require_all=True: int(
        current_user["tenant_id"]
    ),
)
def test_print_uses_s3_cache_when_fingerprint_matches(
    db_session: Session, test_tenant, monkeypatch: pytest.MonkeyPatch
):
    monkeypatch.setattr(settings, "S3_FILE_STORAGE", True, raising=False)
    monkeypatch.setattr(settings, "CSV_IMPORT_STORAGE", "redis", raising=False)

    tid, cid = test_tenant.tenant_id, test_tenant.company_id
    ensure_tenant_company(db_session, tenant_id=tid, company_id=cid)
    d = Doda(
        tenant_id=tid,
        company_id=cid,
        integration_number="X",
        sat_digital_seal="s",
    )
    db_session.add(d)
    db_session.commit()

    fp = build_doda_fingerprint(db_session, d.id)
    d.doda_report_source_fingerprint = fp
    d.doda_report_pdf_path = doda_report_pdf_key(tid, cid, d.id)
    db_session.commit()

    called = {"render": 0}

    class _NoRender:
        def build_pdf_for_doda(self, db, doda):
            called["render"] += 1
            raise AssertionError("should not render when S3 cache hits")

    monkeypatch.setattr(doda_routes, "DodaReportPdfService", lambda: _NoRender())
    monkeypatch.setattr(storage_s3, "object_exists", lambda key: True)
    monkeypatch.setattr(storage_s3, "get_object_bytes", lambda key: b"%PDF-1.4 cached")

    client = _print_client(db_session, test_tenant)
    resp = client.get(f"/doda/{d.id}/print?company_id={cid}")
    assert resp.status_code == 200
    assert resp.content == b"%PDF-1.4 cached"
    assert called["render"] == 0


@patch.object(
    doda_routes,
    "validate_access_to_resource",
    lambda db, company_id, current_user, required_permissions=None, require_all=True: int(
        current_user["tenant_id"]
    ),
)
def test_print_422_without_digital_seal(
    db_session: Session, test_tenant, monkeypatch: pytest.MonkeyPatch
):
    monkeypatch.setattr(settings, "S3_FILE_STORAGE", True, raising=False)

    tid, cid = test_tenant.tenant_id, test_tenant.company_id
    ensure_tenant_company(db_session, tenant_id=tid, company_id=cid)
    d = Doda(
        tenant_id=tid, company_id=cid, integration_number="N", sat_digital_seal="  "
    )
    db_session.add(d)
    db_session.commit()

    put_calls = []

    def _put(key, body, content_type="application/octet-stream"):
        put_calls.append((key, body, content_type))

    monkeypatch.setattr(storage_s3, "put_object_bytes", _put)

    client = _print_client(db_session, test_tenant)
    resp = client.get(f"/doda/{d.id}/print?company_id={cid}")
    assert resp.status_code == 422
    assert put_calls == []
