package com.erp.service;

import com.erp.common.BaseService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class MailTemplateFileService extends BaseService {

    private static final String NS = "mailTemplateFile.";

    private final CommonService commonService;
    private final ObjectMapper objectMapper;

    public Map<String, Object> getMailTemplateFileList(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        commonService.applyPagination(params);
        int totalCount = sqlSession.selectOne(NS + "getMailTemplateFileListCnt", params);
        List<Map<String, Object>> list = sqlSession.selectList(NS + "getMailTemplateFileList", params);
        return commonService.buildListResponse(list, totalCount, params);
    }

    public Map<String, Object> getMailTemplateFileInfo(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        return sqlSession.selectOne(NS + "getMailTemplateFileInfo", params);
    }

    @Transactional
    public Map<String, Object> insertMailTemplateFile(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        serializeJsonFields(params);
        sqlSession.insert(NS + "insertMailTemplateFile", params);
        return params;
    }

    @Transactional
    public Map<String, Object> updateMailTemplateFile(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        serializeJsonFields(params);
        sqlSession.update(NS + "updateMailTemplateFile", params);
        return params;
    }

    @Transactional
    public Map<String, Object> deleteMailTemplateFile(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        sqlSession.delete(NS + "deleteMailTemplateFile", params);
        return params;
    }

    @SuppressWarnings("unchecked")
    public Map<String, Object> previewMailTemplateFile(Map<String, Object> params) {
        commonService.applyCompanyCodeFilter(params);
        Map<String, Object> template = sqlSession.selectOne(NS + "getMailTemplateFileInfo", params);
        if (template == null) {
            return Collections.emptyMap();
        }
        Object componentsRaw = template.get("components");
        String componentsJson = componentsRaw != null ? componentsRaw.toString() : null;
        String renderedHtml = renderTemplateToHtml(componentsJson);
        String subject = (String) template.get("subject");

        Map<String, Object> sampleData = (Map<String, Object>) params.get("sample_data");
        if (sampleData != null && !sampleData.isEmpty()) {
            renderedHtml = replaceVariables(renderedHtml, sampleData);
            subject = replaceVariables(subject, sampleData);
        }

        Map<String, Object> result = new HashMap<>();
        result.put("subject", subject);
        result.put("html", renderedHtml);
        result.put("sample_data", sampleData);
        return result;
    }

    private void serializeJsonFields(Map<String, Object> params) {
        for (String field : new String[]{"components", "query_config", "recipient_config"}) {
            Object val = params.get(field);
            if (val != null && !(val instanceof String)) {
                try {
                    params.put(field, objectMapper.writeValueAsString(val));
                } catch (Exception e) {
                    log.warn("JSON 직렬화 실패: {}", field);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private String renderTemplateToHtml(String componentsJson) {
        if (componentsJson == null || componentsJson.isEmpty()) return "";
        List<Map<String, Object>> components;
        try {
            components = objectMapper.readValue(componentsJson, new TypeReference<List<Map<String, Object>>>() {});
        } catch (Exception e) {
            log.warn("components JSON 파싱 실패", e);
            return "";
        }
        StringBuilder html = new StringBuilder("<div style=\"max-width: 600px; margin: 0 auto; font-family: Arial, sans-serif;\">");
        for (Map<String, Object> comp : components) {
            String type = (String) comp.getOrDefault("type", "");
            Map<String, Object> rawStyles = comp.get("styles") instanceof Map
                    ? (Map<String, Object>) comp.get("styles") : new HashMap<>();
            String stylesStr = buildStylesString(rawStyles);
            switch (type) {
                case "text" -> html.append("<div style=\"").append(stylesStr).append("\">")
                        .append(comp.getOrDefault("content", "")).append("</div>");
                case "button" -> {
                    String bg = rawStyles.containsKey("background_color") ? String.valueOf(rawStyles.get("background_color")) : "#007bff";
                    String color = rawStyles.containsKey("color") ? String.valueOf(rawStyles.get("color")) : "#fff";
                    html.append("<div style=\"text-align: center; ").append(stylesStr).append("\">")
                        .append("<a href=\"").append(comp.getOrDefault("url", "#")).append("\" ")
                        .append("style=\"display: inline-block; padding: 12px 24px; text-decoration: none; ")
                        .append("background-color: ").append(bg).append("; ")
                        .append("color: ").append(color).append("; border-radius: 4px;\">")
                        .append(comp.getOrDefault("text", "Button"))
                        .append("</a></div>");
                }
                case "image" -> html.append("<div style=\"").append(stylesStr).append("\">")
                        .append("<img src=\"").append(comp.getOrDefault("src", "")).append("\" alt=\"\" style=\"max-width: 100%; height: auto;\"/></div>");
                case "spacer" -> html.append("<div style=\"height: ").append(comp.getOrDefault("height", 20)).append("px;\"></div>");
                case "header" -> {
                    String headerBg = (String) comp.getOrDefault("header_bg_color", "#f8f9fa");
                    String logoSrc = (String) comp.get("logo_src");
                    String brandName = String.valueOf(comp.getOrDefault("brand_name", ""));
                    String sendDate = String.valueOf(comp.getOrDefault("send_date", ""));
                    html.append("<div style=\"padding: 20px; background-color: ").append(headerBg)
                        .append("; border-radius: 8px; margin-bottom: 20px;\">")
                        .append("<table style=\"width: 100%;\"><tr><td style=\"vertical-align: middle;\">")
                        .append(logoSrc != null ? "<img src=\"" + logoSrc + "\" alt=\"로고\" style=\"height: 40px; margin-right: 12px;\">" : "")
                        .append("<span style=\"font-size: 18px; font-weight: bold;\">").append(brandName).append("</span>")
                        .append("</td><td style=\"text-align: right; color: #6b7280; font-size: 14px;\">")
                        .append(sendDate).append("</td></tr></table></div>");
                }
                case "info_table" -> {
                    String tableTitle = (String) comp.get("table_title");
                    List<Map<String, Object>> rows = comp.get("rows") instanceof List
                            ? (List<Map<String, Object>>) comp.get("rows") : new ArrayList<>();
                    html.append("<div style=\"border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; margin: 16px 0;\">")
                        .append(tableTitle != null ? "<div style=\"background-color: #f9fafb; padding: 12px 16px; font-weight: 600; border-bottom: 1px solid #e5e7eb;\">" + tableTitle + "</div>" : "")
                        .append("<table style=\"width: 100%; border-collapse: collapse;\">");
                    for (int i = 0; i < rows.size(); i++) {
                        Map<String, Object> row = rows.get(i);
                        html.append("<tr style=\"background-color: ").append(i % 2 == 0 ? "#ffffff" : "#f9fafb").append(";\">")
                            .append("<td style=\"padding: 12px 16px; font-weight: 500; color: #4b5563; width: 35%; border-right: 1px solid #e5e7eb;\">").append(row.getOrDefault("label", "")).append("</td>")
                            .append("<td style=\"padding: 12px 16px;\">").append(row.getOrDefault("value", "")).append("</td></tr>");
                    }
                    html.append("</table></div>");
                }
                case "alert_box" -> {
                    String alertType = (String) comp.getOrDefault("alert_type", "info");
                    String alertTitle = (String) comp.get("alert_title");
                    String content = String.valueOf(comp.getOrDefault("content", ""));
                    Map<String, String> bgMap = Map.of("info", "#eff6ff", "warning", "#fffbeb", "danger", "#fef2f2", "success", "#ecfdf5");
                    Map<String, String> borderMap = Map.of("info", "#3b82f6", "warning", "#f59e0b", "danger", "#ef4444", "success", "#10b981");
                    Map<String, String> textMap = Map.of("info", "#1e40af", "warning", "#92400e", "danger", "#991b1b", "success", "#065f46");
                    html.append("<div style=\"padding: 16px; background-color: ").append(bgMap.getOrDefault(alertType, "#eff6ff"))
                        .append("; border-left: 4px solid ").append(borderMap.getOrDefault(alertType, "#3b82f6"))
                        .append("; border-radius: 4px; margin: 16px 0; color: ").append(textMap.getOrDefault(alertType, "#1e40af")).append(";\">")
                        .append(alertTitle != null ? "<div style=\"font-weight: bold; margin-bottom: 8px;\">" + alertTitle + "</div>" : "")
                        .append("<div>").append(content).append("</div></div>");
                }
                case "divider" -> html.append("<hr style=\"border: none; border-top: ").append(comp.getOrDefault("height", 1)).append("px solid #e5e7eb; margin: 20px 0;\">");
                case "footer" -> {
                    String companyName = (String) comp.get("company_name");
                    String ceoName = (String) comp.get("ceo_name");
                    String businessNumber = (String) comp.get("business_number");
                    String address = (String) comp.get("address");
                    String phone = (String) comp.get("phone");
                    String email = (String) comp.get("email");
                    String copyright = (String) comp.get("copyright");
                    html.append("<div style=\"text-align: center; padding: 24px 16px; background-color: #f9fafb; border-top: 1px solid #e5e7eb; font-size: 14px; color: #6b7280;\">")
                        .append(companyName != null ? "<div style=\"font-weight: 600; color: #374151; margin-bottom: 8px;\">" + companyName + "</div>" : "")
                        .append((ceoName != null || businessNumber != null) ? "<div style=\"margin-bottom: 4px;\">"
                            + (ceoName != null ? "대표: " + ceoName : "")
                            + (ceoName != null && businessNumber != null ? " | " : "")
                            + (businessNumber != null ? "사업자등록번호: " + businessNumber : "") + "</div>" : "")
                        .append(address != null ? "<div style=\"margin-bottom: 4px;\">" + address + "</div>" : "")
                        .append((phone != null || email != null) ? "<div style=\"margin-bottom: 4px;\">"
                            + (phone != null ? "Tel: " + phone : "")
                            + (phone != null && email != null ? " | " : "")
                            + (email != null ? "Email: " + email : "") + "</div>" : "")
                        .append(copyright != null ? "<div style=\"margin-top: 12px; font-size: 12px; color: #9ca3af;\">" + copyright + "</div>" : "")
                        .append("</div>");
                }
                case "numbered_list" -> {
                    String listTitle = (String) comp.get("list_title");
                    List<String> listItems = comp.get("list_items") instanceof List
                            ? (List<String>) comp.get("list_items") : new ArrayList<>();
                    html.append("<div style=\"padding: 16px; ").append(stylesStr).append("\">")
                        .append(listTitle != null ? "<div style=\"font-weight: 600; margin-bottom: 12px;\">" + listTitle + "</div>" : "")
                        .append("<ol style=\"margin: 0; padding-left: 20px;\">");
                    for (String item : listItems) {
                        html.append("<li style=\"margin-bottom: 8px;\">").append(item).append("</li>");
                    }
                    html.append("</ol></div>");
                }
                default -> { /* 알 수 없는 컴포넌트 타입은 무시 */ }
            }
        }
        html.append("</div>");
        return html.toString();
    }

    private String buildStylesString(Map<String, Object> styles) {
        if (styles == null || styles.isEmpty()) return "";
        return styles.entrySet().stream()
                .map(e -> camelToKebab(e.getKey()) + ": " + e.getValue())
                .collect(Collectors.joining("; "));
    }

    private String camelToKebab(String str) {
        return str.replaceAll("([A-Z])", "-$1").toLowerCase();
    }

    private String replaceVariables(String text, Map<String, Object> data) {
        if (text == null || data == null) return text;
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            text = text.replace("{" + entry.getKey() + "}", String.valueOf(entry.getValue()));
        }
        return text;
    }
}
