package manager

import (
	"context"
	"net/http"
	"sync"

	"github.com/google/uuid"
	"github.com/packethost/packngo"
)

// fakequinix implements a wrapngo.Client for testing. It starts out with a
// number of made up hardware reservations, and allows for creating devices and
// SSH keys.
type fakequinix struct {
	mu sync.Mutex

	pid          string
	devices      map[string]*packngo.Device
	reservations map[string]*packngo.HardwareReservation
	sshKeys      map[string]*packngo.SSHKey
}

// newFakequinix makes a fakequinix with a given fake project ID and number of
// hardware reservations to create.
func newFakequinix(pid string, numReservations int) *fakequinix {
	f := fakequinix{
		pid:          pid,
		devices:      make(map[string]*packngo.Device),
		reservations: make(map[string]*packngo.HardwareReservation),
		sshKeys:      make(map[string]*packngo.SSHKey),
	}

	for i := 0; i < numReservations; i++ {
		uid := uuid.New()
		f.reservations[uid.String()] = &packngo.HardwareReservation{
			ID:            uid.String(),
			ShortID:       uid.String(),
			Provisionable: true,
		}
	}

	return &f
}

func (f *fakequinix) notFound() error {
	return &packngo.ErrorResponse{
		Response: &http.Response{
			StatusCode: http.StatusNotFound,
		},
	}
}

func (f *fakequinix) GetDevice(_ context.Context, pid, did string) (*packngo.Device, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	if pid != f.pid {
		return nil, f.notFound()
	}
	val := f.devices[did]
	if val == nil {
		return nil, f.notFound()
	}
	return val, nil
}

func (f *fakequinix) ListDevices(_ context.Context, pid string) ([]packngo.Device, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	if pid != f.pid {
		return nil, nil
	}
	var res []packngo.Device
	for _, dev := range f.devices {
		res = append(res, *dev)
	}
	return res, nil
}

func (f *fakequinix) CreateDevice(_ context.Context, request *packngo.DeviceCreateRequest) (*packngo.Device, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	rid := request.HardwareReservationID
	res := f.reservations[rid]
	if res == nil {
		return nil, f.notFound()
	}
	if res.Device != nil {
		return nil, f.notFound()
	}

	dev := &packngo.Device{
		ID:       uuid.New().String(),
		State:    "very fake",
		Hostname: request.Hostname,
		OS: &packngo.OS{
			Name: request.OS,
			Slug: request.OS,
		},
	}
	res.Device = dev
	res.Provisionable = false

	f.devices[dev.ID] = dev
	return dev, nil
}

func (f *fakequinix) ListReservations(_ context.Context, pid string) ([]packngo.HardwareReservation, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	var res []packngo.HardwareReservation
	for _, r := range f.reservations {
		res = append(res, *r)
	}

	return res, nil
}

func (f *fakequinix) ListSSHKeys(_ context.Context) ([]packngo.SSHKey, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	var res []packngo.SSHKey
	for _, key := range f.sshKeys {
		res = append(res, *key)
	}

	return res, nil
}

func (f *fakequinix) CreateSSHKey(_ context.Context, req *packngo.SSHKeyCreateRequest) (*packngo.SSHKey, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	for _, k := range f.sshKeys {
		if k.Key == req.Key {
			return nil, f.notFound()
		}
		if k.Label == req.Label {
			return nil, f.notFound()
		}
	}

	uid := uuid.New().String()
	f.sshKeys[uid] = &packngo.SSHKey{
		ID:    uid,
		Label: req.Label,
		Key:   req.Key,
	}

	return f.sshKeys[uid], nil
}

func (f *fakequinix) UpdateSSHKey(_ context.Context, kid string, req *packngo.SSHKeyUpdateRequest) (*packngo.SSHKey, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	key := f.sshKeys[kid]
	if key == nil {
		return nil, f.notFound()
	}
	key.Key = *req.Key

	return key, nil
}

func (f *fakequinix) Close() {
}
