package com.erp.service;

import com.erp.common.BaseService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;

@Service
@Slf4j
public class BarcodeLabelService extends BaseService {

    @Autowired private CommonService commonService;
    @Autowired private ObjectMapper objectMapper;

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 목록 조회
    // ──────────────────────────────────────────────────────────────────────────
    public Map<String, Object> getBarcodeLabelList(Map<String, Object> params) {
        if (params.get("use_yn") == null) params.put("use_yn", "Y");
        commonService.applyPagination(params);
        Number cntNum = sqlSession.selectOne("barcodeLabel.getBarcodeLabelListCnt", params);
        int totalCount = cntNum != null ? cntNum.intValue() : 0;
        List<Map<String, Object>> list = sqlSession.selectList("barcodeLabel.getBarcodeLabelList", params);
        return commonService.buildListResponse(list, totalCount, params);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 단건 조회
    // ──────────────────────────────────────────────────────────────────────────
    public Map<String, Object> getBarcodeLabelInfo(String labelId) {
        Map<String, Object> params = new HashMap<>();
        params.put("label_id", labelId);
        return sqlSession.selectOne("barcodeLabel.getBarcodeLabelInfo", params);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 레이아웃 조회 (layout_json 파싱)
    // ──────────────────────────────────────────────────────────────────────────
    public Map<String, Object> getBarcodeLabelLayout(String labelId) {
        Map<String, Object> label = getBarcodeLabelInfo(labelId);
        if (label == null) return null;
        Object layoutJson = label.get("layout_json");
        if (layoutJson == null) return null;
        try {
            return objectMapper.readValue(layoutJson.toString(),
                    new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            log.warn("layout_json 파싱 실패 (labelId={}): {}", labelId, e.getMessage());
            return null;
        }
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 생성
    // ──────────────────────────────────────────────────────────────────────────
    @Transactional
    public Map<String, Object> insertBarcodeLabel(Map<String, Object> params) {
        String labelId = "LBL_" + UUID.randomUUID().toString().replace("-", "").substring(0, 20);
        params.put("label_id", labelId);

        int widthMm = 50;
        int heightMm = 30;
        String layoutJson = null;

        // templateId가 있으면 템플릿 치수/레이아웃 적용
        Object templateId = params.get("template_id");
        if (templateId != null && !templateId.toString().isBlank()) {
            Map<String, Object> tParams = new HashMap<>();
            tParams.put("template_id", templateId.toString().trim());
            Map<String, Object> template = sqlSession.selectOne("barcodeLabel.getBarcodeLabelTemplateInfo", tParams);
            if (template != null) {
                widthMm = toInt(template.get("width_mm"), 50);
                heightMm = toInt(template.get("height_mm"), 30);
                Object tj = template.get("layout_json");
                if (tj != null) layoutJson = tj.toString();
            }
        }

        if (layoutJson == null) {
            Map<String, Object> defaultLayout = new LinkedHashMap<>();
            defaultLayout.put("width_mm", widthMm);
            defaultLayout.put("height_mm", heightMm);
            defaultLayout.put("components", new ArrayList<>());
            try {
                layoutJson = objectMapper.writeValueAsString(defaultLayout);
            } catch (Exception e) {
                layoutJson = "{\"width_mm\":" + widthMm + ",\"height_mm\":" + heightMm + ",\"components\":[]}";
            }
        }

        params.put("width_mm", widthMm);
        params.put("height_mm", heightMm);
        params.put("layout_json", layoutJson);

        sqlSession.insert("barcodeLabel.insertBarcodeLabel", params);

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("label_id", labelId);
        return result;
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 수정
    // ──────────────────────────────────────────────────────────────────────────
    @Transactional
    public boolean updateBarcodeLabel(String labelId, Map<String, Object> params) {
        params.put("label_id", labelId);
        int updated = sqlSession.update("barcodeLabel.updateBarcodeLabel", params);
        return updated > 0;
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 레이아웃 저장
    // ──────────────────────────────────────────────────────────────────────────
    @Transactional
    public void saveBarcodeLabelLayout(String labelId, Map<String, Object> layout, String userId) {
        int widthMm = toInt(layout.get("width_mm"), 0);
        int heightMm = toInt(layout.get("height_mm"), 0);
        String layoutJson;
        try {
            layoutJson = objectMapper.writeValueAsString(layout);
        } catch (Exception e) {
            throw new IllegalArgumentException("레이아웃 직렬화 실패: " + e.getMessage());
        }
        Map<String, Object> params = new HashMap<>();
        params.put("label_id", labelId);
        params.put("width_mm", widthMm);
        params.put("height_mm", heightMm);
        params.put("layout_json", layoutJson);
        params.put("updated_by", userId);
        sqlSession.update("barcodeLabel.updateBarcodeLabelLayout", params);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 삭제
    // ──────────────────────────────────────────────────────────────────────────
    @Transactional
    public boolean deleteBarcodeLabel(String labelId) {
        Map<String, Object> params = new HashMap<>();
        params.put("label_id", labelId);
        int deleted = sqlSession.delete("barcodeLabel.deleteBarcodeLabel", params);
        return deleted > 0;
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 라벨 복사
    // ──────────────────────────────────────────────────────────────────────────
    @Transactional
    public String copyBarcodeLabel(String labelId, String userId) {
        Map<String, Object> original = getBarcodeLabelInfo(labelId);
        if (original == null) return null;

        String newLabelId = "LBL_" + UUID.randomUUID().toString().replace("-", "").substring(0, 20);
        Map<String, Object> params = new HashMap<>();
        params.put("new_label_id", newLabelId);
        params.put("label_id", labelId);
        params.put("created_by", userId);

        sqlSession.insert("barcodeLabel.copyBarcodeLabel", params);
        return newLabelId;
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 템플릿 목록
    // ──────────────────────────────────────────────────────────────────────────
    public List<Map<String, Object>> getBarcodeLabelTemplateList() {
        return sqlSession.selectList("barcodeLabel.getBarcodeLabelTemplateList", new HashMap<>());
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 템플릿 단건 조회 (layout_json 파싱 포함)
    // ──────────────────────────────────────────────────────────────────────────
    public Map<String, Object> getBarcodeLabelTemplateInfo(String templateId) {
        Map<String, Object> params = new HashMap<>();
        params.put("template_id", templateId);
        Map<String, Object> template = sqlSession.selectOne("barcodeLabel.getBarcodeLabelTemplateInfo", params);
        if (template == null) return null;

        Object layoutJson = template.get("layout_json");
        if (layoutJson != null) {
            try {
                Map<String, Object> layout = objectMapper.readValue(
                        layoutJson.toString(), new TypeReference<Map<String, Object>>() {});
                Map<String, Object> result = new LinkedHashMap<>(template);
                result.put("layout", layout);
                return result;
            } catch (Exception e) {
                log.warn("template layout_json 파싱 실패 (templateId={}): {}", templateId, e.getMessage());
            }
        }
        return template;
    }

    // ──────────────────────────────────────────────────────────────────────────
    // 유틸리티
    // ──────────────────────────────────────────────────────────────────────────
    private int toInt(Object v, int defaultVal) {
        if (v == null) return defaultVal;
        if (v instanceof Number) return ((Number) v).intValue();
        try { return Integer.parseInt(v.toString()); }
        catch (NumberFormatException e) { return defaultVal; }
    }
}
