namespace Eis.Infrastructure.Administration;

public sealed record AdminMigrationOptions(
    bool NativeReadsEnabled,
    bool NativeOrganizationWritesEnabled = false,
    bool NativeAccountBatchesEnabled = false,
    bool NativeConfigurationEnabled = false,
    bool NativeNoticeManagementEnabled = false,
    bool NativeCentersEnabled = false,
    bool NativeOperationalReadsEnabled = false,
    bool NativeCandidateManagementEnabled = false,
    bool NativeRegistrationPaymentWritesEnabled = false,
    bool NativeWorkflowOperationsEnabled = false,
    bool NativeExamManagementEnabled = false,
    bool NativeArrangementsEnabled = false,
    bool NativeResultsEnabled = false,
    bool NativeAdmissionsEnabled = false)
{
    public static AdminMigrationOptions FromEnvironment(
        bool configuredNativeReadsEnabled,
        bool authenticationNativeEnabled,
        bool sharesLegacySessions,
        bool configuredNativeOrganizationWritesEnabled = false,
        bool configuredNativeAccountBatchesEnabled = false,
        bool configuredNativeConfigurationEnabled = false,
        bool configuredNativeNoticeManagementEnabled = false,
        bool configuredNativeCentersEnabled = false,
        bool configuredNativeOperationalReadsEnabled = false,
        bool configuredNativeCandidateManagementEnabled = false,
        bool configuredNativeRegistrationPaymentWritesEnabled = false,
        bool configuredNativeWorkflowOperationsEnabled = false,
        bool configuredNativeExamManagementEnabled = false,
        bool configuredNativeArrangementsEnabled = false,
        bool configuredNativeResultsEnabled = false,
        bool configuredNativeAdmissionsEnabled = false)
    {
        var readsEnabled = configuredNativeReadsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_READS_ENABLED"), false);
        var organizationWritesEnabled = configuredNativeOrganizationWritesEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_ORGANIZATION_WRITES_ENABLED"), false);
        var accountBatchesEnabled = configuredNativeAccountBatchesEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_ACCOUNT_BATCHES_ENABLED"), false);
        var configurationEnabled = configuredNativeConfigurationEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_CONFIGURATION_ENABLED"), false);
        var noticeManagementEnabled = configuredNativeNoticeManagementEnabled || ParseBoolean(
            Environment.GetEnvironmentVariable("ADMIN_NATIVE_NOTICE_MANAGEMENT_ENABLED") ??
            Environment.GetEnvironmentVariable("ADMIN_NATIVE_NOTICE_WRITES_ENABLED"),
            false);
        var centersEnabled = configuredNativeCentersEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_CENTERS_ENABLED"), false);
        var operationalReadsEnabled = configuredNativeOperationalReadsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_OPERATIONAL_READS_ENABLED"), false);
        var candidateManagementEnabled = configuredNativeCandidateManagementEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_CANDIDATE_MANAGEMENT_ENABLED"), false);
        var registrationPaymentWritesEnabled = configuredNativeRegistrationPaymentWritesEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_REGISTRATION_PAYMENT_WRITES_ENABLED"), false);
        var workflowOperationsEnabled = configuredNativeWorkflowOperationsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_WORKFLOW_OPERATIONS_ENABLED"), false);
        var examManagementEnabled = configuredNativeExamManagementEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_EXAM_MANAGEMENT_ENABLED"), false);
        var arrangementsEnabled = configuredNativeArrangementsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_ARRANGEMENTS_ENABLED"), false);
        var resultsEnabled = configuredNativeResultsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_RESULTS_ENABLED"), false);
        var admissionsEnabled = configuredNativeAdmissionsEnabled ||
            ParseBoolean(Environment.GetEnvironmentVariable("ADMIN_NATIVE_ADMISSIONS_ENABLED"), false);
        if ((organizationWritesEnabled || accountBatchesEnabled || configurationEnabled || noticeManagementEnabled || centersEnabled || operationalReadsEnabled || candidateManagementEnabled || registrationPaymentWritesEnabled || workflowOperationsEnabled || examManagementEnabled || arrangementsEnabled || resultsEnabled || admissionsEnabled) && !readsEnabled)
        {
            throw new InvalidOperationException(
                "启用原生组织维护接口前必须同时设置 ADMIN_NATIVE_READS_ENABLED=true");
        }
        if ((candidateManagementEnabled || registrationPaymentWritesEnabled || resultsEnabled || admissionsEnabled) && !operationalReadsEnabled)
        {
            throw new InvalidOperationException(
                "启用原生考生、报名或缴费写接口前必须同时设置 ADMIN_NATIVE_OPERATIONAL_READS_ENABLED=true");
        }
        var anyNativeAdminEndpointEnabled = readsEnabled || organizationWritesEnabled || accountBatchesEnabled || configurationEnabled || noticeManagementEnabled || centersEnabled || operationalReadsEnabled || candidateManagementEnabled || registrationPaymentWritesEnabled || workflowOperationsEnabled || examManagementEnabled || arrangementsEnabled || resultsEnabled || admissionsEnabled;
        if (anyNativeAdminEndpointEnabled && !authenticationNativeEnabled)
        {
            throw new InvalidOperationException(
                "启用原生管理端接口前必须同时设置 AUTH_NATIVE_ENABLED=true");
        }

        return new AdminMigrationOptions(readsEnabled, organizationWritesEnabled, accountBatchesEnabled, configurationEnabled, noticeManagementEnabled, centersEnabled, operationalReadsEnabled, candidateManagementEnabled, registrationPaymentWritesEnabled, workflowOperationsEnabled, examManagementEnabled, arrangementsEnabled, resultsEnabled, admissionsEnabled);
    }

    private static bool ParseBoolean(string? value, bool fallback) => value?.Trim().ToLowerInvariant() switch
    {
        "1" or "true" or "yes" or "on" => true,
        "0" or "false" or "no" or "off" => false,
        _ => fallback
    };
}
