package manager

import (
	"context"
	"database/sql"
	"errors"
	"flag"
	"fmt"
	"time"

	"github.com/packethost/packngo"
	"k8s.io/klog/v2"

	"source.monogon.dev/cloud/bmaas/bmdb"
	"source.monogon.dev/cloud/bmaas/bmdb/model"
	"source.monogon.dev/cloud/lib/sinbin"
	ecl "source.monogon.dev/cloud/shepherd/equinix/wrapngo"
)

type UpdaterConfig struct {
	// Enable starts the updater.
	Enable bool
	// IterationRate is the minimu mtime taken between subsequent iterations of the
	// updater.
	IterationRate time.Duration
}

func (u *UpdaterConfig) RegisterFlags() {
	flag.BoolVar(&u.Enable, "updater_enable", true, "Enable the updater, which periodically scans equinix machines and updates their status in the BMDB")
	flag.DurationVar(&u.IterationRate, "updater_iteration_rate", time.Minute, "Rate limiting for updater iteration loop")
}

// The Updater periodically scans all machines backed by the equinix provider and
// updaters their Provided status fields based on data retrieved from the Equinix
// API.
type Updater struct {
	config *UpdaterConfig
	sinbin sinbin.Sinbin[string]

	cl ecl.Client
}

func (c *UpdaterConfig) New(cl ecl.Client) (*Updater, error) {
	return &Updater{
		config: c,
		cl:     cl,
	}, nil
}

func (u *Updater) Run(ctx context.Context, conn *bmdb.Connection) error {
	var sess *bmdb.Session
	var err error

	if !u.config.Enable {
		return nil
	}

	for {
		if sess == nil {
			sess, err = conn.StartSession(ctx)
			if err != nil {
				return fmt.Errorf("could not start BMDB session: %w", err)
			}
		}
		limit := time.After(u.config.IterationRate)

		err = u.runInSession(ctx, sess)
		switch {
		case err == nil:
			<-limit
		case errors.Is(err, ctx.Err()):
			return err
		case errors.Is(err, bmdb.ErrSessionExpired):
			klog.Errorf("Session expired, restarting...")
			sess = nil
			time.Sleep(time.Second)
		case err != nil:
			klog.Errorf("Processing failed: %v", err)
			// TODO(q3k): close session
			time.Sleep(time.Second)
		}
	}
}

// applyNullStringUpdate returns true if 'up' supersedes 'cur'. Otherwise, it
// returns false and zeroes out up.
func applyNullStringUpdate(up, cur *sql.NullString) bool {
	if up.Valid {
		if !cur.Valid {
			return true
		}
		if up.String != cur.String {
			return true
		}
	}
	up.String = ""
	up.Valid = false
	return false
}

// applyNullProviderStatusUpdate returns true if 'up' supersedes 'cur'.
// Otherwise, it returns false and zeroes out up.
func applyNullProviderStatusUpdate(up, cur *model.NullProviderStatus) bool {
	if up.Valid {
		if !cur.Valid {
			return true
		}
		if up.ProviderStatus != cur.ProviderStatus {
			return true
		}
	}
	up.ProviderStatus = model.ProviderStatusUnknown
	up.Valid = false
	return false
}

// applyUpdate returns true if 'up' supersedes 'cur'. Otherwise, it returns false
// and zeroes out up.
func applyUpdate(up *model.MachineUpdateProviderStatusParams, cur *model.MachineProvided) bool {
	res := false
	res = res || applyNullStringUpdate(&up.ProviderReservationID, &cur.ProviderReservationID)
	res = res || applyNullStringUpdate(&up.ProviderIpAddress, &cur.ProviderIpAddress)
	res = res || applyNullStringUpdate(&up.ProviderLocation, &cur.ProviderLocation)
	res = res || applyNullProviderStatusUpdate(&up.ProviderStatus, &cur.ProviderStatus)
	return res
}

// updateLog logs information about the given update as calculated by applyUpdate.
func updateLog(up *model.MachineUpdateProviderStatusParams) {
	if up.ProviderReservationID.Valid {
		klog.Infof("   Device %s: new reservation ID %s", up.ProviderID, up.ProviderReservationID.String)
	}
	if up.ProviderIpAddress.Valid {
		klog.Infof("   Device %s: new IP address %s", up.ProviderID, up.ProviderIpAddress.String)
	}
	if up.ProviderLocation.Valid {
		klog.Infof("   Device %s: new location %s", up.ProviderID, up.ProviderLocation.String)
	}
	if up.ProviderStatus.Valid {
		klog.Infof("   Device %s: new status %s", up.ProviderID, up.ProviderStatus.ProviderStatus)
	}
}

