package bootstrap

import (
	"github.com/break/junhong_cmp_fiber/internal/handler/admin"
	"github.com/break/junhong_cmp_fiber/internal/handler/app"
	authHandler "github.com/break/junhong_cmp_fiber/internal/handler/auth"
	"github.com/break/junhong_cmp_fiber/internal/handler/callback"
	openapiHandler "github.com/break/junhong_cmp_fiber/internal/handler/openapi"
	pollingPkg "github.com/break/junhong_cmp_fiber/internal/polling"
	assetQuery "github.com/break/junhong_cmp_fiber/internal/query/asset"
	exchangeQuery "github.com/break/junhong_cmp_fiber/internal/query/exchange"
	clientOrderSvc "github.com/break/junhong_cmp_fiber/internal/service/client_order"
	pollingSvcPkg "github.com/break/junhong_cmp_fiber/internal/service/polling"
	rechargeOrderSvc "github.com/break/junhong_cmp_fiber/internal/service/recharge_order"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/go-playground/validator/v10"
)

func initHandlers(svc *services, deps *Dependencies) *Handlers {
	validate := validator.New()
	assetWalletStore := postgres.NewAssetWalletStore(deps.DB, deps.Redis)
	packageStore := postgres.NewPackageStore(deps.DB)
	shopPackageAllocationStore := postgres.NewShopPackageAllocationStore(deps.DB)
	iotCardStore := postgres.NewIotCardStore(deps.DB, deps.Redis)
	deviceStore := postgres.NewDeviceStore(deps.DB, deps.Redis)
	assetWalletTransactionStore := postgres.NewAssetWalletTransactionStore(deps.DB, deps.Redis)
	personalCustomerOpenIDStore := postgres.NewPersonalCustomerOpenIDStore(deps.DB)
	personalCustomerStore := postgres.NewPersonalCustomerStore(deps.DB, deps.Redis)
	personalCustomerPhoneStore := postgres.NewPersonalCustomerPhoneStore(deps.DB)
	orderStore := postgres.NewOrderStore(deps.DB, deps.Redis)
	packageSeriesStore := postgres.NewPackageSeriesStore(deps.DB)
	shopSeriesAllocationStore := postgres.NewShopSeriesAllocationStore(deps.DB)
	deviceSimBindingStore := postgres.NewDeviceSimBindingStore(deps.DB, deps.Redis)
	carrierStore := postgres.NewCarrierStore(deps.DB)
	rechargeOrderStore := postgres.NewRechargeOrderStore(deps.DB, deps.Redis)
	paymentStore := postgres.NewPaymentStore(deps.DB, deps.Redis)
	commissionRecordStore := postgres.NewCommissionRecordStore(deps.DB, deps.Redis)
	rechargeOrderService := rechargeOrderSvc.New(
		deps.DB,
		rechargeOrderStore,
		paymentStore,
		assetWalletStore,
		assetWalletTransactionStore,
		iotCardStore,
		deviceStore,
		packageSeriesStore,
		shopSeriesAllocationStore,
		commissionRecordStore,
		deps.QueueClient,
		deps.Logger,
	)
	clientOrderService := clientOrderSvc.New(
		svc.Asset,
		svc.PurchaseValidation,
		orderStore,
		rechargeOrderStore,
		paymentStore,
		assetWalletStore,
		svc.CustomerBinding,
		personalCustomerOpenIDStore,
		personalCustomerStore,
		personalCustomerPhoneStore,
		svc.WechatConfig,
		svc.Order,
		packageSeriesStore,
		shopSeriesAllocationStore,
		iotCardStore,
		deviceStore,
		deps.DB,
		deps.Redis,
		deps.Logger,
	)

	return &Handlers{
		Auth:                        authHandler.NewHandler(svc.Auth, validate),
		Account:                     admin.NewAccountHandler(svc.Account),
		Role:                        admin.NewRoleHandler(svc.Role, validate),
		Permission:                  admin.NewPermissionHandler(svc.Permission),
		PersonalCustomer:            app.NewPersonalCustomerHandler(svc.PersonalCustomer, deps.Logger),
		ClientAuth:                  app.NewClientAuthHandler(svc.ClientAuth, deps.Logger),
		ClientAsset:                 app.NewClientAssetHandler(svc.Asset, svc.CustomerBinding, assetWalletStore, packageStore, shopPackageAllocationStore, iotCardStore, deviceStore, deps.DB, deps.Logger),
		ClientWallet:                app.NewClientWalletHandler(svc.Asset, svc.CustomerBinding, assetWalletStore, assetWalletTransactionStore, rechargeOrderStore, paymentStore, svc.Recharge, personalCustomerOpenIDStore, svc.WechatConfig, deps.Redis, deps.Logger, deps.DB, iotCardStore, deviceStore),
		ClientOrder:                 app.NewClientOrderHandler(clientOrderService, deps.Logger),
		ClientExchange:              app.NewClientExchangeHandler(svc.Exchange),
		ClientRealname:              app.NewClientRealnameHandler(svc.Asset, svc.CustomerBinding, iotCardStore, deviceSimBindingStore, carrierStore, deps.GatewayClient, deps.Logger, svc.PollingManualTrigger),
		ClientDevice:                app.NewClientDeviceHandler(svc.Asset, svc.CustomerBinding, deviceStore, deviceSimBindingStore, iotCardStore, deps.GatewayClient, deps.Logger),
		ClientRechargeOrder:         app.NewClientRechargeOrderHandler(rechargeOrderStore, paymentStore, deps.Logger),
		Shop:                        admin.NewShopHandler(svc.Shop, validate),
		ShopRole:                    admin.NewShopRoleHandler(svc.Shop),
		AdminAuth:                   admin.NewAuthHandler(svc.Auth, validate),
		ShopCommission:              admin.NewShopCommissionHandler(svc.ShopCommission),
		CommissionWithdrawal:        admin.NewCommissionWithdrawalHandler(svc.CommissionWithdrawal, validate),
		CommissionWithdrawalSetting: admin.NewCommissionWithdrawalSettingHandler(svc.CommissionWithdrawalSetting),
		Enterprise:                  admin.NewEnterpriseHandler(svc.Enterprise),
		EnterpriseCard:              admin.NewEnterpriseCardHandler(svc.EnterpriseCard),
		EnterpriseDevice:            admin.NewEnterpriseDeviceHandler(svc.EnterpriseDevice),
		Authorization:               admin.NewAuthorizationHandler(svc.Authorization),
		IotCard:                     admin.NewIotCardHandler(svc.IotCard),
		IotCardImport:               admin.NewIotCardImportHandler(svc.IotCardImport),
		ExportTask:                  admin.NewExportTaskHandler(svc.ExportTask),
		Device:                      admin.NewDeviceHandler(svc.Device),
		DeviceImport:                admin.NewDeviceImportHandler(svc.DeviceImport),
		AssetAllocationRecord:       admin.NewAssetAllocationRecordHandler(svc.AssetAllocationRecord),
		Storage:                     admin.NewStorageHandler(deps.StorageService),
		Carrier:                     admin.NewCarrierHandler(svc.Carrier),
		PackageSeries:               admin.NewPackageSeriesHandler(svc.PackageSeries),
		Package:                     admin.NewPackageHandler(svc.Package),
		PackageUsage:                admin.NewPackageUsageHandler(svc.PackageDailyRecord),
		ShopPackageBatchAllocation:  admin.NewShopPackageBatchAllocationHandler(svc.ShopPackageBatchAllocation),
		ShopPackageBatchPricing:     admin.NewShopPackageBatchPricingHandler(svc.ShopPackageBatchPricing),
		ShopSeriesGrant:             admin.NewShopSeriesGrantHandler(svc.ShopSeriesGrant),
		AdminOrder:                  admin.NewOrderHandler(svc.Order, validate),
		AdminExchange:               admin.NewExchangeHandler(svc.Exchange, exchangeQuery.NewListQuery(deps.DB), validate),
		PaymentCallback:             callback.NewPaymentHandler(svc.Order, svc.Recharge, rechargeOrderService, svc.AgentRecharge, deps.WechatPayment, svc.WechatConfig, paymentStore, deps.Logger),
		PollingConfig:               admin.NewPollingConfigHandler(svc.PollingConfig),
		PollingConcurrency:          admin.NewPollingConcurrencyHandler(svc.PollingConcurrency),
		PollingMonitoring:           admin.NewPollingMonitoringHandler(svc.PollingMonitoring),
		PollingAlert:                admin.NewPollingAlertHandler(svc.PollingAlert),
		PollingCleanup:              admin.NewPollingCleanupHandler(svc.PollingCleanup),
		PollingManualTrigger:        admin.NewPollingManualTriggerHandler(svc.PollingManualTrigger),
		Asset: func() *admin.AssetHandler {
			pollingQueueMgr := pollingPkg.NewPollingQueueManager(deps.Redis, constants.PollingShardCount, deps.Logger)
			assetPollingSvc := pollingSvcPkg.NewAssetPollingService(
				deviceStore,
				deviceSimBindingStore,
				svc.IotCard,
				pollingQueueMgr,
				deps.Logger,
				svc.AssetAudit,
			)
			h := admin.NewAssetHandler(svc.Asset, svc.AssetAudit, svc.Device, svc.IotCard, svc.StopResumeService, assetPollingSvc, assetQuery.NewExchangeTraceQuery(deps.DB, deps.Logger))
			h.SetLifecycleService(svc.AssetLifecycle)
			return h
		}(),
		AssetLifecycle: admin.NewAssetLifecycleHandler(svc.AssetLifecycle),
		AssetWallet: func() *admin.AssetWalletHandler {
			h := admin.NewAssetWalletHandler(svc.AssetWallet)
			h.SetAssetService(svc.Asset)
			return h
		}(),
		WechatConfig:           admin.NewWechatConfigHandler(svc.WechatConfig),
		AgentRecharge:          admin.NewAgentRechargeHandler(svc.AgentRecharge, validate),
		Refund:                 admin.NewRefundHandler(svc.Refund),
		OrderPackageInvalidate: admin.NewOrderPackageInvalidateHandler(svc.OrderPackageInvalidate),
		ClientWechat:           app.NewClientWechatHandler(svc.WechatConfig, deps.Redis, deps.Logger),
		SuperAdmin:             admin.NewSuperAdminHandler(svc.OperationPassword),
		AgentOpenAPI:           openapiHandler.NewHandler(svc.AgentOpenAPI, validate),
	}
}
