package api

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"oci-portal/internal/oci"
)

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

// @Summary  ---- 实例 IP ----
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body object true "请求体(见接口说明)"
// @Success  200 {object} publicIpResponse
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/change-public-ip [post]
func (h *ociConfigHandler) changePublicIP(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req struct {
		Region string `json:"region"`
	}
	_ = c.ShouldBindJSON(&req)
	ip, err := h.svc.ChangeInstancePublicIP(c.Request.Context(), id, req.Region, c.Param("instanceId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{"publicIp": ip})
}

// @Summary  实例添加 IPv6 地址
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body object true "请求体(见接口说明)"
// @Success  201 {object} ipv6AddressResponse
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/ipv6-addresses [post]
func (h *ociConfigHandler) addInstanceIpv6(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req struct {
		Region  string `json:"region"`
		Address string `json:"address"`
	}
	_ = c.ShouldBindJSON(&req)
	address, err := h.svc.AddInstanceIpv6(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.Address)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, gin.H{"ipv6Address": address})
}

// @Summary  移除实例 IPv6 地址
// @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}/ipv6-addresses [delete]
func (h *ociConfigHandler) deleteInstanceIpv6(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	err := h.svc.DeleteInstanceIpv6(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"), c.Query("address"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}

// ---- VNIC 管理 ----

type attachVnicRequest struct {
	Region string `json:"region"`
	oci.AttachVnicInput
}

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

// @Summary  附加 VNIC
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body attachVnicRequest true "请求体"
// @Success  201 {object} oci.Vnic
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/vnics [post]
func (h *ociConfigHandler) attachVnic(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req attachVnicRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	vnic, err := h.svc.AttachVnic(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.AttachVnicInput)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, vnic)
}

// @Summary  分离 VNIC
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    attachmentId path string true "attachmentId"
// @Success  204 "无内容"
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/vnic-attachments/{attachmentId} [delete]
func (h *ociConfigHandler) detachVnic(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	if err := h.svc.DetachVnic(c.Request.Context(), id, c.Query("region"), c.Param("attachmentId")); err != nil {
		respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}

// addVnicIpv6 为指定 VNIC 添加 IPv6;body.address 留空自动分配。
//
// @Summary  为指定 VNIC 添加 IPv6
// @Tags     计算
// @Param    id path int true "配置 ID"
// @Param    vnicId path string true "vnicId"
// @Param    body body object true "请求体(见接口说明)"
// @Success  201 {object} addressResponse
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/vnics/{vnicId}/ipv6-addresses [post]
func (h *ociConfigHandler) addVnicIpv6(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req struct {
		Region  string `json:"region"`
		Address string `json:"address"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	addr, err := h.svc.AddVnicIpv6(c.Request.Context(), id, req.Region, c.Param("vnicId"), req.Address)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, gin.H{"address": addr})
}

// ---- 引导卷挂载 ----

type attachBootVolumeRequest struct {
	Region       string `json:"region"`
	BootVolumeID string `json:"bootVolumeId" binding:"required"`
}

// @Summary  引导卷附件列表
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Success  200 {array} oci.BootVolumeAttachment
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/boot-volume-attachments [get]
func (h *ociConfigHandler) listBootVolumeAttachments(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	atts, err := h.svc.BootVolumeAttachments(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, atts)
}

// @Summary  附加引导卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body attachBootVolumeRequest true "请求体"
// @Success  201 {object} oci.BootVolumeAttachment
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/boot-volume-attachments [post]
func (h *ociConfigHandler) attachBootVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req attachBootVolumeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	att, err := h.svc.AttachBootVolume(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.BootVolumeID)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, att)
}

// @Summary  更换实例引导卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body attachBootVolumeRequest true "请求体"
// @Success  200 {object} oci.BootVolumeAttachment
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/replace-boot-volume [post]
func (h *ociConfigHandler) replaceBootVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req attachBootVolumeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	att, err := h.svc.ReplaceBootVolume(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.BootVolumeID)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, att)
}

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

// ---- 块卷挂载 ----

type attachVolumeRequest struct {
	Region   string `json:"region"`
	VolumeID string `json:"volumeId" binding:"required"`
	ReadOnly bool   `json:"readOnly"`
}

// @Summary  块存储卷列表
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Success  200 {array} oci.BlockVolume
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/volumes [get]
func (h *ociConfigHandler) listBlockVolumes(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	volumes, err := h.svc.BlockVolumes(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    instanceId path string true "instanceId"
// @Success  200 {array} oci.VolumeAttachment
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/volume-attachments [get]
func (h *ociConfigHandler) listVolumeAttachments(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	atts, err := h.svc.VolumeAttachments(c.Request.Context(), id, c.Query("region"), c.Param("instanceId"))
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusOK, atts)
}

// @Summary  附加块存储卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    instanceId path string true "instanceId"
// @Param    body body attachVolumeRequest true "请求体"
// @Success  201 {object} oci.VolumeAttachment
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/instances/{instanceId}/volume-attachments [post]
func (h *ociConfigHandler) attachVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	var req attachVolumeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	att, err := h.svc.AttachVolume(c.Request.Context(), id, req.Region, c.Param("instanceId"), req.VolumeID, req.ReadOnly)
	if err != nil {
		respondError(c, err)
		return
	}
	c.JSON(http.StatusCreated, att)
}

// @Summary  分离块存储卷
// @Tags     存储
// @Param    id path int true "配置 ID"
// @Param    attachmentId path string true "attachmentId"
// @Success  204 "无内容"
// @Security BearerAuth
// @Router   /api/v1/oci-configs/{id}/volume-attachments/{attachmentId} [delete]
func (h *ociConfigHandler) detachVolume(c *gin.Context) {
	id, ok := pathID(c)
	if !ok {
		return
	}
	if err := h.svc.DetachVolume(c.Request.Context(), id, c.Query("region"), c.Param("attachmentId")); err != nil {
		respondError(c, err)
		return
	}
	c.Status(http.StatusNoContent)
}
