package com.ffii.core.user.web;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.ServletRequestBindingException;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.ffii.core.common.ErrorCodes;
import com.ffii.core.exception.NotFoundException;
import com.ffii.core.exception.UnprocessableEntityException;
import com.ffii.core.response.IdRes;
import com.ffii.core.response.RecordsRes;
import com.ffii.core.support.AbstractController;
import com.ffii.core.user.req.SaveGroupReq;
import com.ffii.core.user.service.GroupService;
import com.ffii.core.utils.CriteriaArgsBuilder;
import com.ffii.core.utils.Params;

@RestController
@RequestMapping(value = "/protected/group")
public class GroupController extends AbstractController {

  private GroupService groupService;

  public GroupController(GroupService groupService) {
    this.groupService = groupService;
  }

  @PostMapping("/save")
  @PreAuthorize("hasAuthority('EDIT_USER_GROUP')")
  public IdRes saveOrUpdate(@RequestBody @Valid SaveGroupReq req) {
    return new IdRes(groupService.saveOrUpdate(req).getId());
  }

  @DeleteMapping("/{id}")
  @PreAuthorize("hasAuthority('EDIT_USER_GROUP')")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  public void delete(@PathVariable int id) {
    if (!groupService.existsActiveUser(id)) {
      groupService.delete(groupService.find(id).orElseThrow(NotFoundException::new));
    } else {
      throw new UnprocessableEntityException(ErrorCodes.DELETE_USER_GROUP_ERROR);
    }
  }

  @GetMapping("/{id}")
  public Map<String, Object> load(@PathVariable int id) {
    return Map.of(
        Params.DATA, groupService.find(id).orElseThrow(NotFoundException::new),
        "authIds", groupService.listGroupAuthId(id),
        "userIds", groupService.listGroupUserId(id));
  }

  @GetMapping("/combo")
  public RecordsRes<Map<String, Object>> comboJson(HttpServletRequest request) throws ServletRequestBindingException {
    return new RecordsRes<>(groupService.searchForCombo(
        CriteriaArgsBuilder.withRequest(request)
            .addInteger(Params.ID)
            .addStringLike(Params.QUERY)
            .build()));
  }

  @GetMapping
  public RecordsRes<Map<String, Object>> listJson(HttpServletRequest request) throws ServletRequestBindingException {
    return new RecordsRes<>(groupService.search(
        CriteriaArgsBuilder.withRequest(request)
            .addInteger(Params.ID)
            .addStringLike(Params.NAME)
            .addInteger("userId")
            .build()));
  }

}
