package user

import (
	"context"
	"fmt"
	"os"
	"strings"

	usermodel "github.com/perfect-panel/server/internal/model/user"
	"github.com/perfect-panel/server/internal/config"
	"github.com/perfect-panel/server/internal/model/iap/apple"
	"github.com/perfect-panel/server/internal/model/log"
	"github.com/perfect-panel/server/internal/model/logmessage"
	"github.com/perfect-panel/server/internal/model/order"
	"github.com/perfect-panel/server/internal/model/ticket"
	"github.com/perfect-panel/server/internal/model/traffic"
	"github.com/perfect-panel/server/internal/svc"
	"github.com/perfect-panel/server/internal/types"
	pkglogger "github.com/perfect-panel/server/pkg/logger"
	"github.com/perfect-panel/server/pkg/xerr"
	"github.com/pkg/errors"
	"gorm.io/gorm"
)

type DeleteUserLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	pkglogger.Logger
}

func NewDeleteUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteUserLogic {
	return &DeleteUserLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: pkglogger.WithContext(ctx),
	}
}

func (l *DeleteUserLogic) DeleteUser(req *types.GetDetailRequest) error {
	isDemo := strings.ToLower(os.Getenv("PPANEL_MODE")) == "demo"
	if req.Id == 2 && isDemo {
		return errors.Wrapf(xerr.NewErrCodeMsg(503, "Demo mode does not allow deletion of the admin user"), "delete user failed: cannot delete admin user in demo mode")
	}

	return l.purgeUser(req.Id)
}

// purgeUser 硬删除用户及其所有关联数据，无孤儿数据残留。
// 删除顺序：先删子表（引用 user_id），再删主表（user）。
func (l *DeleteUserLogic) purgeUser(userID int64) error {
	// 1. 事务前：收集需要清缓存的数据
	userInfo, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
		return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "find user failed: %v", err)
	}

	authMethods, _ := l.svcCtx.UserModel.FindUserAuthMethods(l.ctx, userID)
	subscribes, _ := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, userID)

	// 2. 查 ticket id 列表（ticket_follow 通过 ticket_id 关联，需要先查再删）
	var ticketIDs []int64
	l.svcCtx.DB.WithContext(l.ctx).Model(&ticket.Ticket{}).
		Where("user_id = ?", userID).Pluck("id", &ticketIDs)

	// 3. 查家庭关系（需要处理家庭解散）
	var familyMember usermodel.UserFamilyMember
	isFamilyOwner := false
	var familyID int64
	if err := l.svcCtx.DB.WithContext(l.ctx).
		Model(&usermodel.UserFamilyMember{}).
		Where("user_id = ?", userID).
		First(&familyMember).Error; err == nil {
		familyID = familyMember.FamilyId
		var family usermodel.UserFamily
		if err2 := l.svcCtx.DB.WithContext(l.ctx).
			Where("id = ?", familyID).First(&family).Error; err2 == nil {
			isFamilyOwner = (family.OwnerUserId == userID)
		}
	}

	// 4. 事务内：按顺序删除所有关联表，最后删 user
	err = l.svcCtx.DB.WithContext(l.ctx).Transaction(func(tx *gorm.DB) error {
		// 4a. 家庭处理
		if familyID > 0 {
			if isFamilyOwner {
				// 家主：解散整个家庭（删所有成员记录 + 删家庭）
				if e := tx.Unscoped().Where("family_id = ?", familyID).
					Delete(&usermodel.UserFamilyMember{}).Error; e != nil {
					return e
				}
				if e := tx.Unscoped().Where("id = ?", familyID).
					Delete(&usermodel.UserFamily{}).Error; e != nil {
					return e
				}
			} else {
				// 成员：只删自己的成员记录
				if e := tx.Unscoped().Where("user_id = ? AND family_id = ?", userID, familyID).
					Delete(&usermodel.UserFamilyMember{}).Error; e != nil {
					return e
				}
			}
		}

		// 4b. 用户认证方式
		if e := tx.Unscoped().Where("user_id = ?", userID).
			Delete(&usermodel.AuthMethods{}).Error; e != nil {
			return e
		}

		// 4c. 订阅
		if e := tx.Unscoped().Where("user_id = ?", userID).
			Delete(&usermodel.Subscribe{}).Error; e != nil {
			return e
		}

		// 4d. 设备 + 设备在线记录
		if e := tx.Where("user_id = ?", userID).
			Delete(&usermodel.Device{}).Error; e != nil {
			return e
		}
		if e := tx.Where("user_id = ?", userID).
			Delete(&usermodel.DeviceOnlineRecord{}).Error; e != nil {
			return e
		}

		// 4e. 提现记录
		if e := tx.Where("user_id = ?", userID).
			Delete(&usermodel.Withdrawal{}).Error; e != nil {
			return e
		}

		// 4f. 订单
		if e := tx.Where("user_id = ?", userID).
			Delete(&order.Order{}).Error; e != nil {
			return e
		}

		// 4g. 流量日志
		if e := tx.Where("user_id = ?", userID).
			Delete(&traffic.TrafficLog{}).Error; e != nil {
			return e
		}

		// 4h. 系统日志（object_id = userID）
		if e := tx.Where("object_id = ?", userID).
			Delete(&log.SystemLog{}).Error; e != nil {
			return e
		}

		// 4i. 工单 follow + 工单
		if len(ticketIDs) > 0 {
			if e := tx.Where("ticket_id IN ?", ticketIDs).
				Delete(&ticket.Follow{}).Error; e != nil {
				return e
			}
		}
		if e := tx.Where("user_id = ?", userID).
			Delete(&ticket.Ticket{}).Error; e != nil {
			return e
		}

		// 4j. Apple IAP 交易记录
		if e := tx.Where("user_id = ?", userID).
			Delete(&apple.Transaction{}).Error; e != nil {
			return e
		}

		// 4k. 日志消息
		if e := tx.Where("user_id = ?", userID).
			Delete(&logmessage.LogMessage{}).Error; e != nil {
			return e
		}

		// 4l. 最后删除 user（Unscoped = 物理删除）
		if e := tx.Unscoped().Where("id = ?", userID).
			Delete(&usermodel.User{}).Error; e != nil {
			return e
		}

		return nil
	})
	if err != nil {
		return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseDeletedError), "purge user %d failed: %v", userID, err)
	}

	// 5. 事务后：清缓存 + 踢设备
	l.cleanupAfterDelete(userID, userInfo, authMethods, subscribes)

	return nil
}

