package com.yaoai.admin.user;

import cn.dev33.satoken.stp.StpUtil;
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.common.PageResult;
import com.yaoai.admin.user.dto.ResetPasswordResponse;
import com.yaoai.admin.user.dto.UserOrganizationRow;
import com.yaoai.admin.user.dto.UserQuery;
import com.yaoai.admin.user.dto.UserStatusRequest;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.domain.entity.User;
import com.yaoai.domain.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class UserAdminService {

    private final UserMapper userMapper;
    private final JdbcTemplate jdbcTemplate;

    public PageResult<UserOrganizationRow> list(UserQuery query) {
        long page = Math.max(1, query.getPage());
        long size = Math.max(1, Math.min(query.getSize(), 100));
        long offset = (page - 1) * size;
        List<Object> args = new ArrayList<>();
        String where = buildOrganizationWhere(query, args);
        Long total = jdbcTemplate.queryForObject("""
                SELECT COUNT(*)
                  FROM users u
                  JOIN tenants t ON t.id = u.tenant_id
                  LEFT JOIN tenant_members tm ON tm.tenant_id = u.tenant_id AND tm.user_id = u.id
                 WHERE %s
                """.formatted(where), Long.class, args.toArray());

        List<Object> dataArgs = new ArrayList<>(args);
        dataArgs.add(size);
        dataArgs.add(offset);
        List<UserOrganizationRow> rows = jdbcTemplate.query("""
                SELECT u.id AS user_id,
                       u.username,
                       u.email,
                       u.phone,
                       u.status,
                       u.last_login_at,
                       t.id AS tenant_id,
                       t.name AS tenant_name,
                       t.slug AS tenant_slug,
                       t.plan AS tenant_plan,
                       t.status AS tenant_status,
                       tm.id AS member_id,
                       u.role AS account_role,
                       COALESCE(tm.role, u.role) AS member_role,
                       tm.position,
                       tm.joined_at,
                       tq.max_members,
                       tq.max_projects,
                       tq.max_concurrent_tasks
                  FROM users u
                  JOIN tenants t ON t.id = u.tenant_id
                  LEFT JOIN tenant_members tm ON tm.tenant_id = u.tenant_id AND tm.user_id = u.id
                  LEFT JOIN tenant_quotas tq ON tq.tenant_id = u.tenant_id
                 WHERE %s
                 ORDER BY t.name ASC,
                          CASE COALESCE(tm.role, u.role)
                              WHEN 'owner' THEN 1
                              WHEN 'admin' THEN 2
                              ELSE 3
                          END,
                          u.created_at DESC
                 LIMIT ? OFFSET ?
                """.formatted(where), BeanPropertyRowMapper.newInstance(UserOrganizationRow.class), dataArgs.toArray());
        rows.forEach(this::fillHierarchyText);
        return new PageResult<>(rows, total == null ? 0 : total, page, size);
    }

    public User detail(Long id) {
        return requireUser(id);
    }

    @Transactional
    public User updateStatus(Long id, UserStatusRequest request) {
        User user = requireUser(id);
        if (request.getStatus() == null || (request.getStatus() != 0 && request.getStatus() != 1)) {
            throw new BizException(ErrorCode.INVALID_PARAM, "用户状态必须为 0 或 1");
        }
        user.setStatus(request.getStatus());
        user.setUpdatedAt(LocalDateTime.now());
        userMapper.updateById(user);
        if (request.getStatus() == 0) {
            StpUtil.kickout(id);
        }
        return userMapper.selectById(id);
    }

    public void kickout(Long id) {
        requireUser(id);
        StpUtil.kickout(id);
    }

    @Transactional
    public ResetPasswordResponse resetPassword(Long id) {
        User user = requireUser(id);
        String password = "YaoAI-" + RandomUtil.randomString(10);
        user.setPasswordHash(BCrypt.hashpw(password, BCrypt.gensalt()));
        user.setUpdatedAt(LocalDateTime.now());
        userMapper.updateById(user);
        StpUtil.kickout(id);
        return new ResetPasswordResponse(password);
    }

    private LambdaQueryWrapper<User> buildQuery(UserQuery query) {
        LambdaQueryWrapper<User> wrapper = Wrappers.<User>lambdaQuery()
                .isNull(User::getDeletedAt);
        if (query.getTenantId() != null) {
            wrapper.eq(User::getTenantId, query.getTenantId());
        }
        if (query.getStatus() != null) {
            wrapper.eq(User::getStatus, query.getStatus());
        }
        if (StringUtils.hasText(query.getKeyword())) {
            wrapper.and(w -> w.like(User::getEmail, query.getKeyword())
                    .or()
                    .like(User::getUsername, query.getKeyword())
                    .or()
                    .like(User::getPhone, query.getKeyword()));
        }
        return wrapper;
    }

    private String buildOrganizationWhere(UserQuery query, List<Object> args) {
        List<String> clauses = new ArrayList<>();
        clauses.add("u.deleted_at IS NULL");
        clauses.add("t.deleted_at IS NULL");
        if (query.getTenantId() != null) {
            clauses.add("u.tenant_id = ?");
            args.add(query.getTenantId());
        }
        if (query.getStatus() != null) {
            clauses.add("u.status = ?");
            args.add(query.getStatus());
        }
        if (StringUtils.hasText(query.getKeyword())) {
            String keyword = "%" + query.getKeyword().trim() + "%";
            clauses.add("(u.email LIKE ? OR u.username LIKE ? OR u.phone LIKE ? OR t.name LIKE ? OR t.slug LIKE ?)");
            args.add(keyword);
            args.add(keyword);
            args.add(keyword);
            args.add(keyword);
            args.add(keyword);
        }
        return String.join(" AND ", clauses);
    }

    private void fillHierarchyText(UserOrganizationRow row) {
        String role = row.getMemberRole() == null ? row.getAccountRole() : row.getMemberRole();
        if ("owner".equalsIgnoreCase(role)) {
            row.setPermissionScope("企业所有者：企业资料、套餐资源、成员、项目与账务");
        } else if ("admin".equalsIgnoreCase(role)) {
            row.setPermissionScope("企业管理员：项目、资产、成员协作与日常运营");
        } else {
            row.setPermissionScope("企业成员：项目创作、素材使用与本人任务");
        }
        row.setDataBoundary("仅限租户「" + row.getTenantName() + "」ID " + row.getTenantId() + " 的业务数据");
    }

    private User requireUser(Long id) {
        User user = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                .eq(User::getId, id)
                .isNull(User::getDeletedAt));
        if (user == null) {
            throw new BizException(ErrorCode.NOT_FOUND, "用户不存在");
        }
        return user;
    }
}
