// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

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
}
