"""Smoke test external production services without printing secrets."""

from __future__ import annotations

import argparse
import os
import smtplib
import tempfile
import time
from pathlib import Path

import redis

try:
    import oss2
except ImportError:  # pragma: no cover
    oss2 = None


def is_enabled(value: str | None) -> bool:
    return str(value or "").lower() in {"1", "true", "yes", "on"}


def require_env(name: str) -> str:
    value = os.getenv(name)
    if not value:
        raise RuntimeError(f"missing required env: {name}")
    return value


def smoke_redis(strict: bool) -> None:
    enabled = is_enabled(os.getenv("ENABLE_REDIS_SESSIONS"))
    if not strict and not enabled:
        print("SKIP redis sessions: ENABLE_REDIS_SESSIONS is disabled")
        return

    client = redis.Redis.from_url(require_env("REDIS_URL"), decode_responses=True, socket_timeout=5)
    if client.ping() is not True:
        raise RuntimeError("redis ping failed")
    key = f"xiaoxia:smoke:{int(time.time())}"
    client.setex(key, 30, "ok")
    if client.get(key) != "ok":
        raise RuntimeError("redis set/get smoke failed")
    client.delete(key)
    print("OK redis sessions")


def smoke_smtp(strict: bool, send_email_to: str | None) -> None:
    enabled = is_enabled(os.getenv("ENABLE_EMAIL_DELIVERY"))
    if not strict and not enabled:
        print("SKIP smtp: ENABLE_EMAIL_DELIVERY is disabled")
        return

    host = require_env("SMTP_HOST")
    port = int(require_env("SMTP_PORT"))
    user = os.getenv("SMTP_USER", "")
    password = os.getenv("SMTP_PASSWORD", "")
    from_email = require_env("SMTP_FROM_EMAIL")
    use_tls = is_enabled(os.getenv("SMTP_USE_TLS", "true"))

    with smtplib.SMTP(host, port, timeout=10) as server:
        if use_tls:
            server.starttls()
        if user or password:
            server.login(user, password)
        if send_email_to:
            server.sendmail(
                from_email,
                [send_email_to],
                "Subject: Xiaoxia SaaS external service smoke\n\nOK: SMTP smoke test.",
            )
    action = "send" if send_email_to else "connect/login"
    print(f"OK smtp {action}")


def smoke_oss(strict: bool) -> None:
    endpoint = os.getenv("OSS_ENDPOINT", "")
    access_key_id = os.getenv("OSS_ACCESS_KEY_ID", "")
    access_key_secret = os.getenv("OSS_ACCESS_KEY_SECRET", "")
    bucket_name = os.getenv("OSS_BUCKET_NAME", "")
    if not strict and not (endpoint and access_key_id and access_key_secret and bucket_name):
        print("SKIP oss: OSS credentials are not fully configured")
        return
    for name, value in {
        "OSS_ENDPOINT": endpoint,
        "OSS_ACCESS_KEY_ID": access_key_id,
        "OSS_ACCESS_KEY_SECRET": access_key_secret,
        "OSS_BUCKET_NAME": bucket_name,
    }.items():
        if not value:
            raise RuntimeError(f"missing required env: {name}")

    if oss2 is None:
        raise RuntimeError("oss2 is required for OSS smoke")

    auth = oss2.Auth(access_key_id, access_key_secret)
    bucket = oss2.Bucket(auth, endpoint, bucket_name)
    key = f"smoke/external-services-{int(time.time())}.txt"
    with tempfile.NamedTemporaryFile("w", delete=False, encoding="utf-8") as handle:
        handle.write("xiaoxia oss smoke ok\n")
        local_path = Path(handle.name)
    try:
        bucket.put_object_from_file(key, str(local_path), headers={"Content-Type": "text/plain"})
        if not bucket.object_exists(key):
            raise RuntimeError("oss uploaded object does not exist")
        bucket.get_object(key).read()
        bucket.delete_object(key)
    finally:
        local_path.unlink(missing_ok=True)
    print("OK oss upload/download/delete")


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--strict", action="store_true", help="Fail when disabled/unconfigured services are missing.")
    parser.add_argument(
        "--skip-smtp", action="store_true", help="Skip SMTP smoke when email delivery is intentionally disabled."
    )
    parser.add_argument(
        "--skip-redis", action="store_true", help="Skip Redis session smoke when sessions are intentionally disabled."
    )
    parser.add_argument(
        "--skip-oss", action="store_true", help="Skip OSS smoke when object storage is intentionally disabled."
    )
    parser.add_argument(
        "--send-email-to", help="Actually send a test email to this address. Otherwise SMTP only connects/logs in."
    )
    args = parser.parse_args(argv)

    if args.skip_redis:
        print("SKIP redis sessions: explicitly skipped")
    else:
        smoke_redis(args.strict)
    if args.skip_smtp:
        print("SKIP smtp: explicitly skipped")
    else:
        smoke_smtp(args.strict, args.send_email_to)
    if args.skip_oss:
        print("SKIP oss: explicitly skipped")
    else:
        smoke_oss(args.strict)
    print("OK external service smoke complete")
    return 0


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