package jd_cookie

import (
	"context"
	"fmt"
	v1 "kami/api/jd_cookie/v1"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/model"
	"kami/internal/model/do"
	"kami/internal/model/entity"
	"kami/utility/config"
	"kami/utility/utils"

	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/text/gstr"
)

// CreateAccount 创建Cookie账户
func (s *sJdCookie) CreateAccount(ctx context.Context, cookieValue, accountName, remark string) (cookieId string, status int, err error) {
	// 生成唯一的Cookie ID
	cookieId = fmt.Sprintf("jd_%s", utils.GenerateRandomUUID())

	// 清理输入数据
	cookieValue = gstr.Trim(cookieValue)
	accountName = gstr.Trim(accountName)
	remark = gstr.Trim(remark)

	if cookieValue == "" {
		return "", 0, gerror.New("Cookie内容不能为空")
	}

	// 验证Cookie有效性
	glog.Info(ctx, "开始验证新添加的Cookie")
	validationErr := s.validateCookieWithCheckPayment(ctx, cookieValue)
	if validationErr != nil {
		glog.Error(ctx, "Cookie验证失败", g.Map{
			"accountName": accountName,
			"error":       validationErr,
		})
		return "", 0, gerror.Wrap(validationErr, "Cookie无效，无法导入")
	}

	// 插入数据库
	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	_, err = m.Insert(&do.V1JdCookieAccount{
		CookieId:    cookieId,
		CookieValue: cookieValue,
		AccountName: accountName,
		Status:      int(consts.JdCookieStatusNormal),
		Remark:      remark,
	})
	if err != nil {
		return "", 0, gerror.Wrap(err, "创建Cookie账户失败")
	}

	// 记录创建历史（忽略错误）
	go s.RecordCookieHistory(ctx, &model.RecordCookieHistoryReq{
		CookieId:     cookieId,
		ChangeType:   consts.CookieChangeTypeCreate,
		StatusBefore: consts.JdCookieStatusUnknown,
		StatusAfter:  consts.JdCookieStatusNormal,
		OrderId:      "",
		FailureCount: 0,
		Remark:       "创建Cookie账户",
	})

	return
}

// BatchCreateAccount 批量创建Cookie账户
func (s *sJdCookie) BatchCreateAccount(ctx context.Context, cookies []*v1.CreateAccountReq) (successIds []string, failedItems []*v1.BatchCreateResult, err error) {
	successIds = make([]string, 0)
	failedItems = make([]*v1.BatchCreateResult, 0)

	glog.Info(ctx, "开始批量创建Cookie账户", g.Map{
		"totalCookies": len(cookies),
	})

	for i, cookie := range cookies {
		glog.Info(ctx, "正在验证Cookie", g.Map{
			"index":       i + 1,
			"total":       len(cookies),
			"accountName": cookie.AccountName,
		})

		cookieId, _, createErr := s.CreateAccount(ctx, cookie.CookieValue, cookie.AccountName, cookie.Remark)
		if createErr != nil {
			glog.Error(ctx, "Cookie创建失败", g.Map{
				"index":       i + 1,
				"accountName": cookie.AccountName,
				"error":       createErr,
			})
			// 添加失败详情
			failedItem := &v1.BatchCreateResult{
				Index:       i,
				AccountName: cookie.AccountName,
				ErrorMsg:    createErr.Error(),
			}
			failedItems = append(failedItems, failedItem)
			continue
		}

		glog.Info(ctx, "Cookie创建成功", g.Map{
			"index":       i + 1,
			"accountName": cookie.AccountName,
			"cookieId":    cookieId,
		})
		successIds = append(successIds, cookieId)
	}

	glog.Info(ctx, "批量创建Cookie账户完成", g.Map{
		"totalCount":   len(cookies),
		"successCount": len(successIds),
		"failedCount":  len(failedItems),
	})

	return
}

