package com.gxwebsoft.credit.service;

import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * 刷新 credit_company 表内的“关联记录数”字段。
 *
 * <p>这些字段是通过统计：credit_company.id = 关联表.company_id（且 deleted=0） 得到。</p>
 */
@Service
public class CreditCompanyRecordCountService {

    public enum CountType {
        ADMINISTRATIVE_LICENSE("credit_administrative_license", "credit_administrative_license"),
        BANKRUPTCY("credit_bankruptcy", "credit_bankruptcy"),
        BRANCH("credit_branch", "credit_branch"),
        BREACH_OF_TRUST("credit_breach_of_trust", "credit_breach_of_trust"),
        CASE_FILING("credit_case_filing", "credit_case_filing"),
        COMPETITOR("credit_competitor", "credit_competitor"),
        COURT_ANNOUNCEMENT("credit_court_announcement", "credit_court_announcement"),
        COURT_SESSION("credit_court_session", "credit_court_session"),
        CUSTOMER("credit_customer", "credit_customer"),
        DELIVERY_NOTICE("credit_delivery_notice", "credit_delivery_notice"),
        EXTERNAL("credit_external", "credit_external"),
        FINAL_VERSION("credit_final_version", "credit_final_version"),
        GQDJ("credit_gqdj", "credit_gqdj"),
        HISTORICAL_LEGAL_PERSON("credit_historical_legal_person", "credit_historical_legal_person"),
        JUDGMENT_DEBTOR("credit_judgment_debtor", "credit_judgment_debtor"),
        JUDICIAL_DOCUMENT("credit_judicial_document", "credit_judicial_document"),
        JUDICIARY("credit_judiciary", "credit_judiciary"),
        MEDIATION("credit_mediation", "credit_mediation"),
        NEARBY_COMPANY("credit_nearby_company", "credit_nearby_company"),
        PATENT("credit_patent", "credit_patent"),
        RISK_RELATION("credit_risk_relation", "credit_risk_relation"),
        SUPPLIER("credit_supplier", "credit_supplier"),
        SUSPECTED_RELATIONSHIP("credit_suspected_relationship", "credit_suspected_relationship"),
        USER("credit_user", "credit_user"),
        XGXF("credit_xgxf", "credit_xgxf");

        private final String companyColumn;
        private final String sourceTable;

        CountType(String companyColumn, String sourceTable) {
            this.companyColumn = companyColumn;
            this.sourceTable = sourceTable;
        }

        public String getCompanyColumn() {
            return companyColumn;
        }

        public String getSourceTable() {
            return sourceTable;
        }
    }

    private final NamedParameterJdbcTemplate namedJdbc;

    public CreditCompanyRecordCountService(NamedParameterJdbcTemplate namedJdbc) {
        this.namedJdbc = namedJdbc;
    }

    /**
     * 刷新某个“记录数”字段（只更新传入 companyIds）。
     */
    public void refresh(CountType type, Collection<Integer> companyIds) {
        if (type == null || CollectionUtils.isEmpty(companyIds)) {
            return;
        }
        List<Integer> ids = normalizeCompanyIds(companyIds);
        if (ids.isEmpty()) {
            return;
        }

        // 表/字段名来自固定枚举，不允许外部传入，避免 SQL 注入。
        //
        // 这里不要用「UPDATE ... SET col=(SELECT COUNT... WHERE t.company_id=c.id)」的相关子查询：
        // 如果关联表缺少 (company_id, deleted) 索引，会导致对每个 company_id 都进行一次全表扫描，极慢，
        // 进而容易触发 JDBC/MySQL 侧的超时/断链（Communications link failure）。
        //
        // 用聚合后再 JOIN 的方式：每个 chunk 只扫描一次关联表。
        String sql = ""
            + "UPDATE credit_company c "
            + "LEFT JOIN ("
            + "  SELECT company_id, COUNT(1) AS cnt "
            + "  FROM " + type.getSourceTable() + " "
            + "  WHERE deleted = 0 AND company_id IN (:ids) "
            + "  GROUP BY company_id"
            + ") t ON t.company_id = c.id "
            + "SET c." + type.getCompanyColumn() + " = IFNULL(t.cnt, 0) "
            + "WHERE c.id IN (:ids)";

        final int inChunkSize = 500;
        for (int i = 0; i < ids.size(); i += inChunkSize) {
            List<Integer> chunk = ids.subList(i, Math.min(ids.size(), i + inChunkSize));
            namedJdbc.update(sql, new MapSqlParameterSource("ids", chunk));
        }
    }

    /**
     * 刷新全部“记录数”字段（只更新传入 companyIds）。
     */
    public void refreshAll(Collection<Integer> companyIds) {
        if (CollectionUtils.isEmpty(companyIds)) {
            return;
        }
        for (CountType type : CountType.values()) {
            refresh(type, companyIds);
        }
    }

    private static List<Integer> normalizeCompanyIds(Collection<Integer> companyIds) {
        Set<Integer> unique = new LinkedHashSet<>();
        for (Integer id : companyIds) {
            if (id != null && id > 0) {
                unique.add(id);
            }
        }
        return new ArrayList<>(unique);
    }
}
