package qiniu

import (
	"context"
	"fmt"
	"io"

	"u-desk/internal/oss"
)

// StorageType 存储类型枚举
type StorageType int

const (
	// StorageTypeStandard 标准存储 (0)
	StorageTypeStandard StorageType = 0
	// StorageTypeIA 低频存储 (1) - Infrequent Access
	StorageTypeIA StorageType = 1
	// StorageTypeArchive 归档存储 (2) - Archive
	StorageTypeArchive StorageType = 2
	// StorageTypeDeepArchive 深度归档存储 (3) - Deep Archive
	StorageTypeDeepArchive StorageType = 3
	// StorageTypeIntelligentTiering 智能分层存储 (4)
	StorageTypeIntelligentTiering StorageType = 4
	// StorageTypeArchiveIR 归档直读存储 (5) - Archive Immediate Retrieval
	StorageTypeArchiveIR StorageType = 5
)

// String 返回存储类型的字符串表示
func (t StorageType) String() string {
	switch t {
	case StorageTypeStandard:
		return "标准存储"
	case StorageTypeIA:
		return "低频存储"
	case StorageTypeArchive:
		return "归档存储"
	case StorageTypeDeepArchive:
		return "深度归档存储"
	case StorageTypeIntelligentTiering:
		return "智能分层存储"
	case StorageTypeArchiveIR:
		return "归档直读存储"
	default:
		return "未知"
	}
}

// LifecycleConfig 文件生命周期配置
type LifecycleConfig struct {
	// ToIAAfterDays 转换到低频存储的天数，-1 表示取消
	ToIAAfterDays int
	// ToIntelligentTieringAfterDays 转换到智能分层存储的天数，-1 表示取消
	ToIntelligentTieringAfterDays int
	// ToArchiveIRAfterDays 转换到归档直读存储的天数，-1 表示取消
	ToArchiveIRAfterDays int
	// ToArchiveAfterDays 转换到归档存储的天数，-1 表示取消
	ToArchiveAfterDays int
	// ToDeepArchiveAfterDays 转换到深度归档存储的天数，-1 表示取消
	ToDeepArchiveAfterDays int
	// DeleteAfterDays 过期删除的天数，-1 表示取消，0 表示不设置
	DeleteAfterDays int
}

