package transfers

import (
	"context"
	"fmt"

	"github.com/go-playground/validator/v10"
	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"

	commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
	commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
	expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
	expenseService "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/services"
	rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
	rStockTransfer "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/repositories"
	sTransfer "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/transfers/services"
	rKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
	rNonstock "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/repositories"
	rSupplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
	rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
	rProjectFlockKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
	rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
	rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
	sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
	"gitlab.com/mbugroup/lti-api.git/internal/utils"
)

type TransferModule struct{}

func (TransferModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
	stockTransferRepo := rStockTransfer.NewStockTransferRepository(db)
	stockTransferDetailRepo := rStockTransfer.NewStockTransferDetailRepository(db)
	stockTransferDeliveryRepo := rStockTransfer.NewStockTransferDeliveryRepository(db)
	StockTransferDeliveryItemRepo := rStockTransfer.NewStockTransferDeliveryItemRepository(db)
	stockLogsRepo := rStockLogs.NewStockLogRepository(db)
	supplierRepo := rSupplier.NewSupplierRepository(db)
	productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
	userRepo := rUser.NewUserRepository(db)
	warehouseRepo := rWarehouse.NewWarehouseRepository(db)
	projectFlockKandangRepo := rProjectFlockKandang.NewProjectFlockKandangRepository(db)
	projectFlockPopulationRepo := rProjectFlockKandang.NewProjectFlockPopulationRepository(db)
	kandangRepo := rKandang.NewKandangRepository(db)
	nonstockRepo := rNonstock.NewNonstockRepository(db)
	documentRepo := commonRepo.NewDocumentRepository(db)
	expenseRepository := expenseRepo.NewExpenseRepository(db)
	expenseRealizationRepo := expenseRepo.NewExpenseRealizationRepository(db)

	documentSvc, err := commonSvc.NewDocumentServiceFromConfig(context.Background(), documentRepo)
	if err != nil {
		panic(err)
	}

	approvalRepo := commonRepo.NewApprovalRepository(db)
	approvalSvc := commonSvc.NewApprovalService(approvalRepo)
	if err := approvalSvc.RegisterWorkflowSteps(utils.ApprovalWorkflowExpense, utils.ExpenseApprovalSteps); err != nil {
		panic(fmt.Sprintf("failed to register expense approval workflow: %v", err))
	}

	expenseServiceInstance := expenseService.NewExpenseService(
		expenseRepository,
		supplierRepo,
		nonstockRepo,
		approvalSvc,
		expenseRealizationRepo,
		projectFlockKandangRepo,
		documentSvc,
		validate,
	)

	fifoStockV2Service := commonSvc.NewFifoStockV2Service(db, utils.Log)
	expenseBridge := sTransfer.NewTransferExpenseBridge(
		db,
		stockTransferRepo,
		projectFlockKandangRepo,
		kandangRepo,
		expenseServiceInstance,
	)

	transferService := sTransfer.NewTransferService(validate, stockTransferRepo, stockTransferDetailRepo, stockTransferDeliveryRepo, StockTransferDeliveryItemRepo, stockLogsRepo, productWarehouseRepo, supplierRepo, warehouseRepo, projectFlockKandangRepo, projectFlockPopulationRepo, documentSvc, fifoStockV2Service, expenseBridge)
	userService := sUser.NewUserService(userRepo, validate)

	TransferRoutes(router, userService, transferService)
}
