package modules

import (
	"context"

	depthandler "security-center-backend/internal/modules/department/handler"
	depository "security-center-backend/internal/modules/department/repository"
	depservice "security-center-backend/internal/modules/department/service"
	employeehandler "security-center-backend/internal/modules/employee/handler"
	"security-center-backend/internal/pkg/logger"
	"security-center-backend/internal/repository"
	settingsservice "security-center-backend/internal/service/settings"
)

type DepartmentModule struct {
	Handler               *depthandler.Handler
	EmployeeHandler       *employeehandler.Handler
	StopHooks             []StopHook
	Configure             func(settings *settingsservice.Service)
	RuntimeStatusProvider func() depservice.RuntimeStatus
}

type DepartmentBuildInput struct {
	DepartmentRepo depository.DepartmentRepository
	EmployeeRepo   depository.EmployeeRepository
	OrgSyncRunRepo depository.OrgSyncRunRepository
	UserRepo       repository.UserRepository
	Settings       *settingsservice.Service
	Logger         *logger.Logger
}

func BuildDepartment(input DepartmentBuildInput) *DepartmentModule {
	if input.DepartmentRepo == nil {
		return &DepartmentModule{}
	}

	deptSvc := depservice.NewDepartmentService(input.DepartmentRepo, input.EmployeeRepo, input.OrgSyncRunRepo, input.Logger)
	runtime := depservice.NewOrgSyncRuntimeControl(deptSvc, input.Logger)

	module := &DepartmentModule{
		Handler:         depthandler.New(deptSvc, runtime, input.Settings),
		EmployeeHandler: employeehandler.New(deptSvc, runtime, input.UserRepo),
		StopHooks: []StopHook{
			func(ctx context.Context) error {
				runtime.Stop()
				return nil
			},
		},
		Configure: func(settings *settingsservice.Service) {
			if settings == nil {
				return
			}

			ctx := context.Background()
			snapshot, err := settings.Get(ctx)
			if err == nil {
				runtime.SetFreshnessPolicy(freshnessPolicyFromSettings(snapshot.DataSync))
			}
			if err == nil && snapshot.DataSync.OrgSyncEnabled {
				if snapshot.DataSync.LarkAppID != "" && snapshot.DataSync.LarkAppSecret != "" {
					_, _ = runtime.Start(
						snapshot.DataSync.OrgSyncCron,
						snapshot.DataSync.LarkAppID,
						snapshot.DataSync.LarkAppSecret,
					)
				}
			}

			settings.SetOrgSyncReconfigurer(func(dataSync settingsservice.DataSyncSettings) error {
				runtime.SetFreshnessPolicy(freshnessPolicyFromSettings(dataSync))
				if !dataSync.OrgSyncEnabled || dataSync.LarkAppID == "" || dataSync.LarkAppSecret == "" {
					runtime.Stop()
					return nil
				}
				_, err := runtime.Reconfigure(dataSync.OrgSyncCron, dataSync.LarkAppID, dataSync.LarkAppSecret)
				return err
			})
		},
		RuntimeStatusProvider: runtime.Status,
	}

	return module
}

func freshnessPolicyFromSettings(dataSync settingsservice.DataSyncSettings) depservice.FreshnessPolicy {
	return depservice.NormalizeFreshnessPolicy(depservice.FreshnessPolicy{
		StaleAfterHours:   dataSync.OrgSyncStaleAfterHours,
		ExpiredAfterHours: dataSync.OrgSyncExpiredAfterHours,
	})
}
