package com.ffii.core.common.web;

import java.util.Locale;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.bind.annotation.GetMapping;
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 org.springframework.web.servlet.LocaleResolver;

import com.ffii.core.common.SecurityUtils;
import com.ffii.core.common.res.LocaleRes;
import com.ffii.core.common.res.MeRes;
import com.ffii.core.user.entity.User;
import com.ffii.core.user.service.UserService;
import com.ffii.core.utils.LocaleUtils;

import io.swagger.v3.oas.annotations.Operation;

@RestController
@RequestMapping("/protected")
public class CommonProtectedController {

  private LocaleResolver localeResolver;
  private UserService userService;

  public CommonProtectedController(LocaleResolver localeResolver, UserService userService) {
    this.localeResolver = localeResolver;
    this.userService = userService;
  }

  @Operation(summary = "list current details")
  @GetMapping("/me")
  public MeRes me() {
    User u = SecurityUtils.getUser().get();

    MeRes res = new MeRes();
    res.setId(u.getId());
    res.setName(u.getName());
    res.setLandingPage(u.getLandingPage());
    res.setAuthorities(u.getAuthorities().stream()
        .map(GrantedAuthority::getAuthority)
        .collect(Collectors.toList()));
    res.setLocale(LocaleUtils.getLocaleStr());

    return res;
  }

  @Operation(summary = "get current locale")
  @GetMapping("/locale")
  public LocaleRes currentLocale() {
    return new LocaleRes(LocaleUtils.getLocaleStr());
  };

  @Operation(summary = "set locale")
  @PostMapping("/locale")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  public void locale(HttpServletRequest request, HttpServletResponse response,
      @RequestBody @Valid ChangeLocaleReq req) {
    Locale locale = StringUtils.isNotBlank(req.getCountry())
        ? new Locale(req.getLanguage(), req.getCountry())
        : new Locale(req.getLanguage());
    localeResolver.setLocale(request, response, locale);

    SecurityUtils.getUser()
        .ifPresent(user -> {
          userService.setUserLocale(user.getId(), locale);
        });
  }

  public static class ChangeLocaleReq {
    @NotBlank
    private String language;
    private String country;

    public String getLanguage() {
      return language;
    }

    public void setLanguage(String language) {
      this.language = language;
    }

    public String getCountry() {
      return country;
    }

    public void setCountry(String country) {
      this.country = country;
    }

  }
}
