"""GE-Enforce HTTPS payload delivery: content-addressed blob store + the
client-facing GET /api/geenforce/payload/<sha256> endpoint.

Lets share-less (Intune/local-account) PCs pull installers the manifest
references over HTTPS instead of SMB. Auth = a geenforce.fetch service token
(same as /manifest). The sha256 IS the integrity guarantee (client re-verifies).
"""

import hashlib

from plugins.geenforce import service
from plugins.geenforce.models import ManifestBlob


def _fetch_key(client, auth_headers):
    resp = client.post('/api/apitokens',
                       json={'name': 'svc', 'scopes': ['geenforce.fetch']},
                       headers=auth_headers)
    assert resp.status_code == 201, resp.get_json()
    return {'X-API-Key': resp.get_json()['data']['secret']}


def _store(app, raw, filename='setup.exe'):
    with app.app_context():
        sha = service.store_blob(raw, filename, 'application/octet-stream')
        service.db.session.commit()
    return sha


def test_store_blob_dedups_and_registers(app, db):
    raw = b'MZ fake installer bytes'
    sha1 = _store(app, raw)
    sha2 = _store(app, raw)  # same content
    assert sha1 == sha2 == hashlib.sha256(raw).hexdigest()
    with app.app_context():
        assert ManifestBlob.query.count() == 1
        blob = service.db.session.get(ManifestBlob, sha1)
        assert blob.sizebytes == len(raw)


def test_download_returns_exact_bytes(client, app, auth_headers):
    raw = b'\x00\x01 big binary installer \xff\xfe'
    sha = _store(app, raw, 'kiosk.exe')
    headers = _fetch_key(client, auth_headers)

    resp = client.get(f'/api/geenforce/payload/{sha}', headers=headers)
    assert resp.status_code == 200
    assert resp.data == raw
    assert resp.headers['ETag'] == f'"{sha}"'
    assert 'kiosk.exe' in resp.headers.get('Content-Disposition', '')


def test_download_requires_fetch_token(client, app, auth_headers):
    sha = _store(app, b'data')
    # no key
    assert client.get(f'/api/geenforce/payload/{sha}').status_code == 401


def test_download_unknown_hash_404(client, auth_headers):
    headers = _fetch_key(client, auth_headers)
    sha = 'a' * 64
    assert client.get(f'/api/geenforce/payload/{sha}', headers=headers).status_code == 404


def test_download_bad_hash_400(client, auth_headers):
    headers = _fetch_key(client, auth_headers)
    assert client.get('/api/geenforce/payload/not-a-hash', headers=headers).status_code == 400


def test_etag_304(client, app, auth_headers):
    sha = _store(app, b'cacheable')
    headers = _fetch_key(client, auth_headers)
    resp = client.get(f'/api/geenforce/payload/{sha}',
                      headers={**headers, 'If-None-Match': f'"{sha}"'})
    assert resp.status_code == 304


def test_serializer_emits_payload_transport_for_http_only(app):
    """http/inline entries emit PayloadSource + PayloadSha256; smb stays bare."""
    from plugins.geenforce.serializer import entry_to_dict
    from plugins.geenforce.models import ManifestEntry

    smb = ManifestEntry(name='a', entrytype='EXE', payloadsource='smb')
    assert 'PayloadSource' not in entry_to_dict(smb)

    http = ManifestEntry(name='b', entrytype='EXE', payloadsource='http',
                         payloadsha256='f' * 64, payloadref='kiosk.exe')
    out = entry_to_dict(http)
    assert out['PayloadSource'] == 'http'
    assert out['PayloadSha256'] == 'f' * 64
    assert out['PayloadRef'] == 'kiosk.exe'
