import os

import pytest

from bsv.storage.downloader import Downloader
from bsv.storage.exceptions import DownloadError, NetworkError, UploadError
from bsv.storage.uploader import Uploader

# Set fallback URL for offline testing
os.environ.setdefault("E2E_STORAGE_URL", "https://fake-storage.local")
STORAGE_URL = os.environ.get("E2E_STORAGE_URL", "https://nanostore.babbage.systems")
NETWORK = os.environ.get("E2E_NETWORK", "mainnet")


class DummyWallet:
    def get_public_key(self, ctx, args, originator):
        return {"public_key": "dummy_pubkey"}

    def create_action(self, ctx, args, originator):
        return {"tx": b"dummy_tx_bytes"}


@pytest.mark.e2e
@pytest.mark.skipif(
    not os.environ.get("E2E_STORAGE_URL"), reason="E2E_STORAGE_URL not set; set to real storage service to run E2E test"
)
def test_storage_upload_download_e2e():
    uploader = Uploader(storage_url=STORAGE_URL, wallet=DummyWallet())
    downloader = Downloader(network=NETWORK)
    test_data = b"hello e2e storage test"
    mime_type = "text/plain"
    retention = 60  # minutes
    # アップロード
    result = uploader.publish_file(test_data, mime_type, retention)
    assert result.published
    uhrp_url = result.uhrp_url
    assert uhrp_url.startswith("uhrp://")
    # ダウンロード
    downloaded = downloader.download(uhrp_url)
    assert downloaded.data == test_data
    assert downloaded.mime_type == mime_type or downloaded.mime_type is not None


@pytest.mark.e2e
@pytest.mark.skipif(
    not os.environ.get("E2E_STORAGE_URL"), reason="E2E_STORAGE_URL not set; set to real storage service to run E2E test"
)
def test_storage_find_file_e2e():
    uploader = Uploader(storage_url=STORAGE_URL, wallet=DummyWallet())
    test_data = b"find file e2e test"
    mime_type = "text/plain"
    retention = 60
    result = uploader.publish_file(test_data, mime_type, retention)
    uhrp_url = result.uhrp_url
    file_data = uploader.find_file(uhrp_url)
    assert file_data.name is not None
    assert file_data.size is not None
    assert file_data.mime_type == mime_type
    assert file_data.expiry_time > 0


@pytest.mark.e2e
@pytest.mark.skipif(
    not os.environ.get("E2E_STORAGE_URL"), reason="E2E_STORAGE_URL not set; set to real storage service to run E2E test"
)
def test_storage_list_uploads_e2e():
    """Test listing uploads returns a valid list (may be empty if no uploads exist)."""
    uploader = Uploader(storage_url=STORAGE_URL, wallet=DummyWallet())
    uploads = uploader.list_uploads()

    # Verify response is a list
    assert isinstance(uploads, list), f"list_uploads should return a list, got {type(uploads)}"

    # If list is not empty, verify structure of upload entries
    if len(uploads) > 0:
        first_upload = uploads[0]
        assert isinstance(first_upload, dict) or hasattr(
            first_upload, "__dict__"
        ), "Upload entries should be dict-like or objects with attributes"


@pytest.mark.e2e
@pytest.mark.skipif(
    not os.environ.get("E2E_STORAGE_URL"), reason="E2E_STORAGE_URL not set; set to real storage service to run E2E test"
)
def test_storage_renew_file_e2e():
    uploader = Uploader(storage_url=STORAGE_URL, wallet=DummyWallet())
    test_data = b"renew file e2e test"
    mime_type = "text/plain"
    retention = 1
    result = uploader.publish_file(test_data, mime_type, retention)
    uhrp_url = result.uhrp_url
    renew_result = uploader.renew_file(uhrp_url, additional_minutes=10)
    assert renew_result.status == "success"
    assert renew_result.new_expiry_time > renew_result.prev_expiry_time


@pytest.mark.e2e
@pytest.mark.skipif(
    not os.environ.get("E2E_STORAGE_URL"), reason="E2E_STORAGE_URL not set; set to real storage service to run E2E test"
)
def test_storage_download_hash_mismatch_e2e():
    uploader = Uploader(storage_url=STORAGE_URL, wallet=DummyWallet())
    downloader = Downloader(network=NETWORK)
    test_data = b"hash mismatch e2e test"
    mime_type = "text/plain"
    retention = 60
    result = uploader.publish_file(test_data, mime_type, retention)
    _ = result._
    # 改ざんURL（SHA256が異なるデータのUHRP URL）
    import hashlib

    bad_data = b"tampered data"
    from bsv.storage.utils import StorageUtils

    bad_url = StorageUtils.get_url_for_file(bad_data)
    import pytest

    with pytest.raises(DownloadError, match="Hash mismatch"):
        downloader.download(bad_url)
