package service

import (
	"context"
	"fmt"

	"oci-portal/internal/oci"
)

// ChangeInstancePublicIP 更换实例主 VNIC 的临时公网 IP，返回新地址。
func (s *OciConfigService) ChangeInstancePublicIP(ctx context.Context, id uint, region, instanceID string) (string, error) {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return "", err
	}
	return s.client.ChangeInstancePublicIP(ctx, cred, region, instanceID)
}

// AddInstanceIpv6 为实例主 VNIC 分配 IPv6 地址；address 为空时自动分配。
func (s *OciConfigService) AddInstanceIpv6(ctx context.Context, id uint, region, instanceID, address string) (string, error) {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return "", err
	}
	return s.client.AddInstanceIpv6(ctx, cred, region, instanceID, address)
}

// DeleteInstanceIpv6 取消分配实例上的指定 IPv6 地址。
func (s *OciConfigService) DeleteInstanceIpv6(ctx context.Context, id uint, region, instanceID, address string) error {
	if address == "" {
		return fmt.Errorf("delete ipv6: address is required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return err
	}
	return s.client.DeleteInstanceIpv6(ctx, cred, region, instanceID, address)
}

// InstanceVnics 列出实例的全部 VNIC。
func (s *OciConfigService) InstanceVnics(ctx context.Context, id uint, region, instanceID string) ([]oci.Vnic, error) {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListInstanceVnics(ctx, cred, region, instanceID)
}

// AttachVnic 为实例附加次要 VNIC。
func (s *OciConfigService) AttachVnic(ctx context.Context, id uint, region, instanceID string, in oci.AttachVnicInput) (oci.Vnic, error) {
	if instanceID == "" || in.SubnetID == "" {
		return oci.Vnic{}, fmt.Errorf("attach vnic: instanceId and subnetId are required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return oci.Vnic{}, err
	}
	return s.client.AttachVnic(ctx, cred, region, instanceID, in)
}

// DetachVnic 分离 VNIC 附加关系(主 VNIC 由 OCI 拒绝)。
func (s *OciConfigService) DetachVnic(ctx context.Context, id uint, region, attachmentID string) error {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return err
	}
	return s.client.DetachVnic(ctx, cred, region, attachmentID)
}

// AddVnicIpv6 为指定 VNIC 分配 IPv6;address 留空自动分配。
func (s *OciConfigService) AddVnicIpv6(ctx context.Context, id uint, region, vnicID, address string) (string, error) {
	if vnicID == "" {
		return "", fmt.Errorf("add vnic ipv6: vnicId is required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return "", err
	}
	return s.client.AddVnicIpv6(ctx, cred, region, vnicID, address)
}

// BootVolumeAttachments 列出实例的引导卷挂载。
func (s *OciConfigService) BootVolumeAttachments(ctx context.Context, id uint, region, instanceID string) ([]oci.BootVolumeAttachment, error) {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListBootVolumeAttachments(ctx, cred, region, instanceID)
}

// AttachBootVolume 为实例挂载引导卷（实例需 STOPPED）。
func (s *OciConfigService) AttachBootVolume(ctx context.Context, id uint, region, instanceID, bootVolumeID string) (oci.BootVolumeAttachment, error) {
	if instanceID == "" || bootVolumeID == "" {
		return oci.BootVolumeAttachment{}, fmt.Errorf("attach boot volume: instanceId and bootVolumeId are required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return oci.BootVolumeAttachment{}, err
	}
	return s.client.AttachBootVolume(ctx, cred, region, instanceID, bootVolumeID)
}

// DetachBootVolume 分离引导卷挂载（实例需 STOPPED）。
func (s *OciConfigService) DetachBootVolume(ctx context.Context, id uint, region, attachmentID string) error {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return err
	}
	return s.client.DetachBootVolume(ctx, cred, region, attachmentID)
}

// ReplaceBootVolume 替换实例引导卷（实例需 STOPPED）。
func (s *OciConfigService) ReplaceBootVolume(ctx context.Context, id uint, region, instanceID, bootVolumeID string) (oci.BootVolumeAttachment, error) {
	if instanceID == "" || bootVolumeID == "" {
		return oci.BootVolumeAttachment{}, fmt.Errorf("replace boot volume: instanceId and bootVolumeId are required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return oci.BootVolumeAttachment{}, err
	}
	return s.client.ReplaceBootVolume(ctx, cred, region, instanceID, bootVolumeID)
}

// BlockVolumes 列出块存储卷；compartmentID 为空表示租户根。
func (s *OciConfigService) BlockVolumes(ctx context.Context, id uint, region, availabilityDomain, compartmentID string) ([]oci.BlockVolume, error) {
	cred, err := s.credentialsInCompartment(ctx, id, compartmentID)
	if err != nil {
		return nil, err
	}
	return s.client.ListBlockVolumes(ctx, cred, region, availabilityDomain)
}

// VolumeAttachments 列出实例的块卷挂载。
func (s *OciConfigService) VolumeAttachments(ctx context.Context, id uint, region, instanceID string) ([]oci.VolumeAttachment, error) {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return nil, err
	}
	return s.client.ListVolumeAttachments(ctx, cred, region, instanceID)
}

// AttachVolume 为实例附加块卷。
func (s *OciConfigService) AttachVolume(ctx context.Context, id uint, region, instanceID, volumeID string, readOnly bool) (oci.VolumeAttachment, error) {
	if instanceID == "" || volumeID == "" {
		return oci.VolumeAttachment{}, fmt.Errorf("attach volume: instanceId and volumeId are required")
	}
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return oci.VolumeAttachment{}, err
	}
	return s.client.AttachVolume(ctx, cred, region, instanceID, volumeID, readOnly)
}

// DetachVolume 分离块卷挂载。
func (s *OciConfigService) DetachVolume(ctx context.Context, id uint, region, attachmentID string) error {
	cred, err := s.credentialsByID(ctx, id)
	if err != nil {
		return err
	}
	return s.client.DetachVolume(ctx, cred, region, attachmentID)
}
