package api

import (
	"fmt"
	"net"
	"net/url"
	"path"
	"strconv"
	"time"
)

type ServerId int
type ServerRef string

const serverPath = "/api/v1/server/"
const serverBootPath = "/api/v1/server/boot/"
const serverShutdownPath = "/api/v1/server/shutdown/"
const serverRebootPath = "/api/v1/server/reboot/"

func ToServerRef(id ServerId) ServerRef {
	return ServerRef(path.Join(serverPath, strconv.Itoa(int(id))))
}

func ToServerId(ref ServerRef) (ServerId, error) {
	prefix, id := path.Split(string(ref))
	if prefix != diskPath {
		return 0, fmt.Errorf("api.model_server: invalid server ref %s", ref)
	}
	parsed, err := strconv.Atoi(id)
	if err != nil {
		return 0, fmt.Errorf("api.model_server: invalid server ref %s\n  %w", ref, err)
	}
	return ServerId(parsed), nil
}

type BootMode string

const (
	BootModeNormal BootMode = "normal"
	BootModeTest   BootMode = "test"
	BootModeRescue BootMode = "rescue"
)

func ServerBootPath(id ServerId, mode BootMode) (*url.URL, error) {
	return url.Parse(path.Join(serverBootPath, string(mode), strconv.Itoa(int(id))))
}

func ServerShutdownPath(id ServerId) (*url.URL, error) {
	return url.Parse(path.Join(serverShutdownPath, strconv.Itoa(int(id))))
}

func ServerRebootPath(id ServerId) (*url.URL, error) {
	return url.Parse(path.Join(serverRebootPath, strconv.Itoa(int(id))))
}

type Location struct {
	Datacenter string `json:"datacenter,omitempty"`
	Room       string `json:"room,omitempty"`
	Zone       string `json:"zone,omitempty"`
	Line       string `json:"line,omitempty"`
	Rack       string `json:"rack,omitempty"`
	Block      string `json:"block,omitempty"`
	Position   int    `json:"position,omitempty"`
}

type Contacts struct {
	Owner string `json:"owner,omitempty"`
	Tech  string `json:"tech,omitempty"`
}

type RescueProtocol string

const (
	RescueProtocolSsh RescueProtocol = "ssh"
	RescueProtocolVnc RescueProtocol = "vnc"
)

type RescueCredentials struct {
	Login    string         `json:"login,omitempty"`
	Password string         `json:"password,omitempty"`
	Protocol RescueProtocol `json:"protocol,omitempty"`
	IP       net.IP         `json:"ip,omitempty"`
}

type ServerBMC struct {
	SessionKey string `json:"session_key,omitempty"`
}

type DriveArray struct {
	RaidLevel RaidLevel `json:"raid_level,omitempty"`
}

type InstallStatus string

const (
	InstallStatusBlank      InstallStatus = "blank"
	InstallStatusInstalling InstallStatus = "installing"
	InstallStatusInstalled  InstallStatus = "installed"
	InstallStatusErrored    InstallStatus = "errored"
)

type InstallStage string

const (
	ServerStageBoot       InstallStage = "BOOT"
	ServerStageWget       InstallStage = "WGET"
	ServerStageOs         InstallStage = "OS"
	ServerStageConfig     InstallStage = "CONFIG"
	ServerStageStart      InstallStage = "START"
	ServerStageCleanRaid  InstallStage = "CLEAN_RAID"
	ServerStageFdisk      InstallStage = "FDISK"
	ServerStageFormat     InstallStage = "FORMAT"
	ServerStageBootloader InstallStage = "BOOTLOADER"
	ServerStageRebooting  InstallStage = "REBOOTING"
)

type Server struct {
	Id                  ServerId                        `json:"id,omitempty"`
	Offer               string                          `json:"offer,omitempty"`
	Hostname            string                          `json:"hostname,omitempty"`
	OperatingSystem     OperatingSystem                 `json:"os,omitempty"`
	Power               string                          `json:"power,omitempty"`
	BootMode            BootMode                        `json:"boot_mode,omitempty"`
	LastReboot          *time.Time                      `json:"last_reboot,omitempty"`
	AntiDdos            bool                            `json:"anti_ddos"`
	HardwareWatch       bool                            `json:"hardware_watch"`
	ProactiveMonitoring bool                            `json:"proactive_monitoring"`
	Support             string                          `json:"support,omitempty"`
	Abuse               string                          `json:"abuse,omitempty"`
	Location            Location                        `json:"location,omitempty"`
	IP                  []ServerIP                      `json:"ip,omitempty"`
	Contacts            Contacts                        `json:"contacts,omitempty"`
	RescueCredentials   RescueCredentials               `json:"rescue_credentials,omitempty"`
	Bmc                 ServerBMC                       `json:"bmc,omitempty"`
	Disks               []WrappedRef[DiskRef]           `json:"disks,omitempty"`
	DriveArrays         []DriveArray                    `json:"drive_arrays,omitempty"`
	RaidControllers     []WrappedRef[RaidControllerRef] `json:"raid_controllers,omitempty"`
	InstallStatus       InstallStatus                   `json:"install_status,omitempty"`
	Stage               InstallStage                    `json:"stage,omitempty"`
}