package system

import (
	"context"
	"encoding/json"
	"errors"
	"kra/internal/config"
)

var ErrTaskRuntimeReload = errors.New("task runtime reload failed")

type TaskRuntimeReloadError struct{ Err error }

func (e *TaskRuntimeReloadError) Error() string {
	if e == nil || e.Err == nil {
		return ErrTaskRuntimeReload.Error()
	}
	return e.Err.Error()
}
func (e *TaskRuntimeReloadError) Is(target error) bool { return target == ErrTaskRuntimeReload }
func (e *TaskRuntimeReloadError) Unwrap() error {
	if e == nil {
		return nil
	}
	return e.Err
}

type DatabaseConfig struct {
	Driver, Host, Port, User, Password, Name, Path, Config, Template, AdminPassword string
	APIs                                                                            []*API
}

type InitializationRepo interface {
	IsInitialized(context.Context) (bool, error)
	Initialize(context.Context, *DatabaseConfig) error
	PersistConfig(context.Context) error
	PersistRuntimeConfig(context.Context, *config.Config) error
	ReloadConfig(context.Context) error
	ConfigurationJSON() (json.RawMessage, error)
	SaveConfigurationJSON(context.Context, json.RawMessage) error
	DiskMountPoints() []string
}

// TaskReloader is the narrow scheduler boundary needed after configuration
// changes. The consumer owns this interface; worker supplies the implementation.
type TaskReloader interface {
	Reload(context.Context) error
}

type SystemConfigUsecase struct {
	repo  InitializationRepo
	tasks TaskReloader
	info  SystemInfoProvider
}

func NewSystemConfigUsecase(repo InitializationRepo, tasks TaskReloader, info SystemInfoProvider) *SystemConfigUsecase {
	return &SystemConfigUsecase{repo: repo, tasks: tasks, info: info}
}

func (uc *SystemConfigUsecase) IsInitialized(ctx context.Context) (bool, error) {
	if uc == nil || uc.repo == nil {
		return false, errors.New("系统初始化服务未就绪")
	}
	return uc.repo.IsInitialized(ctx)
}
func (uc *SystemConfigUsecase) Initialize(ctx context.Context, config *DatabaseConfig) error {
	if uc == nil || uc.repo == nil {
		return errors.New("系统初始化服务未就绪")
	}
	if config == nil {
		return errors.New("数据库初始化参数无效")
	}
	if err := uc.repo.Initialize(ctx, config); err != nil {
		return err
	}
	if uc.tasks == nil {
		return &TaskRuntimeReloadError{Err: errors.New("任务调度服务未就绪")}
	}
	if err := uc.tasks.Reload(ctx); err != nil {
		return &TaskRuntimeReloadError{Err: err}
	}
	return nil
}
func (uc *SystemConfigUsecase) PersistConfig(ctx context.Context) error {
	if uc == nil || uc.repo == nil {
		return errors.New("系统配置服务未就绪")
	}
	return uc.repo.PersistConfig(ctx)
}
func (uc *SystemConfigUsecase) PersistRuntimeConfig(ctx context.Context, value *config.Config) error {
	if uc == nil || uc.repo == nil {
		return errors.New("系统配置服务未就绪")
	}
	return uc.repo.PersistRuntimeConfig(ctx, value)
}
func (uc *SystemConfigUsecase) ReloadConfig(ctx context.Context) error {
	if uc == nil || uc.repo == nil {
		return errors.New("系统配置服务未就绪")
	}
	if err := uc.repo.ReloadConfig(ctx); err != nil {
		return err
	}
	if uc.tasks == nil {
		return &TaskRuntimeReloadError{Err: errors.New("任务调度服务未就绪")}
	}
	if err := uc.tasks.Reload(ctx); err != nil {
		return &TaskRuntimeReloadError{Err: err}
	}
	return nil
}

func (uc *SystemConfigUsecase) ConfigurationJSON() (json.RawMessage, error) {
	if uc == nil || uc.repo == nil {
		return nil, errors.New("系统配置服务未就绪")
	}
	return uc.repo.ConfigurationJSON()
}

func (uc *SystemConfigUsecase) SaveConfigurationJSON(ctx context.Context, value json.RawMessage) error {
	if uc == nil || uc.repo == nil {
		return errors.New("系统配置服务未就绪")
	}
	return uc.repo.SaveConfigurationJSON(ctx, value)
}

func (uc *SystemConfigUsecase) DiskMountPoints() []string {
	if uc == nil || uc.repo == nil {
		return nil
	}
	return uc.repo.DiskMountPoints()
}

func (uc *SystemConfigUsecase) ServerInfo(ctx context.Context) (*ServerInfo, error) {
	if uc == nil || uc.repo == nil || uc.info == nil {
		return nil, errors.New("系统信息服务未就绪")
	}
	return uc.info.Collect(ctx, uc.repo.DiskMountPoints())
}
