"""
Tests for egress configuration parsing

These tests verify:
1. EGRESS_MODE defaults to "api" (Shuttle only); "both" and "sftp" remain
   available for parallel-run and legacy-only operation
2. EGRESS_MODE is validated and Amazon/S3 settings become mandatory once
   responses can leave via the Shuttle API
3. The derived channel flags match each mode (both / sftp / api)
"""

import os
import sys
import unittest
from pathlib import Path
from unittest.mock import patch

sys.path.insert(0, str(Path(__file__).resolve().parents[2]))

from app.src.config import EGRESS_MODES, create_config_from_env

BASE_ENV = {
    "SFTP_HOST": "sftp.example.com",
    "SFTP_USERNAME": "in-user",
    "RX_API_KEY": "test-api-key",
    "MYSQL_USERNAME": "db-user",
    "MYSQL_PASSWORD": "db-pass",
}

AMAZON_ENV = {
    "AMAZON_COGNITO_TOKEN_URL": "https://cognito.example.com/oauth2/token",
    "AMAZON_CLIENT_ID": "client-id",
    "AMAZON_CLIENT_SECRET": "client-secret",
    "AMAZON_OAUTH_SCOPE": "shuttle-service-gamma-api/consultation",
    "AMAZON_CONSULTATION_RESPONSE_URL": "https://gamma.example.com/v1/consultation/response",
    "S3_BUCKET": "rx-bucket",
}


def load_config(**overrides):
    env = {**BASE_ENV, **overrides}
    with patch.dict(os.environ, env, clear=True):
        return create_config_from_env()


class TestEgressDefaults(unittest.TestCase):
    def test_defaults_to_api_only(self):
        config = load_config(**AMAZON_ENV)

        self.assertEqual(config.egress_mode, "api")
        self.assertFalse(config.egress_sftp_enabled)
        self.assertTrue(config.egress_api_enabled)
        self.assertEqual(config.amazon_provider_name, "myrx")
        self.assertEqual(config.s3_prefix, "consultation-responses")
        self.assertEqual(config.s3_presign_ttl_seconds, 43200)

    def test_api_egress_is_limited_to_test_orders_by_default(self):
        config = load_config(**AMAZON_ENV)

        self.assertTrue(config.egress_api_test_orders_only)

    def test_test_orders_only_gate_can_be_switched_off(self):
        config = load_config(EGRESS_API_TEST_ORDERS_ONLY="false", **AMAZON_ENV)

        self.assertFalse(config.egress_api_test_orders_only)

        config = load_config(EGRESS_API_TEST_ORDERS_ONLY="TRUE", **AMAZON_ENV)
        self.assertTrue(config.egress_api_test_orders_only)

    def test_real_order_ramp_is_off_by_default(self):
        config = load_config(**AMAZON_ENV)
        self.assertEqual(config.egress_api_real_order_limit, 0)

    def test_real_order_ramp_limit_is_read(self):
        config = load_config(EGRESS_API_REAL_ORDER_LIMIT=" 100 ", **AMAZON_ENV)
        self.assertEqual(config.egress_api_real_order_limit, 100)

    def test_real_order_ramp_limit_rejects_garbage(self):
        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_API_REAL_ORDER_LIMIT="hundred", **AMAZON_ENV)
        self.assertIn("EGRESS_API_REAL_ORDER_LIMIT", str(ctx.exception))

    def test_real_order_ramp_limit_rejects_negative(self):
        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_API_REAL_ORDER_LIMIT="-1", **AMAZON_ENV)
        self.assertIn("0 or greater", str(ctx.exception))

    def test_default_mode_refuses_to_start_without_amazon_settings(self):
        with self.assertRaises(ValueError) as ctx:
            load_config()

        message = str(ctx.exception)
        for var in AMAZON_ENV:
            self.assertIn(var, message)

    def test_sftp_mode_does_not_require_amazon_settings(self):
        config = load_config(EGRESS_MODE="sftp")

        self.assertTrue(config.egress_sftp_enabled)
        self.assertFalse(config.egress_api_enabled)
        self.assertEqual(config.amazon_client_id, "")
        self.assertEqual(config.s3_bucket, "")


