package repository

import (
	dbgen "Yimaru-Backend/gen/db"
	"Yimaru-Backend/internal/domain"
	"Yimaru-Backend/internal/ports"
	"context"
	"fmt"

	"go.uber.org/zap"
)

// Interface for creating new setting store
func NewSettingStore(s *Store) ports.SettingStore { return s }

func (s *Store) InsertGlobalSetting(ctx context.Context, setting domain.CreateSetting) error {
	err := s.queries.InsertGlobalSetting(ctx, dbgen.InsertGlobalSettingParams{
		Key:   setting.Key,
		Value: setting.Value,
	})
	if err != nil {
		return err
	}
	return nil
}

func (s *Store) GetGlobalSettingList(ctx context.Context) (domain.SettingList, error) {
	settings, err := s.queries.GetGlobalSettings(ctx)
	if err != nil {
		domain.MongoDBLogger.Error("failed to get all settings", zap.Error(err))
		return domain.SettingList{}, err
	}

	return domain.ConvertDBGlobalSettingList(settings)
}

func (s *Store) GetGlobalSettings(ctx context.Context) ([]domain.Setting, error) {
	settings, err := s.queries.GetGlobalSettings(ctx)

	if err != nil {
		domain.MongoDBLogger.Error("failed to get all settings", zap.Error(err))
	}

	var result []domain.Setting = make([]domain.Setting, 0, len(settings))
	for _, setting := range settings {
		result = append(result, domain.Setting{
			Key:       setting.Key,
			Value:     setting.Value,
			UpdatedAt: setting.UpdatedAt.Time,
		})
	}

	return result, nil
}

func (s *Store) GetGlobalSetting(ctx context.Context, key string) (domain.Setting, error) {
	dbSetting, err := s.queries.GetGlobalSetting(ctx, key)

	if err != nil {
		domain.MongoDBLogger.Error("failed to get all settings", zap.Error(err))
	}

	result := domain.Setting{
		Key:       dbSetting.Key,
		Value:     dbSetting.Value,
		UpdatedAt: dbSetting.UpdatedAt.Time,
	}

	return result, nil
}

func (s *Store) UpdateGlobalSetting(ctx context.Context, key, value string) error {
	err := s.queries.UpdateGlobalSetting(ctx, dbgen.UpdateGlobalSettingParams{
		Key:   key,
		Value: value,
	})

	if err != nil {
		domain.MongoDBLogger.Error("failed to update setting",
			zap.String("key", key),
			zap.String("value", value),
			zap.Error(err),
		)

		return err
	}

	return err

}

func (s *Store) UpdateGlobalSettingList(ctx context.Context, settingList domain.ValidSettingList) error {
	convertedSettings := settingList.ConvertAllSettings()

	for _, setting := range convertedSettings {
		err := s.UpdateGlobalSetting(ctx, setting.Key, setting.Value)
		if err != nil {
			domain.MongoDBLogger.Warn("failed to update setting list", zap.String("key", setting.Key), zap.Error(err))
			return err
		}
	}
	return nil
}

// func (s *Store) GetOverrideSettings(ctx context.Context, companyID int64) ([]domain.Setting, error) {
// 	settings, err := s.queries.GetOverrideSettings(ctx, companyID)

// 	if err != nil {
// 		return nil, err
// 	}

// 	result := make([]domain.Setting, 0, len(settings))
// 	for _, setting := range settings {
// 		result = append(result, domain.Setting{
// 			Key:       setting.Key,
// 			Value:     setting.Value,
// 			UpdatedAt: setting.UpdatedAt.Time,
// 		})
// 	}

// 	return result, nil
// }

// func (s *Store) GetOverrideSettingsList(ctx context.Context, companyID int64) (domain.SettingList, error) {
// 	settings, err := s.queries.GetOverrideSettings(ctx, companyID)

// 	if err != nil {
// 		return domain.SettingList{}, err
// 	}

// 	return domain.ConvertDBOverrideSettingList(settings)
// }

// func (s *Store) DeleteCompanySetting(ctx context.Context, companyID int64, key string) error {
// 	return s.queries.DeleteCompanySetting(ctx, dbgen.DeleteCompanySettingParams{
// 		CompanyID: companyID,
// 		Key:       key,
// 	})
// }
// func (s *Store) DeleteAllCompanySetting(ctx context.Context, companyID int64) error {
// 	return s.queries.DeleteAllCompanySetting(ctx, companyID)
// }

func (s *Store) EnsureAllSettingsExist(ctx context.Context) error {
	defaultSettings := domain.NewDefaultSettingList().ToSettingArray() // returns []domain.Setting from your typed struct

	dbSettings, err := s.GetGlobalSettings(ctx)
	if err != nil {
		return fmt.Errorf("failed to fetch settings: %w", err)
	}

	existing := map[string]struct{}{}
	for _, s := range dbSettings {
		existing[s.Key] = struct{}{}
	}

	for _, setting := range defaultSettings {
		if _, found := existing[setting.Key]; !found {
			if err := s.InsertGlobalSetting(ctx, domain.CreateSetting{
				Key:   setting.Key,
				Value: setting.Value,
			}); err != nil {
				return fmt.Errorf("failed to create missing setting %q: %w", setting.Key, err)
			}
		}
	}

	return nil
}
