package com.hertz.modules.system.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hertz.common.api.ApiResponse;
import com.hertz.modules.system.entity.SysRole;
import com.hertz.modules.system.entity.SysUser;
import com.hertz.modules.system.service.UserService;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/system/users")
public class UserController {
  private final UserService userService;

  public UserController(UserService userService) {
    this.userService = userService;
  }

  @GetMapping
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:view')")
  public ApiResponse<IPage<UserListItem>> page(
      @RequestParam(defaultValue = "1") @Min(1) int page,
      @RequestParam(defaultValue = "10") @Min(1) @Max(200) int size,
      @RequestParam(required = false) String keyword
  ) {
    var p = userService.pageUsers(page, size, keyword);
    var dtoPage = Page.<UserListItem>of(p.getCurrent(), p.getSize(), p.getTotal());
    dtoPage.setRecords(p.getRecords().stream().map(u -> {
      var roles = userService.getUserRoles(u.getId()).stream()
          .map(SysRole::getRoleName)
          .toList();
      return new UserListItem(
          u.getId(),
          u.getUsername(),
          u.getNickname(),
          u.getAvatarPath(),
          u.getPhone(),
          u.getEmail(),
          u.getGender(),
          u.getStatus(),
          u.getCreatedAt(),
          roles
      );
    }).toList());
    return ApiResponse.ok(dtoPage);
  }

  public record UserListItem(
      Long id,
      String username,
      String nickname,
      String avatarPath,
      String phone,
      String email,
      Integer gender,
      Integer status,
      LocalDateTime createdAt,
      List<String> roles
  ) {
  }

  public record CreateUserRequest(
      @NotBlank(message = "用户名不能为空") String username,
      @NotBlank(message = "密码不能为空") String password,
      @NotBlank(message = "昵称不能为空") String nickname,
      String avatarPath,
      String phone,
      String email,
      Integer gender,
      Integer status
  ) {}

  @PostMapping
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:add')")
  public ApiResponse<Void> create(@RequestBody @Valid CreateUserRequest req) {
    var u = new SysUser();
    u.setUsername(req.username());
    u.setPassword(req.password());
    u.setNickname(req.nickname());
    u.setAvatarPath(req.avatarPath());
    u.setPhone(req.phone());
    u.setEmail(req.email());
    u.setGender(req.gender());
    u.setStatus(req.status());
    userService.createUser(u);
    return ApiResponse.ok();
  }

  public record UpdateUserRequest(
      Long id,
      String password,
      @NotBlank(message = "昵称不能为空") String nickname,
      String avatarPath,
      String phone,
      String email,
      Integer gender,
      Integer status
  ) {}

  @PutMapping
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:edit')")
  public ApiResponse<Void> update(@RequestBody @Valid UpdateUserRequest req) {
    var u = new SysUser();
    u.setId(req.id());
    u.setPassword(req.password());
    u.setNickname(req.nickname());
    u.setAvatarPath(req.avatarPath());
    u.setPhone(req.phone());
    u.setEmail(req.email());
    u.setGender(req.gender());
    u.setStatus(req.status());
    userService.updateUser(u);
    return ApiResponse.ok();
  }

  @DeleteMapping("/{id}")
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:remove')")
  public ApiResponse<Void> delete(@PathVariable Long id) {
    userService.deleteUser(id);
    return ApiResponse.ok();
  }

  @DeleteMapping
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:remove')")
  public ApiResponse<Void> deleteBatch(@RequestBody List<Long> ids) {
    userService.deleteUsers(ids);
    return ApiResponse.ok();
  }

  @GetMapping("/{id}/roles")
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:view')")
  public ApiResponse<List<Long>> roleIds(@PathVariable("id") long userId) {
    return ApiResponse.ok(userService.getUserRoleIds(userId));
  }

  public record UpdateRolesRequest(List<Long> roleIds) {
  }

  @PutMapping("/{id}/roles")
  @PreAuthorize("hasRole('ADMIN') or hasAuthority('system:user:assign')")
  public ApiResponse<Void> updateRoles(@PathVariable("id") long userId, @RequestBody UpdateRolesRequest req) {
    userService.updateUserRoles(userId, req == null ? List.of() : req.roleIds());
    return ApiResponse.ok();
  }
}
