package api

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"oci-portal/internal/oci"
)

// @Summary  可用域列表
// @Tags     租户配置
// @Param    id path int true "配置 ID"
// @Success  200 {array} string
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/availability-domains [get]
func (h *ociConfigHandler) availabilityDomains(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	ads, err := h.svc.AvailabilityDomains(c.Request.Context(), id, c.Query("region"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, ads)
}

// ---- 实例 ----

type createInstanceRequest struct {
	Region               string  `json:"region"`
	CompartmentID        string  `json:"compartmentId"`      // 为空时建在租户根
	AvailabilityDomain   string  `json:"availabilityDomain"` // 为空时默认使用第一个可用域
	DisplayName          string  `json:"displayName" binding:"required"`
	Shape                string  `json:"shape" binding:"required"`
	Count                int     `json:"count"` // 批量创建数量，缺省 1，上限 10
	Ocpus                float32 `json:"ocpus"`
	MemoryInGBs          float32 `json:"memoryInGBs"`
	ImageID              string  `json:"imageId"`
	BootVolumeID         string  `json:"bootVolumeId"`
	BootVolumeSizeGBs    int64   `json:"bootVolumeSizeGBs"`
	BootVolumeVpusPerGB  int64   `json:"bootVolumeVpusPerGB"`
	SubnetID             string  `json:"subnetId"` // 为空时自动创建 VCN 与子网
	AssignPublicIP       bool    `json:"assignPublicIp"`
	AssignIpv6           bool    `json:"assignIpv6"`
	SSHPublicKey         string  `json:"sshPublicKey"`
	RootPassword         string  `json:"rootPassword"`
	GenerateRootPassword bool    `json:"generateRootPassword"` // 服务端生成随机 root 密码并写入 TAG RootPassword
	UserData             string  `json:"userData"`
}

type updateInstanceRequest struct {
	Region      string  `json:"region"`
	DisplayName string  `json:"displayName"`
	Shape       string  `json:"shape"` // 更换 shape，运行中实例会自动重启
	Ocpus       float32 `json:"ocpus"`
	MemoryInGBs float32 `json:"memoryInGBs"`
}

type instanceActionRequest struct {
	Region string `json:"region"`
	Action string `json:"action" binding:"required"`
}

// @Summary  实例列表
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Success  200 {array} oci.Instance
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances [get]
func (h *ociConfigHandler) listInstances(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	instances, err := h.svc.Instances(c.Request.Context(), id, c.Query("region"), c.Query("compartmentId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, instances)
}

// @Summary  创建实例
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    body body createInstanceRequest true "请求体"
// @Success  201 {object} createInstancesResponse "部分成功仍 201,errors 为逐台失败信息"
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances [post]
func (h *ociConfigHandler) createInstance(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req createInstanceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	count := req.Count
	if count == 0 {
		count = 1
	}
	instances, failures, err := h.svc.CreateInstances(c.Request.Context(), id, oci.CreateInstanceInput{
		Region:               req.Region,
		CompartmentID:        req.CompartmentID,
		AvailabilityDomain:   req.AvailabilityDomain,
		DisplayName:          req.DisplayName,
		Shape:                req.Shape,
		Ocpus:                req.Ocpus,
		MemoryInGBs:          req.MemoryInGBs,
		ImageID:              req.ImageID,
		BootVolumeID:         req.BootVolumeID,
		BootVolumeSizeGBs:    req.BootVolumeSizeGBs,
		BootVolumeVpusPerGB:  req.BootVolumeVpusPerGB,
		SubnetID:             req.SubnetID,
		AssignPublicIP:       req.AssignPublicIP,
		AssignIpv6:           req.AssignIpv6,
		SSHPublicKey:         req.SSHPublicKey,
		RootPassword:         req.RootPassword,
		GenerateRootPassword: req.GenerateRootPassword,
		UserData:             req.UserData,
	}, count)
	if err != nil {
		respondError(c, err)
		return
	}
	// 全部失败视为执行失败，部分成功仍返回 201 并附带逐台失败信息
	status := http.StatusCreated
	if len(instances) == 0 && len(failures) > 0 {
		status = http.StatusInternalServerError
	}
	// nil 切片会序列化为 null，显式空数组免去前端判空
	if instances == nil {
		instances = []oci.Instance{}
	}
	if failures == nil {
		failures = []string{}
	}
	c.JSON(status, gin.H{"instances": instances, "errors": failures})
}

// @Summary  实例详情
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Success  200 {object} oci.Instance
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId} [get]
func (h *ociConfigHandler) getInstance(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	instance, err := h.svc.Instance(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, instance)
}

// @Summary  更新实例
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body updateInstanceRequest true "请求体"
// @Success  200 {object} oci.Instance
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId} [put]
func (h *ociConfigHandler) updateInstance(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req updateInstanceRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	instance, err := h.svc.UpdateInstance(c.Request.Context(), id, c.Param("instanceId"), oci.UpdateInstanceInput{
		Region:      req.Region,
		DisplayName: req.DisplayName,
		Shape:       req.Shape,
		Ocpus:       req.Ocpus,
		MemoryInGBs: req.MemoryInGBs,
	})
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, instance)
}