func (u *Updater) runInSession(ctx context.Context, sess *bmdb.Session) error {
	// Get all machines provided by us into the BMDB.
	// TODO(q3k): do not load all machines into memory.

	var machines []model.MachineProvided
	err := sess.Transact(ctx, func(q *model.Queries) error {
		var err error
		machines, err = q.GetProvidedMachines(ctx, model.ProviderEquinix)
		return err
	})
	if err != nil {
		return fmt.Errorf("when fetching provided machines: %w", err)
	}

	// Limit how many machines we check by timing them out if they're likely to not
	// get updated soon.
	penalized := 0
	var check []model.MachineProvided
	for _, m := range machines {
		if u.sinbin.Penalized(m.ProviderID) {
			penalized += 1
		} else {
			check = append(check, m)
		}
	}

	klog.Infof("Machines to check %d, skipping: %d", len(check), penalized)
	for _, m := range check {
		dev, err := u.cl.GetDevice(ctx, "", m.ProviderID, &packngo.ListOptions{
			Includes: []string{
				"hardware_reservation",
			},
			Excludes: []string{
				"created_by", "customdata", "network_ports", "operating_system", "actions",
				"plan", "provisioning_events", "ssh_keys", "tags", "volumes",
			},
		})
		if err != nil {
			klog.Warningf("Fetching device %s failed: %v", m.ProviderID, err)
			continue
		}

		// nextCheck will be used to sinbin the machine for some given time if there is
		// no difference between the current state and new state.
		//
		// Some conditions override this to be shorter (when the machine doesn't yet have
		// all data available or is in an otherwise unstable state).
		nextCheck := time.Minute * 30

		up := model.MachineUpdateProviderStatusParams{
			Provider:   m.Provider,
			ProviderID: m.ProviderID,
		}

		if dev.HardwareReservation != nil {
			up.ProviderReservationID.Valid = true
			up.ProviderReservationID.String = dev.HardwareReservation.ID
		} else {
			nextCheck = time.Minute
		}

		for _, addr := range dev.Network {
			if !addr.Public {
				continue
			}
			up.ProviderIpAddress.Valid = true
			up.ProviderIpAddress.String = addr.Address
			break
		}
		if !up.ProviderIpAddress.Valid {
			nextCheck = time.Minute
		}

		if dev.Facility != nil {
			up.ProviderLocation.Valid = true
			up.ProviderLocation.String = dev.Facility.Code
		} else {
			nextCheck = time.Minute
		}

		up.ProviderStatus.Valid = true
		switch dev.State {
		case "active":
			up.ProviderStatus.ProviderStatus = model.ProviderStatusRunning
		case "deleted":
			up.ProviderStatus.ProviderStatus = model.ProviderStatusMissing
		case "failed":
			up.ProviderStatus.ProviderStatus = model.ProviderStatusProvisioningFailedPermanent
		case "inactive":
			up.ProviderStatus.ProviderStatus = model.ProviderStatusStopped
		case "powering_on", "powering_off":
			nextCheck = time.Minute
			up.ProviderStatus.ProviderStatus = model.ProviderStatusStopped
		case "queued", "provisioning", "reinstalling", "post_provisioning":
			nextCheck = time.Minute
			up.ProviderStatus.ProviderStatus = model.ProviderStatusProvisioning
		default:
			klog.Warningf("Device %s has unexpected status: %q", m.ProviderID, dev.State)
			nextCheck = time.Minute
			up.ProviderStatus.ProviderStatus = model.ProviderStatusUnknown
		}

		if !applyUpdate(&up, &m) {
			u.sinbin.Add(m.ProviderID, time.Now().Add(nextCheck))
			continue
		}

		klog.Infof("Device %s has new data:", m.ProviderID)
		updateLog(&up)
		err = sess.Transact(ctx, func(q *model.Queries) error {
			return q.MachineUpdateProviderStatus(ctx, up)
		})
		if err != nil {
			klog.Warningf("Device %s failed to update: %v", m.ProviderID, err)
		}
		u.sinbin.Add(m.ProviderID, time.Now().Add(time.Minute))
	}
	return nil
}
