package management

import (
	"fmt"
	d "playback-device-server/data"
	"slices"

	gonanoid "github.com/matoous/go-nanoid"
)

type DeviceManager struct {
	deviceDatabase    *d.DeviceDatabase
	registrationCodes []string
}

func (dm *DeviceManager) Initialize(deviceDatabase *d.DeviceDatabase) error {
	dm.deviceDatabase = deviceDatabase
	return nil
}

func (dm *DeviceManager) CreateDevice(device *d.PlaybackDevice) (string, error) {
	id, error := dm.deviceDatabase.CreateDevice(device.Name, device.Description)
	if error != nil {
		return "", error
	}
	return id, nil
}

func (dm *DeviceManager) DeviceIdExists(id string) (bool, error) {
	exists, error := dm.deviceDatabase.DeviceIdExists(id)
	if error != nil {
		return false, error
	}
	return exists, nil
}

//func (dm *DeviceManager) Register(code string) (string, error) {
//	device, error := dm.GetDeviceByCode(code)
//	if error != nil {
//		return "", error
//	}
//
//	expiryDate := time.Now().AddDate(0, 0, 30)
//	token, error := dm.deviceDatabase.CreateSession(device.ID, expiryDate)
//	if error != nil {
//		return "", error
//	}
//
//	return token, nil
//}

func (dm *DeviceManager) GetDeviceById(id string) (*d.PlaybackDevice, error) {
	device, error := dm.deviceDatabase.GetDeviceById(id)
	if error != nil {
		return nil, error
	}
	return device, nil
}

func (dm *DeviceManager) UpdateDevice(device *d.PlaybackDevice) error {
	error := dm.deviceDatabase.UpdateDevice(device)
	return error
}

func (dm *DeviceManager) GetDevices() (*[]d.PlaybackDevice, error) {
	users, error := dm.deviceDatabase.GetDevices()
	return users, error
}

func (dm *DeviceManager) DeleteDevice(ID string) error {
	error := dm.deviceDatabase.DeleteDevice(ID)
	return error
}

func (dm *DeviceManager) GetRegistrationCode() (string, error) {
	code := dm.createCode()
	return code, nil
}

func (dm *DeviceManager) CreateIntegration(name, code string) (d.Integration, error) {
	exists, err := dm.deviceDatabase.IntegrationNameExists(name)
	if err != nil {
		return d.Integration{}, err
	}
	if exists {
		return d.Integration{}, fmt.Errorf("Integration name already exists")
	}

	if err := dm.redeemCode(code); err != nil {
		return d.Integration{}, err
	}

	token, err := gonanoid.Nanoid(16)
	if err != nil {
		return d.Integration{}, err
	}

	id, err := dm.deviceDatabase.CreateIntegration(name, token)
	if err != nil {
		return d.Integration{}, err
	}

	integration := d.Integration{
		ID:    id,
		Name:  name,
		Token: token,
	}

	return integration, nil
}

func (dm *DeviceManager) GetIntegration(id string) (*d.Integration, error) {
	integration, err := dm.deviceDatabase.GetIntegration(id)
	if err != nil {
		return nil, err
	}
	return integration, nil
}

func (dm *DeviceManager) GetIntegrations() ([]d.Integration, error) {
	integrations, err := dm.deviceDatabase.GetIntegrations()
	if err != nil {
		return nil, err
	}
	return integrations, nil
}

func (dm *DeviceManager) GetIntegrationByToken(token string) (*d.Integration, error) {
	integration, err := dm.deviceDatabase.GetIntegrationByToken(token)
	if err != nil {
		return nil, err
	}
	return integration, nil
}

func (dm *DeviceManager) DeleteIntegration(id string) error {
	error := dm.deviceDatabase.DeleteIntegration(id)
	return error
}

func (dm *DeviceManager) IntegrationIdExists(id string) (bool, error) {
	exists, error := dm.deviceDatabase.IntegrationIdExists(id)
	if error != nil {
		return false, error
	}
	return exists, nil
}

func (dm *DeviceManager) checkCode(code string) bool {
	for _, c := range dm.registrationCodes {
		if c == code {
			return true
		}
	}
	return false
}

func (dm *DeviceManager) createCode() string {
	code := gonanoid.MustGenerate("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 6)
	dm.registrationCodes = append(dm.registrationCodes, code)
	return code
}

func (dm *DeviceManager) redeemCode(code string) error {
	if !dm.checkCode(code) {
		return fmt.Errorf("Invalid registration code")
	}

	for i, c := range dm.registrationCodes {
		if c == code {
			dm.registrationCodes = slices.Delete(dm.registrationCodes, i, i+1)
			break
		}
	}

	return nil
}