// ListAccount 查询Cookie账户列表
func (s *sJdCookie) ListAccount(ctx context.Context, page, size int, status consts.JdCookieStatus, keyword string) (list []*v1.CookieAccountInfo, total int, err error) {
	if page <= 0 {
		page = 1
	}
	if size <= 0 {
		size = 20
	}

	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())

	// 构建查询条件
	if status > 0 {
		m = m.Where(dao.V1JdCookieAccount.Columns().Status, int(status))
	}
	if keyword != "" {
		keyword = "%" + keyword + "%"
		m = m.WhereOrLike(dao.V1JdCookieAccount.Columns().CookieId, keyword).
			WhereOrLike(dao.V1JdCookieAccount.Columns().AccountName, keyword)
	}

	// 查询总数
	total, err = m.Count()
	if err != nil {
		return nil, 0, gerror.Wrap(err, "查询总数失败")
	}

	// 查询列表数据
	var accounts []*entity.V1JdCookieAccount
	err = m.Page(page, size).OrderDesc(dao.V1JdCookieAccount.Columns().CreatedAt).Scan(&accounts)
	if err != nil {
		return nil, 0, gerror.Wrap(err, "查询账户列表失败")
	}

	// 转换为响应格式
	list = make([]*v1.CookieAccountInfo, 0, len(accounts))
	for _, account := range accounts {
		info := &v1.CookieAccountInfo{
			Id:           account.Id,
			CookieId:     account.CookieId,
			CookieValue:  account.CookieValue,
			AccountName:  account.AccountName,
			Status:       consts.JdCookieStatus(account.Status),
			FailureCount: account.FailureCount,
			LastUsedAt:   account.LastUsedAt,
			SuspendUntil: account.SuspendUntil,
			CreatedAt:    account.CreatedAt,
			UpdatedAt:    account.UpdatedAt,
			DeletedAt:    account.DeletedAt,
			Remark:       account.Remark,
		}

		list = append(list, info)
	}

	return
}

// UpdateAccount 更新Cookie账户
func (s *sJdCookie) UpdateAccount(ctx context.Context, cookieId, cookieValue, accountName string, status consts.JdCookieStatus, remark string) (err error) {
	if cookieId == "" {
		return gerror.New("Cookie ID不能为空")
	}

	// 获取当前账户信息
	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	var currentAccount *entity.V1JdCookieAccount
	err = m.Where(dao.V1JdCookieAccount.Columns().CookieId, cookieId).Scan(&currentAccount)
	if err != nil {
		return gerror.Wrap(err, "查询当前账户信息失败")
	}
	if currentAccount == nil {
		return gerror.New(consts.ErrCodeCookieNotFound)
	}

	// 构建更新数据
	updateData := &do.V1JdCookieAccount{}
	statusBefore := currentAccount.Status

	if cookieValue != "" {
		updateData.CookieValue = gstr.Trim(cookieValue)
	}
	if accountName != "" {
		updateData.AccountName = gstr.Trim(accountName)
	}
	if status > 0 {
		updateData.Status = int(status)
		// 如果恢复为正常状态，重置失败计数
		if status == consts.JdCookieStatusNormal {
			updateData.FailureCount = 0
			updateData.SuspendUntil = nil
		}
	}
	if remark != "" {
		updateData.Remark = gstr.Trim(remark)
	}

	// 执行更新
	_, err = m.Where(dao.V1JdCookieAccount.Columns().CookieId, cookieId).Update(updateData)
	if err != nil {
		return gerror.Wrap(err, "更新Cookie账户失败")
	}

	// 记录变更历史
	var changeType consts.CookieChangeType
	var statusAfter consts.JdCookieStatus
	shouldRecordHistory := false

	if status > 0 && int(status) != statusBefore {
		// 状态变更
		shouldRecordHistory = true
		if status == consts.JdCookieStatusSuspend {
			changeType = consts.CookieChangeTypeSuspend
		} else if status == consts.JdCookieStatusNormal {
			changeType = consts.CookieChangeTypeResume
		} else if status == consts.JdCookieStatusExpired {
			changeType = consts.CookieChangeTypeFail
		}
		statusAfter = status
	} else if (cookieValue != "" && cookieValue != currentAccount.CookieValue) ||
		(accountName != "" && accountName != currentAccount.AccountName) ||
		(remark != "" && remark != currentAccount.Remark) {
		// 非状态变更（内容更新）
		shouldRecordHistory = true
		changeType = consts.CookieChangeTypeUpdate
		statusAfter = consts.JdCookieStatus(currentAccount.Status)
	}

	if shouldRecordHistory {
		err = s.RecordCookieHistory(ctx, &model.RecordCookieHistoryReq{
			CookieId:     cookieId,
			ChangeType:   changeType,
			StatusBefore: consts.JdCookieStatus(statusBefore),
			StatusAfter:  statusAfter,
			OrderId:      "",
			FailureCount: currentAccount.FailureCount,
			Remark:       "更新Cookie账户",
		})
		if err != nil {
			glog.Error(ctx, "记录Cookie变更历史失败", err)
		}
	}

	return
}

