package user

import (
	"github.com/veypi/vbase/internal/model"
	"github.com/veypi/vbase/internal/pkg/crypto"
	"github.com/veypi/vigo"
)

// ListRequest 用户列表请求
type ListRequest struct {
	Page     int    `json:"page" src:"query" default:"1" desc:"页码"`
	PageSize int    `json:"page_size" src:"query" default:"10" desc:"每页数量"`
	Keyword  string `json:"keyword" src:"query" desc:"搜索关键词"`
	Status   *int   `json:"status" src:"query" desc:"状态筛选"`
}

// ListResponse 用户列表响应
type ListResponse struct {
	Items      []UserInfo `json:"items"`
	Total      int64      `json:"total"`
	Page       int        `json:"page"`
	PageSize   int        `json:"page_size"`
	TotalPages int        `json:"total_pages"`
}

// UserInfo 用户信息
type UserInfo struct {
	ID            string `json:"id"`
	Username      string `json:"username"`
	Nickname      string `json:"nickname"`
	Avatar        string `json:"avatar"`
	Email         string `json:"email"`
	Phone         string `json:"phone"`
	Status        int    `json:"status"`
	EmailVerified bool   `json:"email_verified"`
	PhoneVerified bool   `json:"phone_verified"`
	LastLoginAt   string `json:"last_login_at,omitempty"`
	CreatedAt     string `json:"created_at"`
}

