package com.madeu.crm.procedureReview.svc;

import com.madeu.constants.Constants;
import com.madeu.crm.procedureReview.dto.ProcedureReviewDTO;
import com.madeu.crm.procedureReview.mapper.ProcedureReviewMapper;
import com.madeu.common.service.LogHistoryService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service("ProcedureReviewService")
public class ProcedureReviewService {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpSession session;

    @Autowired
    private ProcedureReviewMapper procedureReviewMapper;

    @Autowired
    private LogHistoryService logHistoryService;

    @Autowired
    private MessageSource messageSource;

    @Value("${file.upload-path}")
    private String procedureReviewPath;

    @Value("${url.cdn}")
    String CDN_URL;

    /** 메시지 코드 → 문자열 변환 헬퍼 */
    private String msg(String code) {
        return messageSource.getMessage(code, null, Locale.getDefault());
    }

    public ProcedureReviewDTO getProcedureReviewList(ProcedureReviewDTO dto) {
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        try {
            String selectUseYn = (String) request.getAttribute("selectUseYn");
            if ("Y".equals(selectUseYn)) {
                if (dto.getDir() != null && "B".equals(dto.getDir())) {
                    dto.setDir("ASC");
                } else {
                    dto.setDir("DESC");
                }
                dto.setUseYn("Y");

                List<ProcedureReviewDTO> countList = procedureReviewMapper.selectTotalProcedureReviewCount(dto);
                int total = countList.get(0).getTotalCount();

                dto.setTotalCount(total);
                if (total > 0) {
                    dto.setRows(procedureReviewMapper.selectListProcedureReview(dto));
                } else {
                    dto.setRows(new ArrayList<>());
                }
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.select"));
            }
        } catch (Exception e) {
            log.error("Error in getProcedureReviewList", e);
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.select"));
        }
        return dto;
    }

    public ProcedureReviewDTO getProcedureReview(ProcedureReviewDTO dto) {
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        try {
            if (dto.getMuProcedureReviewId() == null || dto.getMuProcedureReviewId().trim().isEmpty()) {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("procedureReview.error.noData"));
                return dto;
            }

            String selectUseYn = (String) request.getAttribute("selectUseYn");
            if ("Y".equals(selectUseYn)) {
                ProcedureReviewDTO res = procedureReviewMapper.selectProcedureReview(dto);
                dto.setRows(res);
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.select"));
            }
        } catch (Exception e) {
            log.error("Error in getProcedureReview", e);
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.select"));
        }
        return dto;
    }

    public ProcedureReviewDTO getCategoryList(ProcedureReviewDTO dto) {
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        try {
            dto.setCategoryDivCd("07");
            List<Map<String, Object>> cats = procedureReviewMapper.selectListPhotoCategory(dto);
            dto.setRows(cats);
            dto.setMsgCode(Constants.OK);
            dto.setSuccess("true");
        } catch (Exception e) {
            log.error("Error in getCategoryList", e);
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("procedureReview.category.error"));
        }
        return dto;
    }

    @Transactional(rollbackFor = { Exception.class })
    public ProcedureReviewDTO putProcedureReviewFile(MultipartFile file, ProcedureReviewDTO dto) {
        String errorMsg = "";
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        dto.setRegId(dto.getLoginMemberId());
        dto.setModId(dto.getLoginMemberId());

        try {
            String insertUseYn = (String) request.getAttribute("insertUseYn");
            if ("Y".equals(insertUseYn) && file != null && !file.isEmpty()) {
                String ext = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
                String savedName = UUID.randomUUID().toString() + ext;
                String folder = "/procedureReview/" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                        + "/";

                File outDir = new File(procedureReviewPath + folder);
                if (!outDir.exists()) {
                    outDir.mkdirs();
                }

                File dest = new File(outDir, savedName);
                file.transferTo(dest.toPath().toAbsolutePath());

                HashMap<String, Object> resultRow = new HashMap<>();
                resultRow.put("filePath", CDN_URL + folder + savedName);

                dto.setRows(resultRow);
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
                dto.setMsgDesc(msg("success.insert"));
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.noAuthOrEmpty"));
            }
        } catch (Exception e) {
            log.error("Error in putProcedureReviewFile", e);
            errorMsg = e.toString();
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.insert"));
        }
        logHistoryService.save("홈페이지 시술후기 이미지파일 저장", "홈페이지 시술후기 등록", dto, dto, errorMsg);
        return dto;
    }

    @Transactional(rollbackFor = { Exception.class })
    public ProcedureReviewDTO putProcedureReview(ProcedureReviewDTO dto) {
        String errorMsg = "";
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        dto.setMuMemberId(dto.getLoginMemberId());
        dto.setRegId(dto.getLoginMemberId());
        dto.setModId(dto.getLoginMemberId());

        try {
            String insertUseYn = (String) request.getAttribute("insertUseYn");
            if ("Y".equals(insertUseYn)) {
                procedureReviewMapper.insertProcedureReview(dto);
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
                dto.setMsgDesc(msg("success.insert"));
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.noAuth"));
            }
        } catch (Exception e) {
            log.error("Error in putProcedureReview", e);
            errorMsg = e.toString();
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.insert"));
        }
        logHistoryService.save("홈페이지 시술후기 등록", "홈페이지 시술후기 등록", dto, dto, errorMsg);
        return dto;
    }

    @Transactional(rollbackFor = { Exception.class })
    public ProcedureReviewDTO modProcedureReview(ProcedureReviewDTO dto) {
        String errorMsg = "";
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        dto.setRegId(dto.getLoginMemberId());
        dto.setModId(dto.getLoginMemberId());

        try {
            String updateUseYn = (String) request.getAttribute("updateUseYn");
            if ("Y".equals(updateUseYn)) {
                procedureReviewMapper.updateProcedureReview(dto);
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
                dto.setMsgDesc(msg("success.update"));
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.noAuth"));
            }
        } catch (Exception e) {
            log.error("Error in modProcedureReview", e);
            errorMsg = e.toString();
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.update"));
        }
        logHistoryService.save("홈페이지 시술후기 수정", "홈페이지 시술후기 수정", dto, dto, errorMsg);
        return dto;
    }

    @Transactional(rollbackFor = { Exception.class })
    public ProcedureReviewDTO delProcedureReview(ProcedureReviewDTO dto) {
        String errorMsg = "";
        dto.setLoginMemberId(String.valueOf(session.getAttribute("loginMemberId")));
        dto.setRegId(dto.getLoginMemberId());
        dto.setModId(dto.getLoginMemberId());

        try {
            String deleteUseYn = (String) request.getAttribute("deleteUseYn");
            if ("Y".equals(deleteUseYn)) {
                String[] ids = dto.getMuProcedureReviewId().split(",");
                for (String id : ids) {
                    dto.setMuProcedureReviewId(id.trim());
                    procedureReviewMapper.deleteProcedureReview(dto);
                }
                dto.setMsgCode(Constants.OK);
                dto.setSuccess("true");
                dto.setMsgDesc(msg("success.delete"));
            } else {
                dto.setMsgCode(Constants.FAIL);
                dto.setMsgDesc(msg("auth.error.delete"));
            }
        } catch (Exception e) {
            log.error("Error in delProcedureReview", e);
            errorMsg = e.toString();
            dto.setMsgCode(Constants.FAIL);
            dto.setMsgDesc(msg("error.delete"));
        }
        logHistoryService.save("홈페이지 시술후기 삭제", "홈페이지 시술후기 삭제", dto, dto, errorMsg);
        return dto;
    }
}
