using CashLineERP.Application.Health;
using CashLineERP.Application.Identity;
using CashLineERP.Application.IslamicFinance.Facilities;
using CashLineERP.Application.IslamicFinance.ContractTemplates;
using CashLineERP.Application.IslamicFinance.Disbursements;
using CashLineERP.Application.IslamicFinance.Murabaha;
using CashLineERP.Application.IslamicFinance.PartnerLenders;
using CashLineERP.Application.IslamicFinance.ProductProfiles;
using CashLineERP.Application.IslamicFinance.ReceivablesFinance;
using CashLineERP.Application.IslamicFinance.Requests;
using CashLineERP.Application.IslamicFinance.Settlements;
using CashLineERP.Application.IslamicFinance.Shariah;
using CashLineERP.Application.Internal;
using CashLineERP.Application.Integration;
using CashLineERP.Application.External;
using CashLineERP.Application.Documents;
using CashLineERP.Application.Finance;
using CashLineERP.Application.Inventory;
using CashLineERP.Application.Localization;
using CashLineERP.Application.MasterData;
using CashLineERP.Application.Notifications;
using CashLineERP.Application.Parties;
using CashLineERP.Application.Pricing;
using CashLineERP.Application.Privacy;
using CashLineERP.Application.Procurement;
using CashLineERP.Application.Reporting;
using CashLineERP.Application.Sales;
using CashLineERP.Application.Customers;
using CashLineERP.Application.Suppliers;
using CashLineERP.Application.Tax;
using CashLineERP.Application.Workflow;
using CashLineERP.Infrastructure.Configuration;
using CashLineERP.Infrastructure.Documents;
using CashLineERP.Infrastructure.Persistence;
using CashLineERP.Infrastructure.Persistence.Repositories;
using CashLineERP.Infrastructure.Persistence.Repositories.IslamicFinance;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace CashLineERP.Infrastructure.DependencyInjection;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddCashLineInfrastructure(
        this IServiceCollection services,
        IConfiguration configuration,
        string contentRootPath)
    {
        var provider = configuration[$"{DatabaseOptions.SectionName}:Provider"] ?? "SqlServer";
        var connectionString = configuration[$"{DatabaseOptions.SectionName}:ConnectionString"] ?? string.Empty;
        services.AddDbContext<CashLineErpDbContext>(options =>
        {
            if (string.Equals(provider, "SqlServer", StringComparison.OrdinalIgnoreCase))
            {
                options.UseSqlServer(connectionString);
                return;
            }

            if (string.Equals(provider, "Sqlite", StringComparison.OrdinalIgnoreCase))
            {
                options.UseSqlite(ResolveSqliteConnectionString(connectionString, contentRootPath));
                return;
            }

            throw new NotSupportedException(
                $"Database provider '{provider}' is not yet wired in the infrastructure layer.");
        });

        services.AddScoped<IIdentityReadRepository, IdentityReadRepository>();
        services.AddScoped<IOnboardingAccessProvisioningRepository, OnboardingAccessProvisioningRepository>();
        services.AddScoped<IInternalWorkbenchRepository, InternalWorkbenchRepository>();
        services.AddScoped<ILocalizationResourceRepository, LocalizationResourceRepository>();
        services.AddScoped<IIntegrationEndpointRegistryRepository, IntegrationEndpointRegistryRepository>();
        services.AddScoped<IOutboxEventRepository, OutboxEventRepository>();
        services.AddScoped<IInboxMessageRepository, InboxMessageRepository>();
        services.AddScoped<IDeadLetterRepository, DeadLetterRepository>();
        services.AddScoped<INotificationTemplateRepository, NotificationTemplateRepository>();
        services.AddScoped<INotificationOrchestrationRepository, NotificationOrchestrationRepository>();
        services.AddScoped<IExternalPortalRepository, ExternalPortalRepository>();
        services.AddScoped<IDocumentStorageRepository, DocumentStorageRepository>();
        services.AddScoped<IReferenceDataGovernanceRepository, ReferenceDataGovernanceRepository>();
        services.AddScoped<IBusinessPartyRepository, BusinessPartyRepository>();
        services.AddScoped<IOnboardingCaseRepository, OnboardingCaseRepository>();
        services.AddScoped<IOnboardingReviewRepository, OnboardingReviewRepository>();
        services.AddScoped<ISupplierProfileRepository, SupplierProfileRepository>();
        services.AddScoped<ICustomerProfileRepository, CustomerProfileRepository>();
        services.AddScoped<IIslamicFinanceFacilityRepository, IslamicFinanceFacilityRepository>();
        services.AddScoped<IIslamicFinanceContractTemplateRepository, IslamicFinanceContractTemplateRepository>();
        services.AddScoped<IIslamicFinanceMurabahaDisbursementRepository, IslamicFinanceMurabahaDisbursementRepository>();
        services.AddScoped<IIslamicFinanceSettlementRepository, IslamicFinanceSettlementRepository>();
        services.AddScoped<IIslamicFinanceMurabahaAssetRepository, IslamicFinanceMurabahaAssetRepository>();
        services.AddScoped<IIslamicFinanceMurabahaAccountingHookRepository, IslamicFinanceMurabahaAccountingHookRepository>();
        services.AddScoped<IIslamicFinanceMurabahaAssetEvidenceRepository, IslamicFinanceMurabahaAssetEvidenceRepository>();
        services.AddScoped<IIslamicFinanceMurabahaContractRepository, IslamicFinanceMurabahaContractRepository>();
        services.AddScoped<IMurabahaCaseRepository, MurabahaCaseRepository>();
        services.AddScoped<IIslamicFinancePartnerRepository, IslamicFinancePartnerRepository>();
        services.AddScoped<IIslamicFinanceProductRepository, IslamicFinanceProductRepository>();
        services.AddScoped<IReceivablesFinanceRepository, ReceivablesFinanceRepository>();
        services.AddScoped<IIslamicFinanceRequestRepository, IslamicFinanceRequestRepository>();
        services.AddScoped<IShariahReviewRepository, ShariahReviewRepository>();
        services.AddScoped<IPurchaseRequisitionRepository, PurchaseRequisitionRepository>();
        services.AddScoped<IRfqRepository, RfqRepository>();
        services.AddScoped<IRfqEvaluationRepository, RfqEvaluationRepository>();
        services.AddScoped<IPurchaseOrderRepository, PurchaseOrderRepository>();
        services.AddScoped<IGoodsReceiptRepository, GoodsReceiptRepository>();
        services.AddScoped<IPurchaseReturnRepository, PurchaseReturnRepository>();
        services.AddScoped<IAccountsPayableBillRepository, AccountsPayableBillRepository>();
        services.AddScoped<IAccountsPayablePaymentRepository, AccountsPayablePaymentRepository>();
        services.AddScoped<IBankTransferBatchRepository, BankTransferBatchRepository>();
        services.AddScoped<IPaymentSettlementBatchRepository, PaymentSettlementBatchRepository>();
        services.AddScoped<ICashAccountRepository, CashAccountRepository>();
        services.AddScoped<ITreasuryTransferRepository, TreasuryTransferRepository>();
        services.AddScoped<IForeignExchangeQuoteRepository, ForeignExchangeQuoteRepository>();
        services.AddScoped<IForeignExchangeOverrideRepository, ForeignExchangeOverrideRepository>();
        services.AddScoped<IForeignExchangeRevaluationRepository, ForeignExchangeRevaluationRepository>();
        services.AddScoped<ICardTokenReferenceRepository, CardTokenReferenceRepository>();
        services.AddScoped<IPaymentChannelConfigurationRepository, PaymentChannelConfigurationRepository>();
        services.AddScoped<IGatewayCallbackRepository, GatewayCallbackRepository>();
        services.AddScoped<IWalletRuleRepository, WalletRuleRepository>();
        services.AddScoped<IAccountingRuleRepository, FinanceAccountingRuleRepository>();
        services.AddScoped<ICollectionsWorkbenchRepository, CollectionsWorkbenchRepository>();
        services.AddScoped<ICustomerStatementRepository, CustomerStatementRepository>();
        services.AddScoped<ISupplierStatementRepository, SupplierStatementRepository>();
        services.AddScoped<ISupplierAccountReconciliationRepository, SupplierAccountReconciliationRepository>();
        services.AddScoped<IPricingRuleRepository, PricingRuleRepository>();
        services.AddScoped<IAccountsReceivableInvoiceRepository, AccountsReceivableInvoiceRepository>();
        services.AddScoped<IAccountsReceivableReceiptRepository, AccountsReceivableReceiptRepository>();
        services.AddScoped<ICustomerRefundRepository, CustomerRefundRepository>();
        services.AddScoped<IPaymentGatewayExecutionRepository, PaymentGatewayExecutionRepository>();
        services.AddScoped<IFinanceCloseJournalRepository, FinanceCloseJournalRepository>();
        services.AddScoped<IAccountingPeriodRepository, AccountingPeriodRepository>();
        services.AddScoped<IReconciliationRepository, ReconciliationRepository>();
        services.AddScoped<IEtaComplianceRepository, EtaComplianceRepository>();
        services.AddScoped<IStatutoryTaxRepository, StatutoryTaxRepository>();
        services.AddScoped<ISalesOrderRepository, SalesOrderRepository>();
        services.AddScoped<ISalesReturnRepository, SalesReturnRepository>();
        services.AddScoped<IDispatchOrderRepository, DispatchOrderRepository>();
        services.AddScoped<IInventoryAdjustmentRepository, InventoryAdjustmentRepository>();
        services.AddScoped<IInventoryStatusControlRepository, InventoryStatusControlRepository>();
        services.AddScoped<IStockCountRepository, StockCountRepository>();
        services.AddScoped<IWarehouseTransferRepository, WarehouseTransferRepository>();
        services.AddScoped<IReplenishmentRuleRepository, ReplenishmentRuleRepository>();
        services.AddScoped<IInventoryMovementReadRepository, InventoryMovementReadRepository>();
        services.AddScoped<IGeneralLedgerReadRepository, GeneralLedgerReadRepository>();
        services.AddScoped<ICoreReportingRepository, CoreReportingRepository>();
        services.AddScoped<ISupplierQuotationRepository, SupplierQuotationRepository>();
        services.AddScoped<IWorkflowReadRepository, WorkflowReadRepository>();
        services.AddScoped<IApplicationHealthService, ApplicationHealthService>();
        services.AddScoped<IAdminUserRepository, AdminUserRepository>();
        services.AddScoped<IAccountingOfficeClientAssignmentRepository, AccountingOfficeClientAssignmentRepository>();
        services.AddScoped<IAccountingOfficeClientRequestRepository, AccountingOfficeClientRequestRepository>();
        services.AddScoped<IAccountingOfficeAuditRepository, AccountingOfficeAuditRepository>();
        services.AddScoped<IAdminUserService, AdminUserService>();
        services.AddScoped<IAccountingOfficeService, AccountingOfficeService>();
        services.AddScoped<IAccountingOfficeClientRequestService, AccountingOfficeClientRequestService>();
        services.AddScoped<IPrivacyGovernanceService, PrivacyGovernanceService>();
        services.AddScoped<IIdentityService, IdentityService>();
        services.AddScoped<IOnboardingAccessProvisioningService, OnboardingAccessProvisioningService>();
        services.AddScoped<IInternalWorkbenchService, InternalWorkbenchService>();
        services.AddScoped<ILocalizationService, LocalizationService>();
        services.AddScoped<IIntegrationEndpointRegistryService, IntegrationEndpointRegistryService>();
        services.AddScoped<IOutboxEventService, OutboxEventService>();
        services.AddScoped<IInboxMessageService, InboxMessageService>();
        services.AddScoped<IDeadLetterService, DeadLetterService>();
        services.AddScoped<INotificationTemplateService, NotificationTemplateService>();
        services.AddScoped<INotificationOrchestrationService, NotificationOrchestrationService>();
        services.AddScoped<IExternalPortalService, ExternalPortalService>();
        services.AddScoped<IPublicOnboardingService, PublicOnboardingService>();
        services.AddScoped<IInternalOnboardingIntakeService, InternalOnboardingIntakeService>();
        services.AddScoped<IPublicOnboardingPolicyService, PublicOnboardingPolicyService>();
        services.AddScoped<IDocumentStorageService, DocumentStorageService>();
        services.AddScoped<IManagedComplianceDocumentUploadService>(_ => new FileSystemManagedComplianceDocumentUploadService(contentRootPath));
        services.AddScoped<IReferenceDataGovernanceService, ReferenceDataGovernanceService>();
        services.AddScoped<IPartyOnboardingService, PartyOnboardingService>();
        services.AddScoped<IOnboardingLeadRepository, OnboardingLeadRepository>();
        services.AddScoped<IOnboardingLeadService, OnboardingLeadService>();
        services.AddScoped<IOnboardingCaseService, OnboardingCaseService>();
        services.AddScoped<IOnboardingReviewService, OnboardingReviewService>();
        services.AddScoped<IOnboardingReviewApprovalGateService, OnboardingReviewApprovalGateService>();
        services.AddScoped<ISupplierProfileService, SupplierProfileService>();
        services.AddScoped<ICustomerProfileService, CustomerProfileService>();
        services.AddScoped<IIslamicFinanceFacilityService, IslamicFinanceFacilityService>();
        services.AddScoped<IIslamicFinanceContractTemplateService, IslamicFinanceContractTemplateService>();
        services.AddScoped<IIslamicFinanceMurabahaDisbursementService, IslamicFinanceMurabahaDisbursementService>();
        services.AddScoped<IIslamicFinanceSettlementService, IslamicFinanceSettlementService>();
        services.AddScoped<IIslamicFinanceMurabahaAssetService, IslamicFinanceMurabahaAssetService>();
        services.AddScoped<IIslamicFinanceMurabahaAccountingHookService, IslamicFinanceMurabahaAccountingHookService>();
        services.AddScoped<IIslamicFinanceMurabahaAssetEvidenceService, IslamicFinanceMurabahaAssetEvidenceService>();
        services.AddScoped<IIslamicFinanceMurabahaContractService, IslamicFinanceMurabahaContractService>();
        services.AddScoped<IMurabahaCaseService, MurabahaCaseService>();
        services.AddScoped<IIslamicFinancePartnerService, IslamicFinancePartnerService>();
        services.AddScoped<IIslamicFinanceProductService, IslamicFinanceProductService>();
        services.AddScoped<IReceivablesFinanceService, ReceivablesFinanceService>();
        services.AddScoped<IIslamicFinanceRequestService, IslamicFinanceRequestService>();
        services.AddScoped<IShariahReviewService, ShariahReviewService>();
        services.AddScoped<IPurchaseRequisitionService, PurchaseRequisitionService>();
        services.AddScoped<IRfqEvaluationService, RfqEvaluationService>();
        services.AddScoped<IPurchaseOrderService, PurchaseOrderService>();
        services.AddScoped<IGoodsReceiptService, GoodsReceiptService>();
        services.AddScoped<IPurchaseReturnService, PurchaseReturnService>();
        services.AddScoped<IAccountsPayableBillService, AccountsPayableBillService>();
        services.AddScoped<IAccountsPayablePaymentService, AccountsPayablePaymentService>();
        services.AddScoped<IBankTransferBatchService, BankTransferBatchService>();
        services.AddScoped<IPaymentSettlementBatchService, PaymentSettlementBatchService>();
        services.AddScoped<ICashAccountService, CashAccountService>();
        services.AddScoped<ITreasuryTransferService, TreasuryTransferService>();
        services.AddScoped<IForeignExchangeQuoteService, ForeignExchangeQuoteService>();
        services.AddScoped<IForeignExchangeOverrideService, ForeignExchangeOverrideService>();
        services.AddScoped<IForeignExchangeRevaluationService, ForeignExchangeRevaluationService>();
        services.AddScoped<ICardTokenReferenceService, CardTokenReferenceService>();
        services.AddScoped<IPaymentChannelConfigurationService, PaymentChannelConfigurationService>();
        services.AddScoped<IGatewayCallbackService, GatewayCallbackService>();
        services.AddScoped<IWalletRuleService, WalletRuleService>();
        services.AddScoped<IAccountingRuleService, AccountingRuleService>();
        services.AddScoped<ICollectionsWorkbenchService, CollectionsWorkbenchService>();
        services.AddScoped<ICustomerStatementService, CustomerStatementService>();
        services.AddScoped<ISupplierStatementService, SupplierStatementService>();
        services.AddScoped<ISupplierAccountReconciliationService, SupplierAccountReconciliationService>();
        services.AddScoped<IPricingRuleService, PricingRuleService>();
        services.AddScoped<IAccountsReceivableInvoiceService, AccountsReceivableInvoiceService>();
        services.AddScoped<IAccountsReceivableReceiptService, AccountsReceivableReceiptService>();
        services.AddScoped<ICustomerRefundService, CustomerRefundService>();
        services.AddScoped<IPaymentGatewayExecutionService, PaymentGatewayExecutionService>();
        services.AddScoped<IFinanceCloseJournalService, FinanceCloseJournalService>();
        services.AddScoped<IAccountingPeriodService, AccountingPeriodService>();
        services.AddScoped<IReconciliationService, ReconciliationService>();
        services.AddScoped<IEtaComplianceService, EtaComplianceService>();
        services.AddScoped<IEtaAuthorityAuthService, EtaAuthorityAuthService>();
        services.AddScoped<IEtaAuthorityClient, EtaAuthorityClient>();
        services.AddScoped<IEtaAuthorityIntegrationService, EtaAuthorityIntegrationService>();
        services.AddScoped<IEtaAuthorityCallbackService, EtaAuthorityCallbackService>();
        services.AddScoped<IEtaNotificationOperationsService, EtaNotificationOperationsService>();
        services.AddScoped<IStatutoryTaxService, StatutoryTaxService>();
        services.AddScoped<ISalesOrderService, SalesOrderService>();
        services.AddScoped<ISalesReturnService, SalesReturnService>();
        services.AddScoped<IDispatchOrderService, DispatchOrderService>();
        services.AddScoped<IInventoryAdjustmentService, InventoryAdjustmentService>();
        services.AddScoped<IInventoryStatusControlService, InventoryStatusControlService>();
        services.AddScoped<IStockCountService, StockCountService>();
        services.AddScoped<IWarehouseTransferService, WarehouseTransferService>();
        services.AddScoped<IReplenishmentRuleService, ReplenishmentRuleService>();
        services.AddScoped<IInventoryMovementService, InventoryMovementService>();
        services.AddScoped<IGeneralLedgerService, GeneralLedgerService>();
        services.AddScoped<ICoreReportingService, CoreReportingService>();
        services.AddScoped<IRfqService, RfqService>();
        services.AddScoped<ISupplierQuotationService, SupplierQuotationService>();
        services.AddScoped<IWorkflowService, WorkflowService>();
        return services;
    }

    private static string ResolveSqliteConnectionString(string connectionString, string contentRootPath)
    {
        const string prefix = "Data Source=";
        if (!connectionString.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
        {
            return connectionString;
        }

        var rawPath = connectionString[prefix.Length..].Trim();
        if (string.IsNullOrWhiteSpace(rawPath))
        {
            return connectionString;
        }

        if (Path.IsPathRooted(rawPath))
        {
            Directory.CreateDirectory(Path.GetDirectoryName(rawPath)!);
            return $"{prefix}{rawPath}";
        }

        var absolutePath = Path.GetFullPath(rawPath, contentRootPath);
        Directory.CreateDirectory(Path.GetDirectoryName(absolutePath)!);
        return $"{prefix}{absolutePath}";
    }
}