// DeleteAccount 删除Cookie账户
func (s *sJdCookie) DeleteAccount(ctx context.Context, cookieId string) (err error) {
	if cookieId == "" {
		return gerror.New("Cookie ID不能为空")
	}

	// 获取当前账户信息用于记录历史
	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	var currentAccount *entity.V1JdCookieAccount
	err = m.Where(dao.V1JdCookieAccount.Columns().CookieId, cookieId).Scan(&currentAccount)
	if err != nil {
		return gerror.Wrap(err, "查询当前账户信息失败")
	}
	if currentAccount == nil {
		return gerror.New(consts.ErrCodeCookieNotFound)
	}

	// 执行删除操作
	result, err := m.Where(dao.V1JdCookieAccount.Columns().CookieId, cookieId).Delete()
	if err != nil {
		return gerror.Wrap(err, "删除Cookie账户失败")
	}

	affected, _ := result.RowsAffected()
	if affected == 0 {
		return gerror.New(consts.ErrCodeCookieNotFound)
	}

	// 记录删除历史
	_ = s.RecordCookieHistory(ctx, &model.RecordCookieHistoryReq{
		CookieId:     cookieId,
		ChangeType:   consts.CookieChangeTypeDelete,
		StatusBefore: consts.JdCookieStatus(currentAccount.Status),
		StatusAfter:  consts.JdCookieStatusUnknown,
		OrderId:      "",
		FailureCount: currentAccount.FailureCount,
		Remark:       "删除Cookie账户",
	})

	return
}

// BatchDeleteAccount 批量删除Cookie账户
func (s *sJdCookie) BatchDeleteAccount(ctx context.Context, cookieIds []string) (successIds []string, failedCount int, err error) {
	if len(cookieIds) == 0 {
		return []string{}, 0, nil
	}

	successIds = make([]string, 0)
	failedCount = 0

	for _, cookieId := range cookieIds {
		deleteErr := s.DeleteAccount(ctx, cookieId)
		if deleteErr != nil {
			failedCount++
			glog.Warning(ctx, "批量删除Cookie失败", g.Map{
				"cookieId": cookieId,
				"error":    deleteErr,
			})
			continue
		}
		successIds = append(successIds, cookieId)
	}

	return
}

// GetAccount 获取单个Cookie账户
func (s *sJdCookie) GetAccount(ctx context.Context, cookieId string) (account *v1.CookieAccountInfo, err error) {
	if cookieId == "" {
		return nil, gerror.New("Cookie ID不能为空")
	}

	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	var accountEntity *entity.V1JdCookieAccount
	err = m.Where(dao.V1JdCookieAccount.Columns().CookieId, cookieId).Scan(&accountEntity)
	if err != nil {
		return nil, gerror.Wrap(err, "查询Cookie账户失败")
	}
	if accountEntity == nil {
		return nil, gerror.New(consts.ErrCodeCookieNotFound)
	}

	account = &v1.CookieAccountInfo{
		Id:           accountEntity.Id,
		CookieId:     accountEntity.CookieId,
		CookieValue:  accountEntity.CookieValue,
		AccountName:  accountEntity.AccountName,
		Status:       consts.JdCookieStatus(accountEntity.Status),
		FailureCount: accountEntity.FailureCount,
		LastUsedAt:   accountEntity.LastUsedAt,
		SuspendUntil: accountEntity.SuspendUntil,
		CreatedAt:    accountEntity.CreatedAt,
		UpdatedAt:    accountEntity.UpdatedAt,
		DeletedAt:    accountEntity.DeletedAt,
		Remark:       accountEntity.Remark,
	}

	return
}

// DeleteInvalidCookies 删除所有失效的Cookie
func (s *sJdCookie) DeleteInvalidCookies(ctx context.Context) (deletedCount int, successIds []string, failedCount int, results []*v1.CookieDeleteResult, err error) {
	// 查询所有失效状态的Cookie
	m := dao.V1JdCookieAccount.Ctx(ctx).DB(config.GetDatabaseV1())
	var invalidAccounts []*entity.V1JdCookieAccount

	// 查询失效状态的Cookie (status = 3)
	err = m.Where(dao.V1JdCookieAccount.Columns().Status, int(consts.JdCookieStatusExpired)).
		Scan(&invalidAccounts)
	if err != nil {
		return 0, nil, 0, nil, gerror.Wrap(err, "查询失效Cookie失败")
	}

	// 如果没有失效的Cookie，直接返回
	if len(invalidAccounts) == 0 {
		return 0, []string{}, 0, []*v1.CookieDeleteResult{}, nil
	}

	// 提取失效Cookie的ID和账户信息映射
	invalidCookieIds := make([]string, 0, len(invalidAccounts))
	accountMap := make(map[string]*entity.V1JdCookieAccount)
	for _, account := range invalidAccounts {
		invalidCookieIds = append(invalidCookieIds, account.CookieId)
		accountMap[account.CookieId] = account
	}

	// 直接执行批量删除操作，优化性能
	_, err = m.WhereIn(dao.V1JdCookieAccount.Columns().CookieId, invalidCookieIds).Delete()
	if err != nil {
		return 0, nil, 0, nil, gerror.Wrap(err, "批量删除失效Cookie失败")
	}

	// 记录删除历史（异步批量记录）
	go func() {
		for _, account := range invalidAccounts {
			_ = s.RecordCookieHistory(ctx, &model.RecordCookieHistoryReq{
				CookieId:     account.CookieId,
				ChangeType:   consts.CookieChangeTypeBatchDelete,
				StatusBefore: consts.JdCookieStatus(account.Status),
				StatusAfter:  consts.JdCookieStatusUnknown,
				OrderId:      "",
				FailureCount: account.FailureCount,
				Remark:       "批量删除失效Cookie",
			})
		}
	}()

	deletedCount = len(invalidCookieIds)
	successIds = invalidCookieIds
	failedCount = 0

	// 构建删除结果详情
	results = make([]*v1.CookieDeleteResult, 0, len(invalidCookieIds))
	for _, cookieId := range invalidCookieIds {
		result := &v1.CookieDeleteResult{
			CookieId: cookieId,
			Success:  true,
			Message:  "删除成功",
		}
		results = append(results, result)
	}

	return
}

