import argparse

import psycopg
from pydantic import EmailStr, TypeAdapter
from src.infrastructure.clients.cognito_idp_client import CognitoIdpClient
from src.infrastructure.credential_manager import CredentialManager
from src.infrastructure.repositories.user_identity_repository import UserIdentityRepository
from src.logger import logger
from src.settings import Settings
from src.usecases.management_console_usecase import ManagementConsoleUseCase

EMAIL_LIST_ADAPTER = TypeAdapter(list[EmailStr])
settings = Settings()


def main(
    whi_customer_ids: list[str],
    cydas_customer_ids: list[str],
    tenant_name: str,
    user_emails: list[EmailStr],
) -> None:
    logger.info(f"WHI_CUSTOMER_IDS: {whi_customer_ids}")
    logger.info(f"CYDAS_CUSTOMER_IDS: {cydas_customer_ids}")
    logger.info(f"TENANT_NAME: {tenant_name}")
    logger.info(f"USER_EMAILS_COUNT: {len(user_emails)}")

    if not settings.management_user_pool_id:
        raise ValueError("MANAGEMENT_USER_POOL_ID is not set")

    cognito_client = CognitoIdpClient(user_pool_id=settings.management_user_pool_id)
    with psycopg.connect(conninfo=settings.postgres_url, autocommit=True) as connection:
        usecase = ManagementConsoleUseCase.create(
            connection=connection,
            credential_manager=CredentialManager(client=cognito_client),
            user_identity_repository_factory=lambda tenant: UserIdentityRepository(
                tenant=tenant,
                client=cognito_client,
            ),
        )

        usecase.initialize(
            whi_customer_ids=whi_customer_ids,
            cydas_customer_ids=cydas_customer_ids,
            tenant_name=tenant_name,
            user_emails=user_emails,
        )

        logger.info("Management console initialized successfully.")


def __string_list(input_str: str) -> list[str]:
    return [s.strip() for s in input_str.split(",") if s.strip()]


def __non_empty_string(input_str: str) -> str:
    if not input_str:
        raise argparse.ArgumentTypeError("This argument cannot be empty.")
    return input_str


def __non_empty_email_list(input_str: str) -> list[EmailStr]:
    results = __string_list(input_str)
    if not results:
        raise argparse.ArgumentTypeError("At least one value is required.")

    try:
        EMAIL_LIST_ADAPTER.validate_python(results)
    except ValueError as e:
        raise argparse.ArgumentTypeError(
            f"Invalid email address found in input ({len(results)} items provided).",
        ) from e
    return results


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Management Console Initializer Script")
    parser.add_argument(
        "--whi-customer-ids",
        type=__string_list,
        required=False,
        default=[],
        help="WHI Customer IDs (comma-separated)",
    )
    parser.add_argument(
        "--cydas-customer-ids",
        type=__string_list,
        required=False,
        default=[],
        help="CYDAS Customer IDs (comma-separated)",
    )
    parser.add_argument(
        "--tenant-name",
        type=__non_empty_string,
        required=True,
        help="Tenant name for management console",
    )
    parser.add_argument(
        "--user-emails",
        type=__non_empty_email_list,
        required=True,
        help="Initial user emails (comma-separated, typically 2 emails)",
    )

    args = parser.parse_args()
    main(
        whi_customer_ids=args.whi_customer_ids,
        cydas_customer_ids=args.cydas_customer_ids,
        tenant_name=args.tenant_name,
        user_emails=args.user_emails,
    )
