package model

import (
	"database/sql/driver"
	"encoding/json"
	"time"

	"gorm.io/datatypes"
	"gorm.io/gorm"
)

// UIntListJSON uint 数组 JSON 类型。
// 用于在 PostgreSQL jsonb 字段中存储店铺 ID 列表。
type UIntListJSON []uint

// Value 实现 driver.Valuer。
func (ids UIntListJSON) Value() (driver.Value, error) {
	if ids == nil {
		return "[]", nil
	}
	return json.Marshal(ids)
}

// Scan 实现 sql.Scanner。
func (ids *UIntListJSON) Scan(value any) error {
	if value == nil {
		*ids = UIntListJSON{}
		return nil
	}

	switch v := value.(type) {
	case []byte:
		return json.Unmarshal(v, ids)
	case string:
		return json.Unmarshal([]byte(v), ids)
	default:
		*ids = UIntListJSON{}
		return nil
	}
}

// ExportTask 导出主任务模型。
// 记录导出任务的创建信息、执行进度、最终产物和取消状态。
type ExportTask struct {
	gorm.Model
	BaseModel `gorm:"embedded"`

	TaskNo    string `gorm:"column:task_no;type:varchar(50);uniqueIndex:idx_export_task_no,where:deleted_at IS NULL;not null;comment:任务编号(EXP-YYYYMMDD-XXXXXX)" json:"task_no"`
	Scene     string `gorm:"column:scene;type:varchar(50);index:idx_export_task_scene_status_created_at,priority:1;not null;comment:导出场景(device/iot_card)" json:"scene"`
	Format    string `gorm:"column:format;type:varchar(20);not null;comment:导出格式(xlsx/csv)" json:"format"`
	Status    int    `gorm:"column:status;type:int;index:idx_export_task_scene_status_created_at,priority:2;not null;default:1;comment:任务状态 1-待处理 2-处理中 3-已完成 4-已失败 5-已取消" json:"status"`
	Progress  int    `gorm:"column:progress;type:int;not null;default:0;comment:任务进度(0-100)" json:"progress"`
	TotalRows int    `gorm:"column:total_rows;type:int;not null;default:0;comment:总行数" json:"total_rows"`

	ProcessedRows int `gorm:"column:processed_rows;type:int;not null;default:0;comment:已处理行数" json:"processed_rows"`
	TotalShards   int `gorm:"column:total_shards;type:int;not null;default:0;comment:总分片数" json:"total_shards"`
	SuccessShards int `gorm:"column:success_shards;type:int;not null;default:0;comment:成功分片数" json:"success_shards"`
	FailedShards  int `gorm:"column:failed_shards;type:int;not null;default:0;comment:失败分片数" json:"failed_shards"`

	CancelRequested bool `gorm:"column:cancel_requested;type:boolean;not null;default:false;index;comment:是否请求取消" json:"cancel_requested"`

	QueryJSON datatypes.JSON `gorm:"column:query_json;type:jsonb;not null;default:'{}';comment:导出查询参数(JSON)" json:"query_json"`

	ScopeShopIDs        UIntListJSON `gorm:"column:scope_shop_ids;type:jsonb;not null;default:'[]';comment:导出时的数据权限店铺范围快照" json:"scope_shop_ids"`
	CreatorUserID       uint         `gorm:"column:creator_user_id;type:bigint;not null;index;comment:创建人用户ID" json:"creator_user_id"`
	CreatorUserType     int          `gorm:"column:creator_user_type;type:int;not null;comment:创建人用户类型 2-平台 3-代理 4-企业" json:"creator_user_type"`
	CreatorShopID       *uint        `gorm:"column:creator_shop_id;type:bigint;index;comment:创建人店铺ID快照" json:"creator_shop_id,omitempty"`
	CreatorEnterpriseID *uint        `gorm:"column:creator_enterprise_id;type:bigint;index;comment:创建人企业ID快照" json:"creator_enterprise_id,omitempty"`

	FileKey      string     `gorm:"column:file_key;type:varchar(500);comment:最终产物文件Key" json:"file_key"`
	FileSize     int64      `gorm:"column:file_size;type:bigint;not null;default:0;comment:最终产物文件大小(字节)" json:"file_size"`
	ErrorMessage string     `gorm:"column:error_message;type:text;comment:错误信息" json:"error_message"`
	StartedAt    *time.Time `gorm:"column:started_at;comment:开始处理时间" json:"started_at"`
	CompletedAt  *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
}

// TableName 指定表名。
func (ExportTask) TableName() string {
	return "tb_export_task"
}

// ExportShardTask 导出分片任务模型。
// 记录主任务拆分后的每个分片执行状态和分片产物。
type ExportShardTask struct {
	gorm.Model
	BaseModel `gorm:"embedded"`

	TaskID      uint `gorm:"column:task_id;type:bigint;index:idx_export_shard_task_task_status,priority:1;not null;comment:主任务ID" json:"task_id"`
	ShardNo     int  `gorm:"column:shard_no;type:int;not null;comment:分片序号(从1开始)" json:"shard_no"`
	Status      int  `gorm:"column:status;type:int;index:idx_export_shard_task_task_status,priority:2;not null;default:1;comment:分片状态 1-待处理 2-处理中 3-已成功 4-已失败 5-已取消" json:"status"`
	ShardOffset int  `gorm:"column:shard_offset;type:bigint;not null;default:0;comment:分片偏移量(offset)" json:"shard_offset"`
	ShardLimit  int  `gorm:"column:shard_limit;type:int;not null;default:0;comment:分片行数上限(limit)" json:"shard_limit"`

	RowCount      int        `gorm:"column:row_count;type:int;not null;default:0;comment:分片行数" json:"row_count"`
	ProcessedRows int        `gorm:"column:processed_rows;type:int;not null;default:0;comment:分片已处理行数" json:"processed_rows"`
	FileKey       string     `gorm:"column:file_key;type:varchar(500);comment:分片产物文件Key" json:"file_key"`
	FileSize      int64      `gorm:"column:file_size;type:bigint;not null;default:0;comment:分片产物文件大小(字节)" json:"file_size"`
	ErrorMessage  string     `gorm:"column:error_message;type:text;comment:分片错误信息" json:"error_message"`
	StartedAt     *time.Time `gorm:"column:started_at;comment:开始处理时间" json:"started_at"`
	CompletedAt   *time.Time `gorm:"column:completed_at;comment:完成时间" json:"completed_at"`
}

// TableName 指定表名。
func (ExportShardTask) TableName() string {
	return "tb_export_shard_task"
}
