/**
 * 시퀀스 관리 메뉴(시스템 관리 > 시퀀스 관리) idempotent 시드.
 *
 *  - 부팅 시 1회 실행.
 *  - menu_url='/admin/systemMng/sequenceMng' 이 이미 있으면 skip(정규화만).
 *  - 부모(시스템 관리) 찾기 — 다음 순서로 fallback:
 *      (1) menu_name_kor = '시스템 관리' / '시스템관리'
 *      (2) menu_url LIKE '/admin/systemMng/%' 자식들의 가장 빈도 높은 parent_obj_id
 *      (3) menu_url LIKE '/admin/system%' 자식들의 가장 빈도 높은 parent_obj_id
 *      (4) 같은 회사 코드의 메뉴 중 menu_name_kor LIKE '%시스템%' (느슨한 매칭)
 *  - 부모를 찾지 못하면 등록을 건너뛰고 진단 로그 남김(운영 환경에서 수동 등록 가능).
 */
import { getPool } from "../database/db";
import { logger } from "../utils/logger";

const TARGET_URL = "/admin/systemMng/sequenceMng";
const MENU_NAME_KOR = "시퀀스 관리";
const MENU_NAME_ENG = "Sequence Management";

async function findSystemMngParentObjId(pool: ReturnType<typeof getPool>): Promise<number | null> {
  // (1) 이름이 정확히 '시스템 관리' or '시스템관리'
  const byName = await pool.query<{ objid: number }>(
    `SELECT objid FROM menu_info
      WHERE COALESCE(status,'active') = 'active'
        AND (menu_name_kor = '시스템 관리' OR menu_name_kor = '시스템관리')
      ORDER BY objid ASC
      LIMIT 1`,
  );
  if (byName.rowCount && byName.rowCount > 0) {
    return Number(byName.rows[0].objid);
  }

  // (2) /admin/systemMng/* 자식들의 부모 빈도 1위
  const byChildren1 = await pool.query<{ parent_obj_id: number; cnt: string }>(
    `SELECT parent_obj_id, COUNT(*)::text AS cnt
       FROM menu_info
      WHERE menu_url LIKE '/admin/systemMng/%'
        AND parent_obj_id IS NOT NULL
      GROUP BY parent_obj_id
      ORDER BY cnt DESC NULLS LAST
      LIMIT 1`,
  );
  if (byChildren1.rowCount && byChildren1.rowCount > 0) {
    return Number(byChildren1.rows[0].parent_obj_id);
  }

  // (3) /admin/system* 자식들 (대소문자/언더스코어 변형 대비)
  const byChildren2 = await pool.query<{ parent_obj_id: number; cnt: string }>(
    `SELECT parent_obj_id, COUNT(*)::text AS cnt
       FROM menu_info
      WHERE (menu_url ILIKE '/admin/system%' OR menu_url ILIKE '/admin/sys%')
        AND parent_obj_id IS NOT NULL
      GROUP BY parent_obj_id
      ORDER BY cnt DESC NULLS LAST
      LIMIT 1`,
  );
  if (byChildren2.rowCount && byChildren2.rowCount > 0) {
    return Number(byChildren2.rows[0].parent_obj_id);
  }

  // (4) 느슨한 이름 매칭
  const byNameLike = await pool.query<{ objid: number }>(
    `SELECT objid FROM menu_info
      WHERE COALESCE(status,'active') = 'active'
        AND menu_name_kor LIKE '%시스템%'
      ORDER BY objid ASC
      LIMIT 1`,
  );
  if (byNameLike.rowCount && byNameLike.rowCount > 0) {
    return Number(byNameLike.rows[0].objid);
  }

  return null;
}

export async function ensureSequenceMngMenu(): Promise<void> {
  const pool = getPool();
  try {
    // (1) 이미 있으면 종료
    const existing = await pool.query(
      `SELECT objid FROM menu_info WHERE menu_url = $1 LIMIT 1`,
      [TARGET_URL],
    );
    if (existing.rowCount && existing.rowCount > 0) {
      await pool.query(
        `UPDATE menu_info
            SET menu_name_kor = COALESCE(NULLIF(menu_name_kor,''), $1),
                menu_name_eng = COALESCE(NULLIF(menu_name_eng,''), $2),
                status = 'active'
          WHERE menu_url = $3`,
        [MENU_NAME_KOR, MENU_NAME_ENG, TARGET_URL],
      );
      logger.info(`✅ 시퀀스 관리 메뉴 이미 존재 — 정규화만 수행`);
      return;
    }

    // (2) 부모 찾기 (다중 fallback)
    const parentObjId = await findSystemMngParentObjId(pool);
    if (parentObjId == null) {
      logger.warn(
        `[sequenceMngMenu] '시스템 관리' 메뉴를 찾지 못해 시퀀스 관리 시드를 건너뜁니다. ` +
        `메뉴 관리 UI 에서 수동 등록하거나, menu_info 에 다음 행을 추가하세요:\n` +
        `  parent_obj_id = (시스템 관리 OBJID), menu_name_kor = '시퀀스 관리',\n` +
        `  menu_url = '/admin/systemMng/sequenceMng', status = 'active'.`,
      );
      return;
    }

    // (3) seq 와 objid 산출
    const maxSeq = await pool.query<{ max_seq: number | null }>(
      `SELECT COALESCE(MAX(seq), 0)::int AS max_seq
         FROM menu_info WHERE parent_obj_id = $1`,
      [parentObjId],
    );
    const nextSeq = (Number(maxSeq.rows[0]?.max_seq) || 0) + 1;

    const nextObjid = await pool.query<{ next: number }>(
      `SELECT (COALESCE(MAX(objid::bigint), 100000) + 1)::int AS next FROM menu_info`,
    );
    const objid = Number(nextObjid.rows[0].next);

    // (4) 부모 행에서 company_code/writer 승계 (참조 일관성)
    const parentRow = await pool.query<{ company_code: string | null; writer: string | null }>(
      `SELECT company_code, writer FROM menu_info WHERE objid = $1`,
      [parentObjId],
    );
    const companyCode = parentRow.rows[0]?.company_code ?? "*";
    const writer = parentRow.rows[0]?.writer ?? "system-seed";

    // (5) INSERT
    await pool.query(
      `INSERT INTO menu_info
         (objid, parent_obj_id, menu_name_kor, menu_name_eng, menu_url, seq,
          menu_type, company_code, writer, regdate, status)
       VALUES ($1, $2, $3, $4, $5, $6, 2, $7, $8, NOW(), 'active')`,
      [objid, parentObjId, MENU_NAME_KOR, MENU_NAME_ENG, TARGET_URL, nextSeq, companyCode, writer],
    );

    logger.info(
      `🌱 시퀀스 관리 메뉴 등록 완료: objid=${objid}, parent=${parentObjId}, seq=${nextSeq}, company=${companyCode}`,
    );
  } catch (e: any) {
    logger.warn(`[sequenceMngMenu] 메뉴 시드 실패(계속 진행): ${e?.message?.slice(0, 200)}`);
  }
}