// ChangeStorageType 修改文件存储类型
// 根据: https://developer.qiniu.com/kodo/api/3710/chtype
func (c *Client) ChangeStorageType(ctx context.Context, key string, storageType StorageType) error {
	encodedEntry := c.encodeEntry(key)
	path := fmt.Sprintf("/chtype/%s/type/%d", encodedEntry, storageType)

	resp, err := c.doRequest("POST", path, nil)
	if err != nil {
		return oss.NewError("STYPE_ERROR", "failed to change storage type", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		return nil
	}

	body, _ := io.ReadAll(resp.Body)
	return oss.NewError("STYPE_ERROR",
		fmt.Sprintf("change storage type failed with status %d: %s", resp.StatusCode, string(body)), nil)
}

// SetDeleteAfterDays 设置文件过期删除时间
// 根据: https://developer.qiniu.com/kodo/api/update-file-lifecycle
//
// 参数:
//   - key: 文件 key
//   - days: 过期天数，0 表示取消过期删除设置
//
// 注意：
//   - 文件在设置的天数之后被删除，删除后不可恢复
//   - 设置为 0 表示取消过期删除设置
func (c *Client) SetDeleteAfterDays(ctx context.Context, key string, days int) error {
	encodedEntry := c.encodeEntry(key)
	path := fmt.Sprintf("/deleteAfterDays/%s/%d", encodedEntry, days)

	resp, err := c.doRequest("POST", path, nil)
	if err != nil {
		return oss.NewError("LIFECYCLE_ERROR", "failed to set delete after days", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		return nil
	}

	body, _ := io.ReadAll(resp.Body)
	return oss.NewError("LIFECYCLE_ERROR",
		fmt.Sprintf("set delete after days failed with status %d: %s", resp.StatusCode, string(body)), nil)
}

// SetLifecycle 设置文件生命周期
// 根据: https://developer.qiniu.com/kodo/api/8062/modify-object-life-cycle
//
// 参数说明:
//   - ToIAAfterDays: 转换到低频存储的天数，设置为 -1 表示取消
//   - ToIntelligentTieringAfterDays: 转换到智能分层存储的天数，设置为 -1 表示取消
//   - ToArchiveIRAfterDays: 转换到归档直读存储的天数，设置为 -1 表示取消
//   - ToArchiveAfterDays: 转换到归档存储的天数，设置为 -1 表示取消
//   - ToDeepArchiveAfterDays: 转换到深度归档存储的天数，设置为 -1 表示取消
//   - DeleteAfterDays: 过期删除的天数，设置为 -1 表示取消，0 表示不设置
//
// 注意：
//   - 所有参数都是可选的，只设置需要的参数即可
//   - 文件删除后不可恢复
func (c *Client) SetLifecycle(ctx context.Context, key string, config *LifecycleConfig) error {
	encodedEntry := c.encodeEntry(key)
	path := fmt.Sprintf("/lifecycle/%s", encodedEntry)

	// 添加各个生命周期参数
	if config.ToIAAfterDays != 0 {
		path += fmt.Sprintf("/toIAAfterDays/%d", config.ToIAAfterDays)
	}
	if config.ToIntelligentTieringAfterDays != 0 {
		path += fmt.Sprintf("/toIntelligentTieringAfterDays/%d", config.ToIntelligentTieringAfterDays)
	}
	if config.ToArchiveIRAfterDays != 0 {
		path += fmt.Sprintf("/toArchiveIRAfterDays/%d", config.ToArchiveIRAfterDays)
	}
	if config.ToArchiveAfterDays != 0 {
		path += fmt.Sprintf("/toArchiveAfterDays/%d", config.ToArchiveAfterDays)
	}
	if config.ToDeepArchiveAfterDays != 0 {
		path += fmt.Sprintf("/toDeepArchiveAfterDays/%d", config.ToDeepArchiveAfterDays)
	}
	if config.DeleteAfterDays != 0 {
		path += fmt.Sprintf("/deleteAfterDays/%d", config.DeleteAfterDays)
	}

	// 如果没有设置任何参数，返回错误
	if path == fmt.Sprintf("/lifecycle/%s", encodedEntry) {
		return oss.NewError("LIFECYCLE_ERROR", "no lifecycle parameters specified", nil)
	}

	resp, err := c.doRequest("POST", path, nil)
	if err != nil {
		return oss.NewError("LIFECYCLE_ERROR", "failed to set lifecycle", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		return nil
	}

	body, _ := io.ReadAll(resp.Body)
	return oss.NewError("LIFECYCLE_ERROR",
		fmt.Sprintf("set lifecycle failed with status %d: %s", resp.StatusCode, string(body)), nil)
}

// CancelIAConversion 取消转低频存储的生命周期规则
func (c *Client) CancelIAConversion(ctx context.Context, key string) error {
	config := &LifecycleConfig{
		ToIAAfterDays: -1,
	}
	return c.SetLifecycle(ctx, key, config)
}

// CancelArchiveConversion 取消转归档存储的生命周期规则
func (c *Client) CancelArchiveConversion(ctx context.Context, key string) error {
	config := &LifecycleConfig{
		ToArchiveAfterDays: -1,
	}
	return c.SetLifecycle(ctx, key, config)
}

// CancelDeleteAfterDays 取消过期删除的生命周期规则
func (c *Client) CancelDeleteAfterDays(ctx context.Context, key string) error {
	config := &LifecycleConfig{
		DeleteAfterDays: -1,
	}
	return c.SetLifecycle(ctx, key, config)
}

// SetToIAAfterDays 设置文件转低频存储的天数
func (c *Client) SetToIAAfterDays(ctx context.Context, key string, days int) error {
	config := &LifecycleConfig{
		ToIAAfterDays: days,
	}
	return c.SetLifecycle(ctx, key, config)
}

// SetToArchiveAfterDays 设置文件转归档存储的天数
func (c *Client) SetToArchiveAfterDays(ctx context.Context, key string, days int) error {
	config := &LifecycleConfig{
		ToArchiveAfterDays: days,
	}
	return c.SetLifecycle(ctx, key, config)
}

// SetToDeepArchiveAfterDays 设置文件转深度归档存储的天数
func (c *Client) SetToDeepArchiveAfterDays(ctx context.Context, key string, days int) error {
	config := &LifecycleConfig{
		ToDeepArchiveAfterDays: days,
	}
	return c.SetLifecycle(ctx, key, config)
}

// SetToIntelligentTieringAfterDays 设置文件转智能分层存储的天数
func (c *Client) SetToIntelligentTieringAfterDays(ctx context.Context, key string, days int) error {
	config := &LifecycleConfig{
		ToIntelligentTieringAfterDays: days,
	}
	return c.SetLifecycle(ctx, key, config)
}

// SetToArchiveIRAfterDays 设置文件转归档直读存储的天数
func (c *Client) SetToArchiveIRAfterDays(ctx context.Context, key string, days int) error {
	config := &LifecycleConfig{
		ToArchiveIRAfterDays: days,
	}
	return c.SetLifecycle(ctx, key, config)
}