class TestEgressModeValidation(unittest.TestCase):
    def test_all_declared_modes_accepted(self):
        for mode in EGRESS_MODES:
            with self.subTest(mode=mode):
                config = load_config(EGRESS_MODE=mode, **AMAZON_ENV)
                self.assertEqual(config.egress_mode, mode)

    def test_mode_is_case_insensitive(self):
        config = load_config(EGRESS_MODE="BOTH", **AMAZON_ENV)

        self.assertEqual(config.egress_mode, "both")

    def test_both_mode_enables_sftp_and_api(self):
        config = load_config(EGRESS_MODE="both", **AMAZON_ENV)

        self.assertTrue(config.egress_sftp_enabled)
        self.assertTrue(config.egress_api_enabled)

    def test_api_mode_switches_sftp_off(self):
        config = load_config(EGRESS_MODE="api", **AMAZON_ENV)

        self.assertTrue(config.egress_api_enabled)
        self.assertFalse(config.egress_sftp_enabled)

    def test_unknown_mode_rejected(self):
        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_MODE="carrier-pigeon")

        self.assertIn("EGRESS_MODE", str(ctx.exception))

    def test_retired_fallback_mode_rejected(self):
        with self.assertRaises(ValueError):
            load_config(EGRESS_MODE="api_with_sftp_fallback", **AMAZON_ENV)

    def test_both_mode_requires_amazon_and_s3_settings(self):
        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_MODE="both")

        message = str(ctx.exception)
        for var in AMAZON_ENV:
            self.assertIn(var, message)

    def test_api_mode_requires_amazon_and_s3_settings(self):
        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_MODE="api")

        message = str(ctx.exception)
        for var in AMAZON_ENV:
            self.assertIn(var, message)

    def test_reports_only_the_missing_settings(self):
        partial = {k: v for k, v in AMAZON_ENV.items() if k != "AMAZON_CLIENT_SECRET"}

        with self.assertRaises(ValueError) as ctx:
            load_config(EGRESS_MODE="both", **partial)

        message = str(ctx.exception)
        self.assertIn("AMAZON_CLIENT_SECRET", message)
        self.assertNotIn("AMAZON_CLIENT_ID", message)


class TestAmazonSettingsParsing(unittest.TestCase):
    def test_amazon_settings_are_read(self):
        config = load_config(
            EGRESS_MODE="both",
            AMAZON_PROVIDER_NAME="MyRx",
            AMAZON_API_TIMEOUT_SECONDS="45",
            AMAZON_API_RETRY_ATTEMPTS="5",
            AMAZON_API_RETRY_DELAY_SECONDS="2.5",
            S3_REGION="us-west-2",
            S3_PREFIX="/rx/zips/",
            S3_PRESIGN_TTL_SECONDS="3600",
            **AMAZON_ENV,
        )

        self.assertEqual(config.amazon_provider_name, "myrx")
        self.assertEqual(config.amazon_cognito_token_url, AMAZON_ENV["AMAZON_COGNITO_TOKEN_URL"])
        self.assertEqual(config.amazon_client_id, "client-id")
        self.assertEqual(config.amazon_client_secret, "client-secret")
        self.assertEqual(config.amazon_oauth_scope, AMAZON_ENV["AMAZON_OAUTH_SCOPE"])
        self.assertEqual(
            config.amazon_consultation_response_url,
            AMAZON_ENV["AMAZON_CONSULTATION_RESPONSE_URL"],
        )
        self.assertEqual(config.amazon_api_timeout_seconds, 45.0)
        self.assertEqual(config.amazon_api_retry_attempts, 5)
        self.assertEqual(config.amazon_api_retry_delay_seconds, 2.5)
        self.assertEqual(config.s3_bucket, "rx-bucket")
        self.assertEqual(config.s3_region, "us-west-2")
        self.assertEqual(config.s3_prefix, "rx/zips")
        self.assertEqual(config.s3_presign_ttl_seconds, 3600)


if __name__ == "__main__":
    unittest.main()
