package gc.mda.kcg.admin;

import gc.mda.kcg.audit.annotation.Auditable;
import gc.mda.kcg.auth.User;
import gc.mda.kcg.auth.UserRepository;
import gc.mda.kcg.permission.PermissionService;
import gc.mda.kcg.permission.UserRoleRepository;
import gc.mda.kcg.permission.annotation.RequirePermission;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 사용자 관리 API.
 * 권한: admin:user-management
 */
@Slf4j
@RestController
@RequestMapping("/api/admin/users")
@RequiredArgsConstructor
public class UserManagementController {

    private final UserRepository userRepository;
    private final UserRoleRepository userRoleRepository;
    private final PermissionService permissionService;

    /**
     * 사용자 목록 조회 (역할 코드 포함).
     */
    @GetMapping
    @RequirePermission(resource = "admin:user-management", operation = "READ")
    public List<Map<String, Object>> listUsers() {
        List<User> users = userRepository.findAll(
                org.springframework.data.domain.Sort.by("userAcnt").ascending());

        return users.stream().<Map<String, Object>>map(u -> {
            List<String> roles = userRoleRepository.findRoleCodesByUserId(u.getUserId());
            Map<String, Object> m = new LinkedHashMap<>();
            m.put("userId", u.getUserId().toString());
            m.put("userAcnt", u.getUserAcnt());
            m.put("userNm", u.getUserNm());
            m.put("rnkpNm", u.getRnkpNm());
            m.put("email", u.getEmail());
            m.put("userSttsCd", u.getUserSttsCd());
            m.put("authProvider", u.getAuthProvider());
            m.put("failCnt", u.getFailCnt());
            m.put("lastLoginDtm", u.getLastLoginDtm());
            m.put("createdAt", u.getCreatedAt());
            m.put("roles", roles);
            return m;
        }).toList();
    }

    /**
     * 사용자 통계 (역할별 카운트, 상태별 카운트).
     */
    @GetMapping("/stats")
    @RequirePermission(resource = "admin:user-management", operation = "READ")
    public Map<String, Object> stats() {
        List<User> users = userRepository.findAll();

        Map<String, Long> byStatus = users.stream()
                .collect(Collectors.groupingBy(User::getUserSttsCd, Collectors.counting()));

        Map<String, Long> byProvider = users.stream()
                .collect(Collectors.groupingBy(User::getAuthProvider, Collectors.counting()));

        // 역할별 사용자 수
        Map<String, Long> byRole = new LinkedHashMap<>();
        for (User u : users) {
            for (String role : userRoleRepository.findRoleCodesByUserId(u.getUserId())) {
                byRole.merge(role, 1L, Long::sum);
            }
        }

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("total", (long) users.size());
        result.put("active", byStatus.getOrDefault("ACTIVE", 0L));
        result.put("locked", byStatus.getOrDefault("LOCKED", 0L));
        result.put("inactive", byStatus.getOrDefault("INACTIVE", 0L));
        result.put("pending", byStatus.getOrDefault("PENDING", 0L));
        result.put("byStatus", byStatus);
        result.put("byProvider", byProvider);
        result.put("byRole", byRole);
        return result;
    }

    /**
     * 잠긴 계정 해제.
     */
    @Auditable(action = "USER_UNLOCK", resourceType = "USER")
    @PostMapping("/{userId}/unlock")
    @RequirePermission(resource = "admin:user-management", operation = "UPDATE")
    public Map<String, Object> unlockUser(@PathVariable String userId) {
        UUID uid = UUID.fromString(userId);
        User user = userRepository.findById(uid)
                .orElseThrow(() -> new IllegalArgumentException("USER_NOT_FOUND: " + userId));

        user.setUserSttsCd("ACTIVE");
        user.setFailCnt(0);
        userRepository.save(user);
        permissionService.evictUserPermissions(uid);

        log.info("계정 잠금 해제: {}", user.getUserAcnt());
        return Map.of(
                "userId", userId,
                "userAcnt", user.getUserAcnt(),
                "userSttsCd", user.getUserSttsCd()
        );
    }

    /**
     * 계정 상태 변경 (ACTIVE/LOCKED/INACTIVE).
     */
    @Auditable(action = "USER_STATUS_CHANGE", resourceType = "USER")
    @PutMapping("/{userId}/status")
    @RequirePermission(resource = "admin:user-management", operation = "UPDATE")
    public Map<String, Object> changeStatus(@PathVariable String userId, @RequestBody Map<String, String> body) {
        String newStatus = body.get("status");
        if (newStatus == null || !Set.of("ACTIVE", "LOCKED", "INACTIVE", "PENDING").contains(newStatus)) {
            throw new IllegalArgumentException("INVALID_STATUS: " + newStatus);
        }
        UUID uid = UUID.fromString(userId);
        User user = userRepository.findById(uid)
                .orElseThrow(() -> new IllegalArgumentException("USER_NOT_FOUND: " + userId));
        user.setUserSttsCd(newStatus);
        if ("ACTIVE".equals(newStatus)) {
            user.setFailCnt(0);
        }
        userRepository.save(user);
        permissionService.evictUserPermissions(uid);

        return Map.of("userId", userId, "userAcnt", user.getUserAcnt(), "userSttsCd", newStatus);
    }
}
