package oci

import (
	"context"
	"fmt"
	"time"

	"github.com/oracle/oci-go-sdk/v65/core"
)

// Image 是一个可用的实例镜像。
type Image struct {
	ID                     string     `json:"id"`
	DisplayName            string     `json:"displayName"`
	OperatingSystem        string     `json:"operatingSystem"`
	OperatingSystemVersion string     `json:"operatingSystemVersion"`
	SizeInMBs              int64      `json:"sizeInMBs"`
	TimeCreated            *time.Time `json:"timeCreated"`
}

// ImagesQuery 是镜像查询条件。
type ImagesQuery struct {
	Region          string // 目标区域，空则用凭据默认区域
	OperatingSystem string // 如 Canonical Ubuntu、Oracle Linux
	Shape           string // 只返回兼容该 shape 的镜像，如 VM.Standard.A1.Flex
}

// ListImages 实现 Client：分页列出租户可用的平台镜像。
func (c *RealClient) ListImages(ctx context.Context, cred Credentials, q ImagesQuery) ([]Image, error) {
	cc, err := core.NewComputeClientWithConfigurationProvider(provider(cred))
	if err != nil {
		return nil, fmt.Errorf("new compute client: %w", err)
	}
	applyProxy(&cc.BaseClient, cred)
	if q.Region != "" {
		cc.SetRegion(normalizeRegion(q.Region))
	}
	var images []Image
	var page *string
	for {
		resp, err := cc.ListImages(ctx, buildImagesRequest(cred, q, page))
		if err != nil {
			return nil, fmt.Errorf("list images: %w", err)
		}
		for _, item := range resp.Items {
			images = append(images, toImage(item))
		}
		if resp.OpcNextPage == nil {
			return orEmpty(images), nil
		}
		page = resp.OpcNextPage
	}
}

// GetImage 实现 Client：查询单个镜像（按 imageId 补显示名等信息）。
func (c *RealClient) GetImage(ctx context.Context, cred Credentials, region, imageID string) (Image, error) {
	cc, err := core.NewComputeClientWithConfigurationProvider(provider(cred))
	if err != nil {
		return Image{}, fmt.Errorf("new compute client: %w", err)
	}
	applyProxy(&cc.BaseClient, cred)
	if region != "" {
		cc.SetRegion(normalizeRegion(region))
	}
	resp, err := cc.GetImage(ctx, core.GetImageRequest{ImageId: &imageID})
	if err != nil {
		return Image{}, fmt.Errorf("get image: %w", err)
	}
	return toImage(resp.Image), nil
}

// buildImagesRequest 组装镜像列表请求；过滤条件仅在非空时下发。
func buildImagesRequest(cred Credentials, q ImagesQuery, page *string) core.ListImagesRequest {
	req := core.ListImagesRequest{
		CompartmentId:  cred.EffectiveCompartment(),
		Page:           page,
		LifecycleState: core.ImageLifecycleStateAvailable,
	}
	if q.OperatingSystem != "" {
		req.OperatingSystem = &q.OperatingSystem
	}
	if q.Shape != "" {
		req.Shape = &q.Shape
	}
	return req
}

func toImage(img core.Image) Image {
	out := Image{
		ID:                     deref(img.Id),
		DisplayName:            deref(img.DisplayName),
		OperatingSystem:        deref(img.OperatingSystem),
		OperatingSystemVersion: deref(img.OperatingSystemVersion),
		TimeCreated:            sdkTime(img.TimeCreated),
	}
	if img.SizeInMBs != nil {
		out.SizeInMBs = *img.SizeInMBs
	}
	return out
}
