package com.ffii.lioner.modules.master.web;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.ffii.lioner.modules.master.entity.Division;
import com.ffii.lioner.modules.master.entity.SubDivision;
import com.ffii.lioner.modules.master.req.UpdateDivisionReq;
import com.ffii.lioner.modules.master.service.DivisionService;
import com.ffii.lioner.modules.master.service.SubDivisionService;
import com.ffii.core.exception.NotFoundException;
import com.ffii.core.response.RecordsRes;
import com.ffii.core.utils.CriteriaArgsBuilder;
import com.ffii.core.utils.Params;

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

@RestController
@RequestMapping("/division")
public class DivisionController{

    private final Log logger = LogFactory.getLog(getClass());
    private DivisionService divisionService;
    private SubDivisionService subDivisionService;
	
    public DivisionController(
		DivisionService divisionService,
		SubDivisionService subDivisionService
		) {
		this.divisionService = divisionService;
		this.subDivisionService = subDivisionService;
	}
    
    @PostMapping("/save")
	public Map<String, Object> saveOrUpdate(@RequestBody @Valid UpdateDivisionReq req) {
		return Map.of(
				Params.DATA,divisionService.saveOrUpdate(req)
			);
	}

	@DeleteMapping("/{id}")
	//@ResponseStatus(HttpStatus.NO_CONTENT)
	public Map<String, Object> delete(@PathVariable Long id) {
		return Map.of(
			Params.DATA, divisionService.softDeleteWithSubDivision(id)
			);
	}

	@GetMapping("/{id}")
	public Map<String, Object> get(@PathVariable Long id) {
		return Map.of(
				Params.DATA, divisionService.find(id).orElseThrow(NotFoundException::new),
				"subDivision", subDivisionService.listSubdivision(Map.of("id", id))
			);
	}

	@GetMapping
	public RecordsRes<Map<String, Object>> list(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		List<Map<String, Object>> temp = divisionService.listDivision(
			CriteriaArgsBuilder.withRequest(request)
					.addInteger("id")
					.addString("branch")
					.addStringLike(Params.NAME)
					.build()
					);

		Map<String, Object> subDivisionSearch = CriteriaArgsBuilder.withRequest(request)
														.addStringLike("subDivisionName")														.addStringLike("subDivisionName")
														.build();
		if(subDivisionSearch.containsKey("subDivisionName")){
			//apply sub division search
			List<Map<String, Object>> finalResult = new ArrayList<Map<String,Object>>(); 

			for (int i=0 ; i < temp.size(); i++) {
				Map<String, Object> record = temp.get(i);
				List<Map<String,Object>> subRecord = subDivisionService.listSubdivision(
					Map.of(
						"id", record.get("id"),
						"subDivisionName", subDivisionSearch.get("subDivisionName")
						)
				);
				if(subRecord.size() > 0){
					//sub division list have size
					record.put("subDivision", subRecord);
					finalResult.add(record);
				}
			}
			return new RecordsRes<>(finalResult);
		}
		else{
			//get all record directly
			for (int i=0 ; i < temp.size(); i++) {
			Map<String, Object> record = temp.get(i);
			record.put("subDivision", subDivisionService.listSubdivision(Map.of("id", record.get("id"))));
			temp.set(i, record); 
			}
			return new RecordsRes<>(temp);

		}
		
	}

	@GetMapping("/fromSubDiv")
	public Map<String, Object> getDivisionBySubDivision(@RequestParam Long id) throws ServletRequestBindingException {
		SubDivision temp = subDivisionService.find(id).get();
		Division output = divisionService.find(temp.getDivisionId()).get(); 
		return Map.of("data",output);
	}

	@GetMapping("/combo")
	public RecordsRes<Map<String, Object>> getDivisionCombo(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(subDivisionService.listDivisionCombo(
				CriteriaArgsBuilder.withRequest(request)
						.build()));
	}

	@GetMapping("/subdivision")
	public RecordsRes<Map<String, Object>> getSubDivisionById(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(subDivisionService.listSubdivision(
				CriteriaArgsBuilder.withRequest(request)
						.addInteger("id")
						.build()));
	}

	@GetMapping("/subdivision/combo")
	public RecordsRes<Map<String, Object>> getSubDivisionCombo(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(subDivisionService.listSubdivisionCombo(
				CriteriaArgsBuilder.withRequest(request)
						.addIntegerList("divisionIds")
						.build()));
	}

	@GetMapping("/subdivision/event/combo")
	public RecordsRes<Map<String, Object>> listSubdivisionComboForApplication(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(subDivisionService.listSubdivisionComboForApplication(
				CriteriaArgsBuilder.withRequest(request)
						.addIntegerList("eventId")
						.build()));
	}

	@GetMapping("/subdivision/application/combo")
	public RecordsRes<Map<String, Object>> listSubdivisionComboForAward(HttpServletRequest request) throws ServletRequestBindingException {
		System.out.println(request);
		return new RecordsRes<>(subDivisionService.listSubdivisionComboForAward(
				CriteriaArgsBuilder.withRequest(request)
						.addIntegerList("applicationId")
						.build()));
	}
	
	

	@GetMapping("/checkDuplicate")
    public Map<String, Object> checkDuplicate(HttpServletRequest request) throws ServletRequestBindingException {
		String isSubDivNameTaken = subDivisionService.isNameTaken(
			CriteriaArgsBuilder.withRequest(request)
						.addStringList("subDivisionList")
						.addInteger("divisionId")
						.build());

        String isDivNameTaken = divisionService.isNameTaken(
			CriteriaArgsBuilder.withRequest(request)
						.addString("division")
						.addInteger("divisionId")
						.build());
		boolean valid = true;

		if(isDivNameTaken != "" || isSubDivNameTaken != null){
			valid = false;
		}
        return Map.of(
			"valid", valid,
            "duplicatedDivision", isDivNameTaken,
			"duplicatedSubDivision", isSubDivNameTaken == null ? "" : isSubDivNameTaken
        );
    }
}