// @Summary  终止实例
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Success  204 "无内容"
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId} [delete]
func (h *ociConfigHandler) terminateInstance(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	preserve := c.Query("preserveBootVolume") == "true"
	if err := h.svc.TerminateInstance(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"), preserve); err != nil {
		respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}

// @Summary  实例电源操作(启停/重启)
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body instanceActionRequest true "请求体"
// @Success  200 {object} oci.Instance
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/action [post]
func (h *ociConfigHandler) instanceAction(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req instanceActionRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	instance, err := h.svc.InstanceAction(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.Action)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, instance)
}

// ---- 引导卷 ----

type updateBootVolumeRequest struct {
	Region      string `json:"region"`
	DisplayName string `json:"displayName"`
	SizeInGBs   int64  `json:"sizeInGBs"`
	VpusPerGB   int64  `json:"vpusPerGB"`
}

// @Summary  引导卷列表
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Success  200 {array} oci.BootVolume
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/boot-volumes [get]
func (h *ociConfigHandler) listBootVolumes(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	volumes, err := h.svc.BootVolumes(c.Request.Context(), id, c.Query("region"), c.Query("availabilityDomain"), c.Query("compartmentId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, volumes)
}

// @Summary  引导卷详情
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    bootVolumeId path string true "bootVolumeId"
// @Success  200 {object} oci.BootVolume
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/boot-volumes/{bootVolumeId} [get]
func (h *ociConfigHandler) getBootVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	volume, err := h.svc.BootVolume(c.Request.Context(), id, c.Query("region"), c.Param("bootVolumeId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, volume)
}

// @Summary  更新引导卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    bootVolumeId path string true "bootVolumeId"
// @Param    body body updateBootVolumeRequest true "请求体"
// @Success  200 {object} oci.BootVolume
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/boot-volumes/{bootVolumeId} [put]
func (h *ociConfigHandler) updateBootVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req updateBootVolumeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	volume, err := h.svc.UpdateBootVolume(c.Request.Context(), id, c.Param("bootVolumeId"), oci.UpdateBootVolumeInput{
		Region:      req.Region,
		DisplayName: req.DisplayName,
		SizeInGBs:   req.SizeInGBs,
		VpusPerGB:   req.VpusPerGB,
	})
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, volume)
}

// @Summary  删除引导卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    bootVolumeId path string true "bootVolumeId"
// @Success  204 "无内容"
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/boot-volumes/{bootVolumeId} [delete]
func (h *ociConfigHandler) deleteBootVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	if err := h.svc.DeleteBootVolume(c.Request.Context(), id, c.Query("region"), c.Param("bootVolumeId")); err != nil {
		respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}
