package extension

import (
	"fmt"

	"github.com/hiddify/hiddify-core/v2/db"
	"github.com/sagernet/sing-box/log"

	"github.com/hiddify/hiddify-core/v2/service_manager"
)

var (
	allExtensionsMap     = make(map[string]ExtensionFactory)
	enabledExtensionsMap = make(map[string]*Extension)
)

func RegisterExtension(factory ExtensionFactory) error {
	if _, ok := allExtensionsMap[factory.Id]; ok {
		err := fmt.Errorf("Extension with ID %s already exists", factory.Id)
		log.Warn(err)
		return err
	}

	table := db.GetTable[extensionData]()
	data, err := table.Get(factory.Id)
	if data == nil || err != nil {
		log.Warn("Data of Extension ", factory.Id, " not found, creating new one")
		data = &extensionData{Id: factory.Id, Enable: false}
		if err := table.UpdateInsert(data); err != nil {
			log.Warn("Failed to create new extension data: ", err, " ", factory.Id)
			return err
		}
	}

	allExtensionsMap[factory.Id] = factory

	return nil
}

func isEnable(id string) bool {
	table := db.GetTable[extensionData]()
	extdata, err := table.Get(id)
	if err != nil {
		return false
	}
	return extdata.Enable
}

func loadExtension(factory ExtensionFactory) error {
	if !isEnable(factory.Id) {
		return fmt.Errorf("Extension with ID %s is not enabled", factory.Id)
	}
	extension := factory.Builder()
	extension.init(factory.Id)

	// fmt.Printf("Registered extension: %+v\n", extension)
	enabledExtensionsMap[factory.Id] = &extension

	return nil
}

type extensionService struct {
	// Storage *CacheFile
}

func (s *extensionService) Start() error {
	table := db.GetTable[extensionData]()
	extdata, err := table.All()
	if err != nil {
		// Extensions are optional, skip if database not available
		return nil
	}
	for _, data := range extdata {
		if !data.Enable {
			continue
		}
		if factory, ok := allExtensionsMap[data.Id]; ok {
			if err := loadExtension(factory); err != nil {
				return fmt.Errorf("failed to load extension %s: %w", data.Id, err)
			}
		} else {
			return fmt.Errorf("extension %s is enabled but not found", data.Id)
		}
	}
	return nil
}

func (s *extensionService) Close() error {
	for _, extension := range enabledExtensionsMap {
		if err := (*extension).Close(); err != nil {
			return err
		}
	}
	return nil
}

func init() {
	service_manager.Register(&extensionService{})
}
