package com.erp.service;

import com.erp.common.BaseService;
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.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ShippingOrderService extends BaseService {

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

    // ─── 출하지시 목록 조회 ──────────────────────────────────────────────────────

    public List<Map<String, Object>> getShippingOrderList(Map<String, Object> params) {
        List<Map<String, Object>> list = sqlSession.selectList("shippingOrder.getShippingOrderList", params);
        for (Map<String, Object> row : list) {
            Object items = row.get("items");
            if (items != null) {
                try {
                    row.put("items", objectMapper.readValue(items.toString(), List.class));
                } catch (Exception e) {
                    row.put("items", List.of());
                }
            }
        }
        return list;
    }

    // ─── 다음 출하지시번호 미리보기 ─────────────────────────────────────────────

    public Map<String, Object> previewNextNo(Map<String, Object> params) {
        String companyCode = (String) params.get("company_code");
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_m_mdd"));
        Map<String, Object> seqParams = new HashMap<>();
        seqParams.put("company_code", companyCode);
        seqParams.put("like_pattern", "SI-" + today + "-%");
        Map<String, Object> seqRow = sqlSession.selectOne("shippingOrder.getShippingOrderSeqNo", seqParams);
        long seq = seqRow != null ? ((Number) seqRow.get("seq")).longValue() : 1L;
        Map<String, Object> result = new HashMap<>();
        result.put("instruction_no", String.format("SI-%s-%03d", today, seq));
        return result;
    }

    // ─── 출하지시 저장 (신규/수정) ────────────────────────────────────────────────

    @Transactional
    public Map<String, Object> save(Map<String, Object> params) {
        String companyCode = (String) params.get("company_code");
        String userId = (String) params.get("user_id");
        Object editId = params.get("id");

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> items = (List<Map<String, Object>>) params.get("items");

        Long instructionId;
        String instructionNo;

        if (editId != null) {
            // 수정
            instructionId = ((Number) editId).longValue();
            Map<String, Object> infoParams = new HashMap<>();
            infoParams.put("company_code", companyCode);
            infoParams.put("id", instructionId);
            Map<String, Object> existing = sqlSession.selectOne("shippingOrder.getShippingOrderInfo", infoParams);
            if (existing == null) {
                throw new IllegalArgumentException("출하지시를 찾을 수 없습니다");
            }
            instructionNo = (String) existing.get("instruction_no");
            params.put("updated_by", userId);
            sqlSession.update("shippingOrder.updateShippingOrder", params);

            Map<String, Object> delParams = new HashMap<>();
            delParams.put("company_code", companyCode);
            delParams.put("instruction_id", instructionId);
            sqlSession.delete("shippingOrder.deleteShippingOrderDetails", delParams);
        } else {
            // 신규 - 채번 생성
            String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy_m_mdd"));
            Map<String, Object> seqParams = new HashMap<>();
            seqParams.put("company_code", companyCode);
            seqParams.put("like_pattern", "SI-" + today + "-%");
            Map<String, Object> seqRow = sqlSession.selectOne("shippingOrder.getShippingOrderSeqNo", seqParams);
            long seq = seqRow != null ? ((Number) seqRow.get("seq")).longValue() : 1L;
            instructionNo = String.format("SI-%s-%03d", today, seq);
            params.put("instruction_no", instructionNo);
            params.put("created_by", userId);
            sqlSession.insert("shippingOrder.insertShippingOrder", params);
            instructionId = ((Number) params.get("id")).longValue();
        }

        // 상세 삽입
        if (items != null) {
            for (Map<String, Object> item : items) {
                Map<String, Object> d = new HashMap<>();
                d.put("company_code", companyCode);
                d.put("instruction_id", instructionId);
                d.put("shipment_plan_id", item.get("shipment_plan_id"));
                d.put("sales_order_id", item.get("sales_order_id"));
                d.put("detail_id", item.get("detail_id"));
                d.put("item_code", item.get("item_code"));
                d.put("item_name", item.get("item_name"));
                d.put("spec", item.get("spec"));
                d.put("material", item.get("material"));
                d.put("order_qty", item.getOrDefault("order_qty", 0));
                d.put("plan_qty", item.getOrDefault("plan_qty", 0));
                d.put("ship_qty", item.getOrDefault("ship_qty", 0));
                d.put("source_type", item.getOrDefault("source_type", "shipment_plan"));
                d.put("created_by", userId);
                sqlSession.insert("shippingOrder.insertShippingOrderDetail", d);
            }
        }

        Map<String, Object> result = new HashMap<>();
        result.put("id", instructionId);
        result.put("instruction_no", instructionNo);
        return result;
    }

    // ─── 출하지시 삭제 (일괄) ─────────────────────────────────────────────────────

    @Transactional
    public Map<String, Object> remove(Map<String, Object> params) {
        int deletedCount = sqlSession.delete("shippingOrder.deleteShippingOrders", params);
        Map<String, Object> result = new HashMap<>();
        result.put("deleted_count", deletedCount);
        return result;
    }

    // ─── 소스 데이터 (모달 패널) ────────────────────────────────────────────────

    public Map<String, Object> getShipmentPlanSource(Map<String, Object> params) {
        applySourcePagination(params);
        Number cntNum1 = sqlSession.selectOne("shippingOrder.getShipmentPlanSourceCnt", params);
        int totalCount = cntNum1 != null ? cntNum1.intValue() : 0;
        List<Map<String, Object>> data = sqlSession.selectList("shippingOrder.getShipmentPlanSourceList", params);
        return buildSourceResponse(data, totalCount, params);
    }

    public Map<String, Object> getSalesOrderSource(Map<String, Object> params) {
        applySourcePagination(params);
        Number cntNum2 = sqlSession.selectOne("shippingOrder.getSalesOrderSourceCnt", params);
        int totalCount = cntNum2 != null ? cntNum2.intValue() : 0;
        List<Map<String, Object>> data = sqlSession.selectList("shippingOrder.getSalesOrderSourceList", params);
        return buildSourceResponse(data, totalCount, params);
    }

    public Map<String, Object> getItemSource(Map<String, Object> params) {
        applySourcePagination(params);
        Number cntNum3 = sqlSession.selectOne("shippingOrder.getItemSourceCnt", params);
        int totalCount = cntNum3 != null ? cntNum3.intValue() : 0;
        List<Map<String, Object>> data = sqlSession.selectList("shippingOrder.getItemSourceList", params);
        return buildSourceResponse(data, totalCount, params);
    }

    // ─── 내부 헬퍼 ───────────────────────────────────────────────────────────────

    private void applySourcePagination(Map<String, Object> params) {
        int page = toInt(params.getOrDefault("page", 1), 1);
        int pageSize = Math.min(100, Math.max(1, toInt(params.getOrDefault("page_size", 20), 20)));
        params.put("page", page);
        params.put("page_size", pageSize);
        params.put("offset", (page - 1) * pageSize);
    }

    private Map<String, Object> buildSourceResponse(List<Map<String, Object>> data, int totalCount,
                                                      Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        result.put("data", data);
        result.put("total_count", totalCount);
        result.put("page", params.get("page"));
        result.put("page_size", params.get("page_size"));
        return result;
    }

    private int toInt(Object val, int def) {
        if (val == null) return def;
        try { return Integer.parseInt(val.toString()); } catch (Exception e) { return def; }
    }
}
