package gc.mda.kcg.permission;

import gc.mda.kcg.permission.dto.PermissionUpdateRequest;
import gc.mda.kcg.permission.dto.RoleCreateRequest;
import gc.mda.kcg.permission.dto.RoleUpdateRequest;
import gc.mda.kcg.permission.dto.UserRoleAssignRequest;
import gc.mda.kcg.permission.annotation.RequirePermission;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 권한 트리 + 역할 + 사용자 역할 배정 API.
 * - 트리 조회: 모든 사용자
 * - 역할/권한 CRUD: admin:role-management 또는 admin:permission-management
 * - 사용자 역할 배정: admin:user-management (UPDATE)
 */
@RestController
@RequiredArgsConstructor
public class PermTreeController {

    private final PermTreeRepository permTreeRepository;
    private final RoleRepository roleRepository;
    private final PermRepository permRepository;
    private final RoleManagementService roleManagementService;

    // ========================================================================
    // 권한 트리 (모든 사용자)
    // ========================================================================

    @GetMapping("/api/perm-tree")
    public List<PermTree> getPermTree() {
        return permTreeRepository.findAllByOrderByRsrcLevelAscSortOrdAsc();
    }

    // ========================================================================
    // 역할 조회 + 권한 매트릭스
    // ========================================================================

    @GetMapping("/api/roles")
    @RequirePermission(resource = "admin:role-management", operation = "READ")
    public List<Map<String, Object>> getRolesWithPermissions() {
        List<Role> roles = roleRepository.findAllByOrderByRoleSnAsc();
        return roles.stream().<Map<String, Object>>map(r -> {
            List<Perm> perms = permRepository.findByRoleSn(r.getRoleSn());
            java.util.Map<String, Object> result = new java.util.LinkedHashMap<>();
            result.put("roleSn", r.getRoleSn());
            result.put("roleCd", r.getRoleCd());
            result.put("roleNm", r.getRoleNm());
            result.put("roleDc", r.getRoleDc() == null ? "" : r.getRoleDc());
            result.put("colorHex", r.getColorHex());
            result.put("dfltYn", r.getDfltYn());
            result.put("builtinYn", r.getBuiltinYn());
            result.put("permissions", perms);
            return result;
        }).toList();
    }

    // ========================================================================
    // 역할 CRUD
    // ========================================================================

    @PostMapping("/api/roles")
    @RequirePermission(resource = "admin:role-management", operation = "CREATE")
    public Role createRole(@Valid @RequestBody RoleCreateRequest req) {
        return roleManagementService.createRole(req);
    }

    @PutMapping("/api/roles/{roleSn}")
    @RequirePermission(resource = "admin:role-management", operation = "UPDATE")
    public Role updateRole(@PathVariable Long roleSn, @RequestBody RoleUpdateRequest req) {
        return roleManagementService.updateRole(roleSn, req);
    }

    @DeleteMapping("/api/roles/{roleSn}")
    @RequirePermission(resource = "admin:role-management", operation = "DELETE")
    public Map<String, Object> deleteRole(@PathVariable Long roleSn) {
        roleManagementService.deleteRole(roleSn);
        return Map.of("ok", true);
    }

    // ========================================================================
    // 권한 매트릭스 일괄 갱신
    // ========================================================================

    @PutMapping("/api/roles/{roleSn}/permissions")
    @RequirePermission(resource = "admin:permission-management", operation = "UPDATE")
    public Map<String, Object> updatePermissions(
            @PathVariable Long roleSn,
            @Valid @RequestBody PermissionUpdateRequest req
    ) {
        int changed = roleManagementService.updatePermissions(roleSn, req);
        return Map.of("ok", true, "changed", changed);
    }

    // ========================================================================
    // 사용자 역할 배정
    // ========================================================================

    @PutMapping("/api/admin/users/{userId}/roles")
    @RequirePermission(resource = "admin:user-management", operation = "UPDATE")
    public Map<String, Object> assignUserRoles(
            @PathVariable String userId,
            @RequestBody UserRoleAssignRequest req
    ) {
        UUID uid = UUID.fromString(userId);
        List<Long> roleSns = req.roleSns() == null ? List.of() : req.roleSns();
        List<String> assigned = roleManagementService.assignUserRoles(uid, roleSns);
        return Map.of("userId", userId, "roles", assigned);
    }
}
