package com.ffii.fhsmsc.modules.settings.web;

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

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.exception.BadRequestException;
import com.ffii.core.exception.NotFoundException;
import com.ffii.core.response.RecordsRes;
import com.ffii.core.utils.Params;
import com.ffii.fhsmsc.modules.settings.entity.Settings;
import com.ffii.fhsmsc.modules.settings.service.SettingsService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

@RestController
@RequestMapping("/settings")
public class SettingsController{

  private SettingsService settingsService;

  public SettingsController(SettingsService settingsService) {
    this.settingsService = settingsService;
  }

  @Operation(summary = "list system settings", security = @SecurityRequirement(name = "bearerAuth"))
  @GetMapping
  // @PreAuthorize("hasAuthority('ADMIN')")
  public List<Settings> listAll() {
    return this.settingsService.listAll();
  }

  @Operation(summary = "update system setting", security = @SecurityRequirement(name = "bearerAuth"))
  @PatchMapping("/{name}")
  // @PreAuthorize("hasAuthority('ADMIN')")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  public void update(@PathVariable String name, @RequestBody @Valid UpdateReq body) {
    Settings entity = this.settingsService.findByName(name)
        .orElseThrow(NotFoundException::new);
    if (!this.settingsService.validateType(entity.getType(), body.value)) {
      throw new BadRequestException();
    }

    entity.setValue(body.value);
    this.settingsService.save(entity);
  }

  @GetMapping("/{name}")
  public Map<String, Object> getSetting(@PathVariable String name) {
    Settings entity = this.settingsService.findByName(name)
        .orElseThrow(NotFoundException::new);
    
    return Map.of(
      Params.DATA, entity.getValue()
    );
  }

  @PutMapping("/save")
  // @PreAuthorize("hasAuthority('ADMIN')")
  @ResponseStatus(HttpStatus.NO_CONTENT)
  public void update(@RequestBody @Valid UpdateListReq req) {
    for (Map<String,String> setting : req.getSettingList()) {
      Settings entity = this.settingsService.findByName(setting.get("name"))
      .orElseThrow(NotFoundException::new);

      if (!this.settingsService.validateType(entity.getType(), setting.get("value"))) {
        throw new BadRequestException();
      }
      
      entity.setValue(setting.get("value"));
      this.settingsService.save(entity);
    }
  }


  @GetMapping("/config")
	public RecordsRes<Map<String, Object>> getSystemConfig(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(settingsService.listSetting(
				Map.of("category","settings")
        ));
	}

  @GetMapping("/passwordPolicy")
	public RecordsRes<Map<String, Object>> getPasswordConfig(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(settingsService.listSetting(
				Map.of("category","passwordPolicy")
        ));
	}

  public static class UpdateListReq {
    @NotNull
    private List<Map<String,String>> settingList;

    public List<Map<String,String>> getSettingList() {
      return settingList;
    }

    public void setSettingList(List<Map<String,String>> settingList) {
      this.settingList = settingList;
    }
  }

  public static class UpdateReq {
    @NotBlank
    private String value;

    public String getValue() {
      return value;
    }

    public void setValue(String value) {
      this.value = value;
    }
  }
}
