#!/usr/bin/env python3
"""
Real MinIO integration checks.

These tests are intentionally separate from the core automated suite because
they require a reachable MinIO instance.
"""

from __future__ import annotations

import asyncio
import os
import sys
import tempfile
import time
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent.parent))

from sandai.operator.env import get_minio_config
from sandai.operator.processor import BatchProcessor


def test_minio_connection() -> bool:
    print("Checking MinIO connectivity")
    config = get_minio_config()
    print(f"  endpoint={config.endpoint}")
    print(f"  bucket={config.bucket_name}")
    print(f"  access_key={config.access_key}")
    print(f"  secure={config.secure}")

    try:
        import boto3
        from botocore.exceptions import EndpointConnectionError, NoCredentialsError

        s3_client = boto3.client(
            "s3",
            endpoint_url=f"{'https' if config.secure else 'http'}://{config.endpoint}",
            aws_access_key_id=config.access_key,
            aws_secret_access_key=config.secret_key,
            region_name=config.region,
        )
        response = s3_client.list_buckets()
        buckets = [bucket["Name"] for bucket in response["Buckets"]]

        print("  connection succeeded")
        print(f"  buckets={buckets}")
        if config.bucket_name in buckets:
            print(f"  target bucket exists: {config.bucket_name}")
        else:
            print(f"  target bucket is missing and may be created later: {config.bucket_name}")
        return True
    except EndpointConnectionError:
        print(f"  failed to connect to {config.endpoint}")
        print("  ensure MinIO is running before rerunning this test")
        return False
    except NoCredentialsError:
        print("  credentials are invalid")
        return False
    except Exception as exc:
        print(f"  connection failed: {exc}")
        return False


def test_minio_real_upload() -> bool:
    print("Running real MinIO upload check")
    processor = BatchProcessor("test-operator", "v1", ignore_nongil_check=True)
    processor._setup_temp_directory()
    test_content = f"Test file for MinIO upload\nTimestamp: {time.time()}\nContent: Hello MinIO!"

    with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as temp_file:
        temp_file.write(test_content)
        test_file_path = temp_file.name

    try:
        print(f"  local_file={test_file_path}")
        print(f"  content_length={len(test_content)}")
        result = asyncio.run(processor._upload_to_storage(test_file_path))
        result_url = result[1]["external-url"] if isinstance(result, tuple) else result
        print(f"  upload succeeded: {result_url}")

        config = get_minio_config()
        expected_prefix = (
            f"{'https' if config.secure else 'http'}://{config.endpoint}/"
            f"{config.bucket_name}/{config.prefix}/"
        )
        if result_url.startswith(expected_prefix):
            print("  URL prefix is correct")
        else:
            print("  URL prefix differs from the expected config")
            print(f"  expected_prefix={expected_prefix}")
            print(f"  actual_url={result_url}")
        return True
    except Exception as exc:
        print(f"  upload failed: {exc}")
        import traceback

        traceback.print_exc()
        return False
    finally:
        if os.path.exists(test_file_path):
            os.unlink(test_file_path)
            print("  cleaned up local test file")


def test_minio_bucket_operations() -> bool:
    print("Checking MinIO bucket operations")
    try:
        import boto3
        from botocore.exceptions import ClientError

        config = get_minio_config()
        s3_client = boto3.client(
            "s3",
            endpoint_url=f"{'https' if config.secure else 'http'}://{config.endpoint}",
            aws_access_key_id=config.access_key,
            aws_secret_access_key=config.secret_key,
            region_name=config.region,
        )

        try:
            s3_client.head_bucket(Bucket=config.bucket_name)
            print(f"  bucket exists: {config.bucket_name}")
            bucket_exists = True
        except ClientError as exc:
            if exc.response["Error"]["Code"] == "404":
                print(f"  bucket is missing: {config.bucket_name}")
                bucket_exists = False
            else:
                raise

        if not bucket_exists:
            print(f"  creating bucket: {config.bucket_name}")
            s3_client.create_bucket(Bucket=config.bucket_name)
            print("  bucket creation succeeded")

        try:
            response = s3_client.list_objects_v2(
                Bucket=config.bucket_name,
                Prefix=config.prefix,
                MaxKeys=10,
            )
            if "Contents" in response:
                objects = response["Contents"]
                print(f"  found {len(objects)} object(s) under prefix {config.prefix}")
                for obj in objects[:5]:
                    print(f"    - {obj['Key']} ({obj['Size']} bytes)")
                if len(objects) > 5:
                    print(f"    ... plus {len(objects) - 5} more")
            else:
                print("  bucket/prefix is currently empty")
        except Exception as exc:
            print(f"  failed to list objects: {exc}")

        return True
    except Exception as exc:
        print(f"  bucket operations failed: {exc}")
        return False


def test_minio_with_custom_config() -> bool:
    print("Checking custom MinIO config overrides")
    original_env = {}
    custom_env = {
        "SANDAI_OPERATOR_MINIO_BUCKET": "test-sandai-bucket",
        "SANDAI_OPERATOR_MINIO_PREFIX": "test-uploads",
    }

    for key in custom_env:
        if key in os.environ:
            original_env[key] = os.environ[key]

    try:
        for key, value in custom_env.items():
            os.environ[key] = value

        from importlib import reload
        from sandai.operator import env

        reload(env)
        config = env.get_minio_config()
        print(f"  bucket={config.bucket_name}")
        print(f"  prefix={config.prefix}")

        processor = BatchProcessor("test-operator", "v1", ignore_nongil_check=True)
        processor._setup_temp_directory()
        with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as temp_file:
            temp_file.write("Test content for custom config")
            test_file_path = temp_file.name

        try:
            result = asyncio.run(processor._upload_to_storage(test_file_path))
            result_url = result[1]["external-url"] if isinstance(result, tuple) else result
            if config.bucket_name in result_url and config.prefix in result_url:
                print(f"  custom config is reflected in URL: {result_url}")
                return True
            print(f"  custom config was not reflected in URL: {result_url}")
            return False
        finally:
            if os.path.exists(test_file_path):
                os.unlink(test_file_path)
    finally:
        for key in custom_env:
            if key in original_env:
                os.environ[key] = original_env[key]
            else:
                os.environ.pop(key, None)
        reload(env)


def main() -> int:
    print("Real MinIO integration checks")
    print("=" * 60)
    print("This test requires a reachable MinIO service, typically on localhost:9000")
    print(
        'Example startup: docker run -p 9000:9000 -p 9001:9001 minio/minio server /data --console-address ":9001"'
    )

    tests = [
        ("connection", test_minio_connection),
        ("real_upload", test_minio_real_upload),
        ("bucket_ops", test_minio_bucket_operations),
        ("custom_config", test_minio_with_custom_config),
    ]

    passed = 0
    failed = 0

    for name, test_func in tests:
        print(f"\n{'=' * 20} {name} {'=' * 20}")
        try:
            if test_func():
                print(f"PASS {name}")
                passed += 1
            else:
                print(f"FAIL {name}")
                failed += 1
        except Exception as exc:
            print(f"ERROR {name}: {exc}")
            import traceback

            traceback.print_exc()
            failed += 1

    print("\n" + "=" * 60)
    print(f"passed={passed} failed={failed}")
    if failed == 0:
        print("All real MinIO integration checks passed")
        return 0

    if failed == len(tests):
        print("Common causes: MinIO is not running, the port is unavailable, networking is blocked, or credentials are wrong")
    return 1


if __name__ == "__main__":
    raise SystemExit(main())
