package main

import (
	"context"
	"fmt"
	"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
	reboots      map[string]int
}

// 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),
		reboots:      make(map[string]int),
	}

	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.ListOptions) (*packngo.Device, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	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) UpdateDevice(ctx context.Context, id string, r *packngo.DeviceUpdateRequest) (*packngo.Device, error) {
	return nil, fmt.Errorf("not implemented")
}

// MoveReservation is not implemented in fakequinix
func (f *fakequinix) MoveReservation(_ context.Context, hardwareReservationDID, projectID string) (*packngo.HardwareReservation, error) {
	return nil, &packngo.ErrorResponse{
		Response: &http.Response{
			StatusCode: http.StatusNotImplemented,
		},
	}
}

func (f *fakequinix) DeleteDevice(_ context.Context, id string) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	if _, ok := f.devices[id]; !ok {
		return f.notFound()
	}

	delete(f.devices, id)

	return 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: "active",
		HardwareReservation: &packngo.HardwareReservation{
			ID: rid,
		},
		Network: []*packngo.IPAddressAssignment{
			{
				IpAddressCommon: packngo.IpAddressCommon{
					Public:  true,
					Address: "1.2.3.4",
				},
			},
		},
		Facility: &packngo.Facility{
			Code: "wad",
		},
		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) RebootDevice(_ context.Context, did string) error {
	f.mu.Lock()
	defer f.mu.Unlock()

	f.reboots[did]++

	return nil
}

func (f *fakequinix) Close() {
}
