package main

import (
	"context"
	"database/sql"
	"fmt"
	"net/netip"

	"k8s.io/klog/v2"

	"source.monogon.dev/cloud/bmaas/bmdb"
	"source.monogon.dev/cloud/bmaas/bmdb/model"
	"source.monogon.dev/cloud/shepherd"
)

// provider represents a shepherd.Provider that works entirely on a
// static device list. It requires a provider type and a device list.
type provider struct {
	providerType model.Provider
	machines     map[shepherd.ProviderID]machine
}

type machine struct {
	ProviderID shepherd.ProviderID `json:"ID"`
	Address    netip.Addr          `json:"Addr"`
	Location   string              `json:"Location"`
}

func (d machine) Failed() bool {
	return false
}

func (d machine) ID() shepherd.ProviderID {
	return d.ProviderID
}

func (d machine) Addr() netip.Addr {
	return d.Address
}

func (d machine) Availability() shepherd.Availability {
	return shepherd.AvailabilityPossiblyUsed
}

func (p *provider) ListMachines(ctx context.Context) ([]shepherd.Machine, error) {
	machines := make([]shepherd.Machine, 0, len(p.machines))
	for _, m := range p.machines {
		machines = append(machines, m)
	}

	return machines, nil
}

func (p *provider) GetMachine(ctx context.Context, id shepherd.ProviderID) (shepherd.Machine, error) {
	// If the provided machine is not inside our known machines,
	// bail-out early as this is unsupported.
	if _, ok := p.machines[id]; !ok {
		return nil, fmt.Errorf("unknown provided machine requested")
	}

	return p.machines[id], nil
}

func (p *provider) CreateMachine(ctx context.Context, session *bmdb.Session, request shepherd.CreateMachineRequest) (shepherd.Machine, error) {
	if request.UnusedMachine == nil {
		return nil, fmt.Errorf("parameter UnusedMachine is missing")
	}

	//TODO: Do we just trust the implementation to be correct?
	m, ok := request.UnusedMachine.(machine)
	if !ok {
		return nil, fmt.Errorf("invalid type for parameter UnusedMachine")
	}

	if err := p.assimilate(ctx, session, m); err != nil {
		klog.Errorf("Failed to provision machine %s: %v", m.ProviderID, err)
		return nil, err
	}

	return m, nil
}

func (p *provider) assimilate(ctx context.Context, sess *bmdb.Session, machine machine) error {
	return sess.Transact(ctx, func(q *model.Queries) error {
		// Create a new machine record within BMDB.
		m, err := q.NewMachine(ctx)
		if err != nil {
			return fmt.Errorf("while creating a new machine record in BMDB: %w", err)
		}

		// Link the new machine with the device, and tag it "provided".
		addParams := model.MachineAddProvidedParams{
			MachineID:  m.MachineID,
			ProviderID: string(machine.ProviderID),
			Provider:   p.providerType,
		}
		klog.Infof("Setting \"provided\" tag (ID: %s, PID: %s, Provider: %s).", addParams.MachineID, addParams.ProviderID, addParams.Provider)
		if err := q.MachineAddProvided(ctx, addParams); err != nil {
			return fmt.Errorf("while tagging machine active: %w", err)
		}

		upParams := model.MachineUpdateProviderStatusParams{
			ProviderID: string(machine.ProviderID),
			Provider:   p.providerType,
			ProviderIpAddress: sql.NullString{
				String: machine.Address.String(),
				Valid:  true,
			},
			ProviderLocation: sql.NullString{
				String: machine.Location,
				Valid:  machine.Location != "",
			},
			ProviderStatus: model.NullProviderStatus{
				ProviderStatus: model.ProviderStatusUnknown,
				Valid:          true,
			},
		}

		klog.Infof("Setting \"provided\" tag status parameter (ID: %s, PID: %s, Provider: %s).", addParams.MachineID, upParams.ProviderID, upParams.Provider)
		if err := q.MachineUpdateProviderStatus(ctx, upParams); err != nil {
			return fmt.Errorf("while setting machine params: %w", err)
		}

		return nil
	})
}

func (p *provider) Type() model.Provider {
	return p.providerType
}