// ValidateCookie 验证单个Cookie是否有效
func (s *sJdCookie) ValidateCookie(ctx context.Context, cookieValue string) (isValid bool, message string, cookieId string, err error) {
	// 清理输入数据
	cookieValue = gstr.Trim(cookieValue)
	if cookieValue == "" {
		return false, "Cookie内容不能为空", "", nil
	}

	glog.Info(ctx, "开始验证Cookie有效性")

	// 使用现有的验证方法
	validationErr := s.validateCookieWithCheckPayment(ctx, cookieValue)
	if validationErr != nil {
		glog.Error(ctx, "Cookie验证失败", g.Map{
			"error": validationErr,
		})
		return false, validationErr.Error(), "", nil
	}

	// 生成一个可能的Cookie ID（用于展示，不保存到数据库）
	cookieId = fmt.Sprintf("jd_%s", utils.GenerateRandomUUID())

	glog.Info(ctx, "Cookie验证成功")
	return true, "Cookie有效", cookieId, nil
}

// BatchValidateCookie 批量验证Cookie是否有效
func (s *sJdCookie) BatchValidateCookie(ctx context.Context, cookies []*v1.ValidateCookieItem) (results []*v1.BatchValidateResult, totalCount int, validCount int, invalidCount int, err error) {
	totalCount = len(cookies)
	results = make([]*v1.BatchValidateResult, 0, totalCount)

	glog.Info(ctx, "开始批量验证Cookie", g.Map{
		"totalCount": totalCount,
	})

	for i, cookie := range cookies {
		glog.Info(ctx, "正在验证Cookie", g.Map{
			"index":       i + 1,
			"total":       totalCount,
			"accountName": cookie.AccountName,
		})

		// 清理输入数据
		cookieValue := gstr.Trim(cookie.CookieValue)
		if cookieValue == "" {
			glog.Error(ctx, "Cookie内容不能为空")
			result := &v1.BatchValidateResult{
				Index:       i,
				AccountName: cookie.AccountName,
				IsValid:     false,
				Message:     "Cookie内容不能为空",
				CookieId:    "",
			}
			results = append(results, result)
			invalidCount++
			continue
		}

		// 验证Cookie有效性
		validationErr := s.validateCookieWithCheckPayment(ctx, cookieValue)
		if validationErr != nil {
			glog.Error(ctx, "Cookie验证失败", g.Map{
				"index":       i + 1,
				"accountName": cookie.AccountName,
				"error":       validationErr,
			})
			result := &v1.BatchValidateResult{
				Index:       i,
				AccountName: cookie.AccountName,
				IsValid:     false,
				Message:     validationErr.Error(),
				CookieId:    "",
			}
			results = append(results, result)
			invalidCount++
			continue
		}

		// 生成一个可能的Cookie ID（用于展示，不保存到数据库）
		cookieId := fmt.Sprintf("jd_%s", utils.GenerateRandomUUID())

		glog.Info(ctx, "Cookie验证成功", g.Map{
			"index":       i + 1,
			"accountName": cookie.AccountName,
			"cookieId":    cookieId,
		})

		result := &v1.BatchValidateResult{
			Index:       i,
			AccountName: cookie.AccountName,
			IsValid:     true,
			Message:     "Cookie有效",
			CookieId:    cookieId,
		}
		results = append(results, result)
		validCount++
	}

	glog.Info(ctx, "批量验证Cookie完成", g.Map{
		"totalCount":   totalCount,
		"validCount":   validCount,
		"invalidCount": invalidCount,
	})

	return
}
