package com.ffii.core.department.web;

import java.util.Map;

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

import org.springframework.beans.BeanUtils;
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.PutMapping;
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.department.entity.Department;
import com.ffii.core.department.req.SaveDepartmentReq;
import com.ffii.core.department.service.DepartmentService;
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.utils.CriteriaArgsBuilder;
import com.ffii.core.utils.Params;

@RestController
@RequestMapping("/protected/department")
public class DepartmentController extends AbstractController {

  private DepartmentService departmentService;

  public DepartmentController(DepartmentService departmentService) {
    this.departmentService = departmentService;
  }

  @PostMapping
  @ResponseStatus(HttpStatus.CREATED)
  @PreAuthorize("hasAuthority('EDIT_DEPARTMENT')")
  public IdRes add(@RequestBody @Valid SaveDepartmentReq req) {
    Department instance = new Department();
    BeanUtils.copyProperties(req, instance);
    instance = departmentService.save(instance);
    return new IdRes(instance.getId());
  }

  @PutMapping("/{id}")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  @PreAuthorize("hasAuthority('EDIT_DEPARTMENT')")
  public void update(@RequestBody @Valid SaveDepartmentReq req, @PathVariable int id) {
    Department instance = departmentService.find(id).orElseThrow(NotFoundException::new);
    BeanUtils.copyProperties(req, instance);
    instance = departmentService.save(instance);
  }

  @DeleteMapping("/{id}")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  @PreAuthorize("hasAuthority('EDIT_DEPARTMENT')")
  public void delete(@PathVariable int id) {
    if (!departmentService.existsEqType(id)) {
      departmentService.markDelete(departmentService.find(id).orElseThrow(NotFoundException::new));
    } else {
      throw new UnprocessableEntityException(ErrorCodes.DELETE_DEPARTMENT_ERROR);
    }
  }

  @GetMapping
  @PreAuthorize("hasAuthority('VIEW_DEPARTMENT')")
  public RecordsRes<Map<String, Object>> listJson(HttpServletRequest request) throws ServletRequestBindingException {
    Map<String, Object> args = CriteriaArgsBuilder.withRequest(request)
        .addStringLike(Params.QUERY)
        .addInteger(Params.ID)
        .addStringLike(Params.NAME)
        .addStringLike("description")
        .addInteger(Params.START)
        .addInteger(Params.LIMIT)
        .build();

    return new RecordsRes<>(departmentService.search(args), departmentService.searchTotalCount(args));
  }

  // #App comboJson
  @GetMapping("/combo")
  // @PreAuthorize("hasAuthority('VIEW_DEPARTMENT')")
  public RecordsRes<Map<String, Object>> comboJson(HttpServletRequest request) throws ServletRequestBindingException {
    return new RecordsRes<>(departmentService.searchForCombo(
        CriteriaArgsBuilder.withRequest(request)
            .addStringLike(Params.QUERY)
            .addInteger(Params.ID)
            .addStringLike(Params.NAME)
            .build()));
  }
}
