package com.kospo.talk.controller;

import com.kospo.talk.config.exception.CustomErrorResponse;
import com.kospo.talk.config.utils.CommonUtils;
import com.kospo.talk.model.Talk;
import com.kospo.talk.model.TalkMessage;
import com.kospo.talk.model.TalkMessageId;
import com.kospo.talk.model.Work;
import com.kospo.talk.payload.*;
import com.kospo.talk.service.TalkMemberService;
import com.kospo.talk.service.TalkMessageService;
import com.kospo.talk.service.TalkService;
import com.kospo.talk.service.WorkService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Tag(name = "SCM API", description = "SCM 작업 관리")
@RequestMapping("/api/scm")
@RequiredArgsConstructor
@Slf4j
public class ScmController {

    @Value("${rabbitmq.user.exchange}")
    private String userExchange;
    @Value("${rabbitmq.user.route}")
    private String userRoute;
    @Value("${rabbitmq.talk.exchange}")
    private String talkExchange;
    @Value("${rabbitmq.talk.route}")
    private String talkRoute;
    private final WebClient scmWebClient;
    private final TalkService talkService;
    private final WorkService workService;
    private final TalkMessageService talkMessageService;
    private final TalkMemberService talkMemberService;
    private final RabbitTemplate userTemplate;
    private final RabbitTemplate talkTemplate;