func (l *DeleteUserLogic) cleanupAfterDelete(
	userID int64,
	userInfo *usermodel.User,
	authMethods []*usermodel.AuthMethods,
	subscribes []*usermodel.SubscribeDetails,
) {
	// 踢设备
	var devices []usermodel.Device
	l.svcCtx.DB.WithContext(l.ctx).Where("user_id = ?", userID).Find(&devices)
	for _, d := range devices {
		l.svcCtx.DeviceManager.KickDevice(d.UserId, d.Identifier)
	}

	// 清 session
	l.clearAllSessions(userID)

	// 清 email 缓存
	var emailKeys []string
	for _, am := range authMethods {
		if am.AuthType == "email" && am.AuthIdentifier != "" {
			emailKeys = append(emailKeys, fmt.Sprintf("cache:user:email:%s", am.AuthIdentifier))
		}
	}
	if len(emailKeys) > 0 {
		if e := l.svcCtx.Redis.Del(l.ctx, emailKeys...).Err(); e != nil {
			l.Errorw("clear email cache failed", pkglogger.Field("user_id", userID), pkglogger.Field("error", e.Error()))
		}
	}

	// 清 user 缓存
	if userInfo != nil {
		if e := l.svcCtx.UserModel.ClearUserCache(l.ctx, userInfo); e != nil {
			l.Errorw("clear user cache failed", pkglogger.Field("user_id", userID), pkglogger.Field("error", e.Error()))
		}
	}

	// 清订阅缓存
	subModels := make([]*usermodel.Subscribe, 0, len(subscribes)+1)
	subModels = append(subModels, &usermodel.Subscribe{UserId: userID})
	for _, s := range subscribes {
		subModels = append(subModels, &usermodel.Subscribe{
			Id: s.Id, UserId: s.UserId, SubscribeId: s.SubscribeId, Token: s.Token,
		})
	}
	if e := l.svcCtx.UserModel.ClearSubscribeCache(l.ctx, subModels...); e != nil {
		l.Errorw("clear subscribe cache failed", pkglogger.Field("user_id", userID), pkglogger.Field("error", e.Error()))
	}
}

// clearAllSessions 清理用户所有 session
func (l *DeleteUserLogic) clearAllSessions(userID int64) {
	sessionsKey := fmt.Sprintf("%s%d", config.UserSessionsKeyPrefix, userID)
	sessions, _ := l.svcCtx.Redis.ZRange(l.ctx, sessionsKey, 0, -1).Result()
	pipe := l.svcCtx.Redis.TxPipeline()
	for _, sid := range sessions {
		pipe.Del(l.ctx, fmt.Sprintf("%s:%s", config.SessionIdKey, sid))
		pipe.Del(l.ctx, fmt.Sprintf("%s:detail:%s", config.SessionIdKey, sid))
		pipe.ZRem(l.ctx, sessionsKey, sid)
	}
	pipe.Del(l.ctx, sessionsKey)
	if _, e := pipe.Exec(l.ctx); e != nil {
		l.Errorw("clear sessions failed", pkglogger.Field("user_id", userID), pkglogger.Field("error", e.Error()))
	}
}