// List 用户列表
func List(x *vigo.X, req *ListRequest) (*ListResponse, error) {
	if req.Page < 1 {
		req.Page = 1
	}
	if req.PageSize < 1 || req.PageSize > 100 {
		req.PageSize = 10
	}

	var total int64
	query := model.DB.Model(&model.User{})

	if req.Keyword != "" {
		query = query.Where("username LIKE ? OR nickname LIKE ? OR email LIKE ?", "%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
	}
	if req.Status != nil {
		query = query.Where("status = ?", *req.Status)
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	var users []model.User
	offset := (req.Page - 1) * req.PageSize
	if err := query.Offset(offset).Limit(req.PageSize).Order("created_at DESC").Find(&users).Error; err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	items := make([]UserInfo, 0, len(users))
	for _, u := range users {
		items = append(items, toUserInfo(&u))
	}

	totalPages := int((total + int64(req.PageSize) - 1) / int64(req.PageSize))

	return &ListResponse{
		Items:      items,
		Total:      total,
		Page:       req.Page,
		PageSize:   req.PageSize,
		TotalPages: totalPages,
	}, nil
}

// GetRequest 获取用户请求
type GetRequest struct {
	ID string `json:"id" src:"path@user_id" desc:"用户ID"`
}

// Get 获取用户详情
func Get(x *vigo.X, req *GetRequest) (*UserInfo, error) {
	var user model.User
	if err := model.DB.First(&user, "id = ?", req.ID).Error; err != nil {
		return nil, vigo.ErrNotFound
	}

	info := toUserInfo(&user)
	return &info, nil
}

// CreateRequest 创建用户请求
type CreateRequest struct {
	Username string  `json:"username" src:"json" desc:"用户名"`
	Password string  `json:"password" src:"json" desc:"密码"`
	Nickname *string `json:"nickname" src:"json" desc:"昵称"`
	Email    *string `json:"email" src:"json" desc:"邮箱"`
	Phone    *string `json:"phone" src:"json" desc:"手机号"`
	Status   *int    `json:"status" src:"json" desc:"状态"`
}

// Create 创建用户
func Create(x *vigo.X, req *CreateRequest) (*UserInfo, error) {
	// 检查用户名是否已存在
	var count int64
	model.DB.Model(&model.User{}).Where("username = ?", req.Username).Count(&count)
	if count > 0 {
		return nil, vigo.ErrArgInvalid.WithString("username already exists")
	}

	// 检查邮箱是否已存在
	if req.Email != nil && *req.Email != "" {
		model.DB.Model(&model.User{}).Where("email = ?", *req.Email).Count(&count)
		if count > 0 {
			return nil, vigo.ErrArgInvalid.WithString("email already exists")
		}
	}

	// 哈希密码
	hashedPassword, err := crypto.HashPassword(req.Password, 12)
	if err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	// 创建用户
	user := &model.User{
		Username: req.Username,
		Password: hashedPassword,
		Status:   model.UserStatusActive,
	}

	if req.Nickname != nil {
		user.Nickname = *req.Nickname
	} else {
		user.Nickname = req.Username
	}
	if req.Email != nil {
		user.Email = *req.Email
	}
	if req.Phone != nil {
		user.Phone = *req.Phone
	}
	if req.Status != nil {
		user.Status = *req.Status
	}

	if err := model.DB.Create(user).Error; err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	info := toUserInfo(user)
	return &info, nil
}

// UpdateRequest 更新用户请求
type UpdateRequest struct {
	ID       string  `json:"id" src:"path@user_id" desc:"用户ID"`
	Nickname *string `json:"nickname" src:"json" desc:"昵称"`
	Avatar   *string `json:"avatar" src:"json" desc:"头像"`
	Email    *string `json:"email" src:"json" desc:"邮箱"`
	Phone    *string `json:"phone" src:"json" desc:"手机号"`
	Status   *int    `json:"status" src:"json" desc:"状态"`
}

// Update 更新用户
func Update(x *vigo.X, req *UpdateRequest) (*UserInfo, error) {
	var user model.User
	if err := model.DB.First(&user, "id = ?", req.ID).Error; err != nil {
		return nil, vigo.ErrNotFound
	}

	updates := make(map[string]interface{})
	if req.Nickname != nil {
		updates["nickname"] = *req.Nickname
	}
	if req.Avatar != nil {
		updates["avatar"] = *req.Avatar
	}
	if req.Email != nil && *req.Email != user.Email {
		// 检查邮箱是否被其他用户使用
		var count int64
		model.DB.Model(&model.User{}).Where("email = ? AND id != ?", *req.Email, req.ID).Count(&count)
		if count > 0 {
			return nil, vigo.ErrArgInvalid.WithString("email already exists")
		}
		updates["email"] = *req.Email
	}
	if req.Phone != nil && *req.Phone != user.Phone {
		var count int64
		model.DB.Model(&model.User{}).Where("phone = ? AND id != ?", *req.Phone, req.ID).Count(&count)
		if count > 0 {
			return nil, vigo.ErrArgInvalid.WithString("phone already exists")
		}
		updates["phone"] = *req.Phone
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}

	if len(updates) > 0 {
		if err := model.DB.Model(&user).Updates(updates).Error; err != nil {
			return nil, vigo.ErrInternalServer.WithError(err)
		}
	}

	info := toUserInfo(&user)
	return &info, nil
}

// DeleteRequest 删除用户请求
type DeleteRequest struct {
	ID string `json:"id" src:"path@user_id" desc:"用户ID"`
}

// Delete 删除用户（软删除）
func Delete(x *vigo.X, req *DeleteRequest) error {
	var user model.User
	if err := model.DB.First(&user, "id = ?", req.ID).Error; err != nil {
		return vigo.ErrNotFound
	}

	if err := model.DB.Delete(&user).Error; err != nil {
		return vigo.ErrInternalServer.WithError(err)
	}

	return nil
}

// UpdateStatusRequest 更新用户状态请求
type UpdateStatusRequest struct {
	ID     string `json:"id" src:"path@user_id" desc:"用户ID"`
	Status int    `json:"status" src:"json" desc:"状态: 0禁用 1正常 2未激活"`
}

// UpdateStatus 更新用户状态
func UpdateStatus(x *vigo.X, req *UpdateStatusRequest) (*UserInfo, error) {
	var user model.User
	if err := model.DB.First(&user, "id = ?", req.ID).Error; err != nil {
		return nil, vigo.ErrNotFound
	}

	if err := model.DB.Model(&user).Update("status", req.Status).Error; err != nil {
		return nil, vigo.ErrInternalServer.WithError(err)
	}

	info := toUserInfo(&user)
	return &info, nil
}

// helper function
func toUserInfo(u *model.User) UserInfo {
	info := UserInfo{
		ID:            u.ID,
		Username:      u.Username,
		Nickname:      u.Nickname,
		Avatar:        u.Avatar,
		Email:         u.Email,
		Phone:         u.Phone,
		Status:        u.Status,
		EmailVerified: u.EmailVerified,
		PhoneVerified: u.PhoneVerified,
		CreatedAt:     u.CreatedAt.Format("2006-01-02 15:04:05"),
	}
	if u.LastLoginAt != nil {
		info.LastLoginAt = u.LastLoginAt.Format("2006-01-02 15:04:05")
	}
	return info
}
