package system

import (
	"context"
	"regexp"
	"strings"

	"nadir/internal/oscmd"

	"github.com/danielgtaylor/huma/v2"
)

// whenRe matches the shutdown(8) TIME forms we accept: "now", "+<minutes>", or
// "hh:mm". Validating before exec keeps a value like "-r" or "--help" from
// being read as a flag (shutdown does not honor a "--" separator), per the
// repo's input-validation rule.
var whenRe = regexp.MustCompile(`^(now|\+\d+|([01]?\d|2[0-3]):[0-5]\d)$`)

type PowerInput struct {
	Body struct {
		When string `json:"when,omitempty" example:"+1" doc:"When to act, as a shutdown(8) TIME (e.g. \"+5\" minutes, \"23:00\"). Empty or 'now' = immediate."`
	}
}

const powerDescription = "Requires the `root` permission. The response is sent once `shutdown` " +
	"accepts the request; for the immediate form it returns before the machine " +
	"actually goes down, so a 200 does not guarantee a clean shutdown completed."

func registerPower(api huma.API) {
	huma.Register(api, huma.Operation{
		OperationID: "system-reboot",
		Method:      "POST",
		Path:        "/api/system/reboot",
		Summary:     "Reboot the system",
		Description: powerDescription,
		Tags:        []string{tagSystem},
		Metadata:    op("root"),
		Errors:      []int{400, 401, 403, 500},
	}, func(ctx context.Context, in *PowerInput) (*oscmd.StatusOutput, error) {
		return schedulePower("reboot", in.Body.When)
	})

	huma.Register(api, huma.Operation{
		OperationID: "system-poweroff",
		Method:      "POST",
		Path:        "/api/system/poweroff",
		Summary:     "Power off the system",
		Description: powerDescription,
		Tags:        []string{tagSystem},
		Metadata:    op("root"),
		Errors:      []int{400, 401, 403, 500},
	}, func(ctx context.Context, in *PowerInput) (*oscmd.StatusOutput, error) {
		return schedulePower("poweroff", in.Body.When)
	})
}

func schedulePower(action, when string) (*oscmd.StatusOutput, error) {
	w := strings.TrimSpace(when)
	if w == "" {
		w = "now"
	}
	if !whenRe.MatchString(w) {
		return nil, huma.Error400BadRequest("invalid when: " + w)
	}
	flag := "-h"
	if action == "reboot" {
		flag = "-r"
	}
	if _, err := oscmd.Run("shutdown", flag, w); err != nil {
		return nil, huma.Error500InternalServerError("shutdown failed", err)
	}
	return oscmd.OK(), nil
}
