from sqlalchemy.engine.url import make_url, URL
from starlette.config import Config
from starlette.datastructures import CommaSeparatedStrings
from starlette.datastructures import Secret


class CommaSeparatedLogins(CommaSeparatedStrings):
    def __init__(self, value):
        super().__init__(value)
        self._items = [item.split(":") for item in self._items]


config = Config(".env")

# =============== Server  ===============

# When True, (1) sets log level to debug and (2) ensures fastapi log/error traces are more detailed:
DEBUG = config("DEBUG", cast=bool, default=False)
TESTING = config("TESTING", cast=bool, default=False)
# (For easier local testing/dev - DO NOT ENABLE IN PROD) If set to True, this flag will disable authz to simplify some test paths:
TESTING_WITH_DISABLED_AUTHZ = config(
    "TESTING_WITH_DISABLED_AUTHZ", cast=bool, default=False
)
USE_AGG_MDS = config("USE_AGG_MDS", cast=bool, default=False)
AGG_MDS_NAMESPACE = config("AGG_MDS_NAMESPACE", default="default_namespace")
AGG_MDS_DEFAULT_STUDY_DATA_FIELD = config(
    "AGG_MDS_DEFAULT_STUDY_DATA_FIELD", cast=str, default="gen3_discovery"
)
AGG_MDS_DEFAULT_DATA_DICT_FIELD = config(
    "AGG_MDS_DEFAULT_DATA_DICT_FIELD", cast=str, default="data_dictionaries"
)
ES_ENDPOINT = config("GEN3_ES_ENDPOINT", default="http://localhost:9200")

# =============== Database ===============

DB_DRIVER = config("DB_DRIVER", default="postgresql+asyncpg")
DB_HOST = config("DB_HOST", default=None)
DB_PORT = config("DB_PORT", cast=int, default=None)
DB_USER = config("DB_USER", default=None)
DB_PASSWORD = config("DB_PASSWORD", cast=Secret, default=None)
DB_DATABASE = config("DB_DATABASE", default=None)

if TESTING:
    DB_DATABASE = "test_" + (DB_DATABASE or "metadata")
    TEST_KEEP_DB = config("TEST_KEEP_DB", cast=bool, default=False)


DB_DSN = config(
    "DB_DSN",
    cast=make_url,
    default=URL.create(
        drivername=DB_DRIVER,
        username=DB_USER,
        password=str(DB_PASSWORD) if DB_PASSWORD else None,
        host=DB_HOST,
        port=DB_PORT,
        database=DB_DATABASE,
    ),
)
DB_POOL_MIN_SIZE = config("DB_POOL_MIN_SIZE", cast=int, default=5)
DB_POOL_MAX_SIZE = config("DB_POOL_MAX_SIZE", cast=int, default=15)
DB_ECHO = config("DB_ECHO", cast=bool, default=False)
DB_SSL = config("DB_SSL", default=None)
DB_CONNECT_RETRIES = config("DB_CONNECT_RETRIES", cast=int, default=32)


# =============== Elasticsearch ===============
ES_RETRY_INTERVAL = config("ES_RETRY_INTERVAL", cast=int, default=20)
ES_RETRY_LIMIT = config("ES_RETRY_LIMIT", cast=int, default=5)
# =============== Authz string ===============

DEFAULT_AUTHZ_STR = config(
    "DEFAULT_AUTHZ_STR",
    cast=str,
    default='{"version": 0, "_resource_paths": ["/open"]}',
)

# =============== Limits ===============
METADATA_QUERY_RESULTS_LIMIT = config(
    "METADATA_QUERY_RESULTS_LIMIT", cast=int, default=2000
)

# =============== Security ===============

# Optional. Can be set to enable basic auth on some admin endpoints. E.g. ADMIN_LOGINS=alice:123,bob:456
ADMIN_LOGINS = config("ADMIN_LOGINS", cast=CommaSeparatedLogins, default=[])
FORCE_ISSUER = config("FORCE_ISSUER", default=None)
ALLOWED_ISSUERS = set(config("ALLOWED_ISSUERS", cast=CommaSeparatedStrings, default=""))
# If set to True, this flag will force an authorization check for all metadata query endpoints:
FORCE_AUTHZ_CHECK_FOR_METADATA_QUERIES = config(
    "FORCE_AUTHZ_CHECK_FOR_METADATA_QUERIES", cast=bool, default=False
)

# =============== Other Services ===============

INDEXING_SERVICE_ENDPOINT = config(
    "INDEXING_SERVICE_ENDPOINT", cast=str, default="http://indexd-service"
)
DATA_ACCESS_SERVICE_ENDPOINT = config(
    "DATA_ACCESS_SERVICE_ENDPOINT", cast=str, default="http://fence-service"
)
