package com.yaoai.admin.adminuser;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yaoai.admin.adminuser.dto.AdminUserCreateRequest;
import com.yaoai.admin.adminuser.dto.AdminUserQuery;
import com.yaoai.admin.adminuser.dto.AdminUserUpdateRequest;
import com.yaoai.admin.auth.StpAdminUtil;
import com.yaoai.admin.common.PageResult;
import com.yaoai.admin.user.dto.ResetPasswordResponse;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.domain.entity.AdminUser;
import com.yaoai.domain.mapper.AdminUserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Set;

@Service
@RequiredArgsConstructor
public class AdminUserAdminService {

    private static final Set<String> ROLES = Set.of("SUPER_ADMIN", "OPERATOR", "FINANCE", "READONLY");

    private final AdminUserMapper adminUserMapper;

    public PageResult<AdminUser> list(AdminUserQuery query) {
        long page = Math.max(1, query.getPage());
        long size = Math.max(1, Math.min(query.getSize(), 100));
        long offset = (page - 1) * size;
        long total = adminUserMapper.selectCount(buildQuery(query));
        return new PageResult<>(
                adminUserMapper.selectList(buildQuery(query)
                        .orderByDesc(AdminUser::getCreatedAt)
                        .last("LIMIT " + size + " OFFSET " + offset)),
                total,
                page,
                size);
    }

    @Transactional
    public AdminUser create(AdminUserCreateRequest request) {
        if (!StringUtils.hasText(request.getUsername())) {
            throw new BizException(ErrorCode.INVALID_PARAM, "用户名不能为空");
        }
        if (!ROLES.contains(request.getRole())) {
            throw new BizException(ErrorCode.INVALID_PARAM, "运营角色无效");
        }
        if (adminUserMapper.selectCount(Wrappers.<AdminUser>lambdaQuery()
                .eq(AdminUser::getUsername, request.getUsername())) > 0) {
            throw new BizException(ErrorCode.INVALID_PARAM, "用户名已存在");
        }

        String password = StringUtils.hasText(request.getPassword())
                ? request.getPassword()
                : "YaoAI-" + RandomUtil.randomString(10);
        AdminUser user = new AdminUser();
        user.setUsername(request.getUsername());
        user.setPasswordHash(BCrypt.hashpw(password, BCrypt.gensalt()));
        user.setDisplayName(request.getDisplayName());
        user.setEmail(request.getEmail());
        user.setRole(request.getRole());
        user.setStatus(1);
        user.setMustChangePassword(1);
        user.setCreatedBy(StpAdminUtil.getLoginIdAsLong());
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        adminUserMapper.insert(user);
        return adminUserMapper.selectById(user.getId());
    }

    @Transactional
    public AdminUser update(Long id, AdminUserUpdateRequest request) {
        AdminUser user = requireAdminUser(id);
        if (request.getDisplayName() != null) user.setDisplayName(request.getDisplayName());
        if (request.getEmail() != null) user.setEmail(request.getEmail());
        if (request.getRole() != null) {
            if (!ROLES.contains(request.getRole())) {
                throw new BizException(ErrorCode.INVALID_PARAM, "运营角色无效");
            }
            user.setRole(request.getRole());
        }
        if (request.getStatus() != null) {
            if (request.getStatus() != 0 && request.getStatus() != 1) {
                throw new BizException(ErrorCode.INVALID_PARAM, "账号状态必须为 0 或 1");
            }
            user.setStatus(request.getStatus());
        }
        user.setUpdatedAt(LocalDateTime.now());
        adminUserMapper.updateById(user);
        return adminUserMapper.selectById(id);
    }

    @Transactional
    public ResetPasswordResponse resetPassword(Long id) {
        AdminUser user = requireAdminUser(id);
        String password = "YaoAI-" + RandomUtil.randomString(10);
        user.setPasswordHash(BCrypt.hashpw(password, BCrypt.gensalt()));
        user.setMustChangePassword(1);
        user.setUpdatedAt(LocalDateTime.now());
        adminUserMapper.updateById(user);
        StpAdminUtil.INSTANCE.kickout(id);
        return new ResetPasswordResponse(password);
    }

    private LambdaQueryWrapper<AdminUser> buildQuery(AdminUserQuery query) {
        LambdaQueryWrapper<AdminUser> wrapper = Wrappers.<AdminUser>lambdaQuery();
        if (StringUtils.hasText(query.getKeyword())) {
            wrapper.and(w -> w.like(AdminUser::getUsername, query.getKeyword())
                    .or()
                    .like(AdminUser::getDisplayName, query.getKeyword())
                    .or()
                    .like(AdminUser::getEmail, query.getKeyword()));
        }
        if (StringUtils.hasText(query.getRole())) {
            wrapper.eq(AdminUser::getRole, query.getRole());
        }
        if (query.getStatus() != null) {
            wrapper.eq(AdminUser::getStatus, query.getStatus());
        }
        return wrapper;
    }

    private AdminUser requireAdminUser(Long id) {
        AdminUser user = adminUserMapper.selectById(id);
        if (user == null) {
            throw new BizException(ErrorCode.NOT_FOUND, "运营账号不存在");
        }
        return user;
    }
}