    @Operation(summary = "SCM 업무 카테고리 그룹 조회", description = "SCM 업무 카테고리 그룹 조회 후 map 으로 리턴")
    @ApiResponses({
            @ApiResponse(description = "Success", responseCode = "200",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
                            schema = @Schema(oneOf =
                                    {HashMap.class})
                    ))),
            @ApiResponse(description = "Not found", responseCode = "404",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Internal Error", responseCode = "500",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {CustomErrorResponse.class })))
    })
    @GetMapping("/group")
    public ResponseEntity getGroup(
            HttpServletRequest request,
            Principal principal
    ) {


        MultiValueMap cookieMap = new LinkedMultiValueMap();

        Arrays.stream(request.getCookies()).forEach((cookie) -> {
            cookieMap.add(cookie.getName(), cookie.getValue());
        });

        MultiValueMap headerMap = new LinkedMultiValueMap();

        headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));


        List<HashMap<String,String>> resultList = scmWebClient.post()
                .uri("/api/reqScmCodeGroup.do")
                .headers(h -> h.addAll(headerMap))
                .cookies(c -> c.addAll(cookieMap))
                .retrieve().bodyToMono(List.class).block();

        return ResponseEntity.ok(resultList);
    }

    @Operation(summary = "SCM 업무 코드 조회", description = "SCM 업무 코드 조회 후 map 으로 리턴")
    @ApiResponses({
            @ApiResponse(description = "Success", responseCode = "200",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", array = @ArraySchema(
                            schema = @Schema(oneOf =
                                    {HashMap.class})
                    ))),
            @ApiResponse(description = "Not found", responseCode = "404",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Internal Error", responseCode = "500",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {CustomErrorResponse.class })))
    })
    @GetMapping("/code")
    public ResponseEntity getCode(
            @Parameter(description = "구분코드") @RequestParam("gubun") String gubun,
            HttpServletRequest request,
            Principal principal
    ) {


        MultiValueMap cookieMap = new LinkedMultiValueMap();

        Arrays.stream(request.getCookies()).forEach((cookie) -> {
            cookieMap.add(cookie.getName(), cookie.getValue());
        });

        MultiValueMap headerMap = new LinkedMultiValueMap();

        headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));

        HashMap<String, String> body =new HashMap();
        body.put("SEARCH_SYS_GUBUN", gubun);

        List<HashMap<String,String>> resultList = scmWebClient.post()
                .uri("/api/reqScmCodeList.do")
                .headers(h -> h.addAll(headerMap))
                .cookies(c -> c.addAll(cookieMap))
                .bodyValue(body)
                .retrieve().bodyToMono(List.class).block();

        return ResponseEntity.ok(resultList);
    }

    @Operation(summary = "SCM 작업 요청 하기", description = "itsm 요청 정보 저장 결과값으로 req_id 리턴")
    @ApiResponses({
            @ApiResponse(description = "Success", responseCode = "200",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Not found", responseCode = "404",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Internal Error", responseCode = "500",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {CustomErrorResponse.class })))
    })
    @PostMapping("/save")
    public ResponseEntity save(
            @RequestBody ScmDto scmDto,
            HttpServletRequest request,
            Principal principal
    ) {

        MultiValueMap cookieMap = new LinkedMultiValueMap();

        Arrays.stream(request.getCookies()).forEach((cookie) -> {
            cookieMap.add(cookie.getName(), cookie.getValue());
        });

        MultiValueMap headerMap = new LinkedMultiValueMap();

        headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));

        try {
            String req_id = scmWebClient.post()
                    .uri("/api/reqHelpTalkIns.do")
                    .headers(h -> h.addAll(headerMap))
                    .cookies(c -> c.addAll(cookieMap))
                    .bodyValue(scmDto)
                    .retrieve().bodyToMono(String.class).block();

            Talk talk = talkService.findByOne(scmDto.getTalk_id());
            talk.setReqId(req_id);
            talkService.createTalk(talk);

            MessageDto messageDto = MessageDto.builder().type("EXTERNAL_SAVE")
                    .reqId(req_id)
                    .talkId(talk.getTalkId()).build();
            talkTemplate.convertAndSend(talkExchange, talkRoute + talk.getTalkId(), messageDto);

            return ResponseEntity.ok(req_id);
        } catch(Exception e) {
            return ResponseEntity.ok("");
        }
    }

    @Operation(summary = "외부 ITSM 만족도 조사", description = "itsm 만족도 조사 등록")
    @ApiResponses({
            @ApiResponse(description = "Success", responseCode = "200",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Not found", responseCode = "404",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "text/plain", schema = @Schema(oneOf =
                            {String.class}))),
            @ApiResponse(description = "Internal Error", responseCode = "500",
                    content = @io.swagger.v3.oas.annotations.media.Content(mediaType = "application/json", schema = @Schema(oneOf =
                            {CustomErrorResponse.class })))
    })
    @PostMapping("/satis")
    public ResponseEntity satisSave(
            @RequestBody SatisDto satisDto,
            HttpServletRequest request,
            Principal principal
    ) {
        MultiValueMap cookieMap = new LinkedMultiValueMap();

        Arrays.stream(request.getCookies()).forEach((cookie) -> {
            cookieMap.add(cookie.getName(), cookie.getValue());
        });

        MultiValueMap headerMap = new LinkedMultiValueMap();

        Talk currentTalk = talkService.findByOne(satisDto.getTalk_id());


        Map<String, String> resultMap = new HashMap<>();
        headerMap.add("X-Forwarded-For", request.getHeader("X-Forwarded-For"));
        resultMap = scmWebClient.post()
                .uri("/api/reqHelpTalkManIns.do")
                .headers(h -> h.addAll(headerMap))
                .cookies(c -> c.addAll(cookieMap))
                .bodyValue(HappyDto.builder()
                        .req_id(currentTalk.getReqId())
                        .h_point(satisDto.getH_point())
                        .opinion(satisDto.getOpinion()).build()
                )
                .retrieve().bodyToMono(Map.class).block();


        String result = resultMap.get("result");
        if(result.equals("s")) {
            talkService.ratingUpdate(currentTalk.getReqId());
            Work work = workService.findByTalkId(currentTalk.getTalkId());
            MessageDto messageDto = MessageDto.builder()
                    .type("STATUS")
                    .message("만족도 조사에 참여해 주셔서 감사해요.\n앞으로도 많은 참여 부탁드려요.")
                    .talkId(currentTalk.getTalkId())
                    .workId(work.getWorkId())
                    .workNm(work.getWorkNm())
                    .insSabun("info")
                    .insName("시스템")
                    .insDate(LocalDateTime.now())
                    .build();
            talkMessageService.save(TalkMessage.builder()
                    .id(TalkMessageId.builder().talkId(messageDto.getTalkId()).sabun(messageDto.getInsSabun()).insDate(messageDto.getInsDate()).build())
                    .message(messageDto.getMessage())
                    .searchYn(false)
                    .insName(messageDto.getInsName()).build()
            );


            talkMemberService.findAllByTalkId(messageDto.getTalkId()).stream().forEach(talkMember -> {
                talkMember.getId().getSabun();
                userTemplate.convertAndSend(userExchange, userRoute + talkMember.getId().getSabun(), messageDto);
            });

        }
        return ResponseEntity.ok(resultMap.get("result"));
    }
}

