/**
 * 채번 룰 의존성 분석 유틸
 *  - 룰이 동작하려면 적용 테이블에 어떤 폼 키 컬럼들이 있어야 하는지 추출
 *  - 테이블 타입 관리에서 룰 선택 시 검증에 사용
 *
 *  의존이 생기는 케이스:
 *    1) reference 파트 (mode=master) : 폼키(referenceColumnName) 가 적용 테이블의 컬럼이어야 한다
 *    2) reference 파트 (mode=form)   : 폼키(referenceColumnName) 가 적용 테이블의 컬럼이어야 한다
 *    3) category 파트                : categoryKey="table.col" 일 때, table 이 적용 테이블이면 col 이 의존
 *                                       (table 이 다른 테이블이면 그 테이블 마스터 조회 — 의존 아님)
 *
 *  의존이 아닌 케이스:
 *    - sequence / date / number / text / reference(constant)
 */

export interface NumberingRulePartLite {
  partType: string;
  autoConfig?: Record<string, any>;
}
export interface NumberingRuleLite {
  ruleId?: string;
  ruleName?: string;
  parts?: NumberingRulePartLite[];
}

/** 룰에서 적용 테이블에 있어야 하는 폼 키(컬럼명) 목록을 추출 */
export function extractRequiredFormKeys(
  rule: NumberingRuleLite | null | undefined,
  tableName?: string,
): string[] {
  if (!rule?.parts) return [];
  const keys: string[] = [];
  for (const p of rule.parts) {
    const c = (p.autoConfig ?? {}) as Record<string, any>;
    if (p.partType === "reference") {
      const mode = c.mode ?? (c.sourceTableName ? "master" : c.constantValue ? "constant" : "form");
      // master/form 모두 폼키(referenceColumnName) 필요
      if ((mode === "master" || mode === "form") && c.referenceColumnName) {
        keys.push(String(c.referenceColumnName));
      }
    } else if (p.partType === "category") {
      // categoryKey="table.col" → table 이 적용 테이블이면 col 이 의존
      const key: string = c.categoryKey ?? "";
      if (typeof key === "string" && key.includes(".")) {
        const [tbl, col] = key.split(".");
        if (tableName && tbl && col && tbl === tableName) {
          keys.push(col);
        }
        // 다른 테이블이면 마스터 조회 — 적용 테이블 의존은 아님
      } else if (typeof key === "string" && key && tableName) {
        // table 명시 안 됨 → 적용 테이블의 컬럼명으로 간주
        keys.push(key);
      }
    }
  }
  // 중복 제거 + 의미있는 값만
  return Array.from(new Set(keys.filter(Boolean)));
}

export interface DependencyCheckResult {
  required: string[];
  satisfied: string[];
  missing: string[];
}

/** 룰의 요구 컬럼 vs 실제 테이블 컬럼 → 충족/누락 분석 */
export function checkRuleDependencies(
  rule: NumberingRuleLite | null | undefined,
  tableName: string,
  tableColumns: Array<{ columnName: string }>,
): DependencyCheckResult {
  const required = extractRequiredFormKeys(rule, tableName);
  const colSet = new Set(tableColumns.map((c) => c.columnName.toLowerCase()));
  const satisfied: string[] = [];
  const missing: string[] = [];
  for (const k of required) {
    if (colSet.has(k.toLowerCase())) satisfied.push(k);
    else missing.push(k);
  }
  return { required, satisfied, missing };
}
