/**
 * 탑씰(company_7) 버튼 스타일 일괄 변경 스크립트
 *
 * 사용법:
 *   npx ts-node scripts/btn-bulk-update-company7.ts --test    # 1건만 테스트 (ROLLBACK)
 *   npx ts-node scripts/btn-bulk-update-company7.ts --run     # 전체 실행 (COMMIT)
 *   npx ts-node scripts/btn-bulk-update-company7.ts --backup  # 백업 테이블만 생성
 *   npx ts-node scripts/btn-bulk-update-company7.ts --restore # 백업에서 원복
 */

import { Pool } from "pg";

// ── 배포 DB 연결 ──
const pool = new Pool({
  connectionString:
    "postgresql://postgres:vexplor0909!!@211.115.91.141:11134/vexplor",
});

const COMPANY_CODE = "COMPANY_7";
const BACKUP_TABLE = "screen_layouts_v2_backup_20260313";

// ── 액션별 기본 아이콘 매핑 (frontend/lib/button-icon-map.tsx 기준) ──
const actionIconMap: Record<string, string> = {
  save: "Check",
  delete: "Trash2",
  edit: "Pencil",
  navigate: "ArrowRight",
  modal: "Maximize2",
  transferData: "SendHorizontal",
  excel_download: "Download",
  excel_upload: "Upload",
  quickInsert: "Zap",
  control: "Settings",
  barcode_scan: "ScanLine",
  operation_control: "Truck",
  event: "Send",
  copy: "Copy",
};
const FALLBACK_ICON = "SquareMousePointer";

function getIconForAction(actionType?: string): string {
  if (actionType && actionIconMap[actionType]) {
    return actionIconMap[actionType];
  }
  return FALLBACK_ICON;
}

// ── 버튼 컴포넌트인지 판별 (최상위 + 탭 내부 둘 다 지원) ──
function isTopLevelButton(comp: any): boolean {
  return (
    comp.url?.includes("v2-button-primary") ||
    comp.overrides?.type === "v2-button-primary"
  );
}

function isTabChildButton(comp: any): boolean {
  return comp.componentType === "v2-button-primary";
}

function isButtonComponent(comp: any): boolean {
  return isTopLevelButton(comp) || isTabChildButton(comp);
}

// ── 탭 위젯인지 판별 ──
function isTabsWidget(comp: any): boolean {
  return (
    comp.url?.includes("v2-tabs-widget") ||
    comp.overrides?.type === "v2-tabs-widget"
  );
}

// ── 버튼 스타일 변경 (최상위 버튼용: overrides 사용) ──
function applyButtonStyle(config: any, actionType: string | undefined) {
  const iconName = getIconForAction(actionType);

  config.displayMode = "icon-text";

  config.icon = {
    name: iconName,
    type: "lucide",
    size: "보통",
    ...(config.icon?.color ? { color: config.icon.color } : {}),
  };

  config.iconTextPosition = "right";
  config.iconGap = 6;

  if (!config.style) config.style = {};
  delete config.style.width;  // 레거시 하드코딩 너비 제거 (size.width만 사용)
  config.style.borderRadius = "8px";
  config.style.labelColor = "#FFFFFF";
  config.style.fontSize = "12px";
  config.style.fontWeight = "normal";
  config.style.labelTextAlign = "left";

  if (actionType === "delete") {
    config.style.backgroundColor = "#F04544";
  } else if (actionType === "excel_upload" || actionType === "excel_download") {
    config.style.backgroundColor = "#212121";
  } else {
    config.style.backgroundColor = "#3B83F6";
  }
}

function updateButtonStyle(comp: any): boolean {
  if (isTopLevelButton(comp)) {
    const overrides = comp.overrides || {};
    const actionType = overrides.action?.type;

    if (!comp.size) comp.size = {};
    comp.size.height = 40;

    applyButtonStyle(overrides, actionType);
    comp.overrides = overrides;
    return true;
  }

  if (isTabChildButton(comp)) {
    const config = comp.componentConfig || {};
    const actionType = config.action?.type;

    if (!comp.size) comp.size = {};
    comp.size.height = 40;

    applyButtonStyle(config, actionType);
    comp.componentConfig = config;

    // 탭 내부 버튼은 렌더러가 comp.style (최상위)에서 스타일을 읽음
    if (!comp.style) comp.style = {};
    comp.style.borderRadius = "8px";
    comp.style.labelColor = "#FFFFFF";
    comp.style.fontSize = "12px";
    comp.style.fontWeight = "normal";
    comp.style.labelTextAlign = "left";
    comp.style.backgroundColor = config.style.backgroundColor;

    return true;
  }

  return false;
}

// ── 백업 테이블 생성 ──
async function createBackup() {
  console.log(`\n=== 백업 테이블 생성: ${BACKUP_TABLE} ===`);

  const exists = await pool.query(
    `SELECT to_regclass($1) AS tbl`,
    [BACKUP_TABLE],
  );
  if (exists.rows[0].tbl) {
    console.log(`백업 테이블이 이미 존재합니다: ${BACKUP_TABLE}`);
    const count = await pool.query(`SELECT COUNT(*) FROM ${BACKUP_TABLE}`);
    console.log(`기존 백업 레코드 수: ${count.rows[0].count}`);
    return;
  }

  await pool.query(
    `CREATE TABLE ${BACKUP_TABLE} AS
     SELECT * FROM screen_layouts_v2
     WHERE company_code = $1`,
    [COMPANY_CODE],
  );

  const count = await pool.query(`SELECT COUNT(*) FROM ${BACKUP_TABLE}`);
  console.log(`백업 완료. 레코드 수: ${count.rows[0].count}`);
}

// ── 백업에서 원복 ──
async function restoreFromBackup() {
  console.log(`\n=== 백업에서 원복: ${BACKUP_TABLE} ===`);

  const result = await pool.query(
    `UPDATE screen_layouts_v2 AS target
     SET layout_data = backup.layout_data,
         updated_at = backup.updated_at
     FROM ${BACKUP_TABLE} AS backup
     WHERE target.screen_id = backup.screen_id
       AND target.company_code = backup.company_code
       AND target.layer_id = backup.layer_id`,
  );
  console.log(`원복 완료. 변경된 레코드 수: ${result.rowCount}`);
}

// ── 메인: 버튼 일괄 변경 ──
async function updateButtons(testMode: boolean) {
  const modeLabel = testMode ? "테스트 (1건, ROLLBACK)" : "전체 실행 (COMMIT)";
  console.log(`\n=== 버튼 일괄 변경 시작 [${modeLabel}] ===`);

  // company_7 레코드 조회
  const rows = await pool.query(
    `SELECT screen_id, layer_id, company_code, layout_data
     FROM screen_layouts_v2
     WHERE company_code = $1
     ORDER BY screen_id, layer_id`,
    [COMPANY_CODE],
  );
  console.log(`대상 레코드 수: ${rows.rowCount}`);

  if (!rows.rowCount) {
    console.log("변경할 레코드가 없습니다.");
    return;
  }

  const client = await pool.connect();
  try {
    await client.query("BEGIN");

    let totalUpdated = 0;
    let totalButtons = 0;
    const targetRows = testMode ? [rows.rows[0]] : rows.rows;

    for (const row of targetRows) {
      const layoutData = row.layout_data;
      if (!layoutData?.components || !Array.isArray(layoutData.components)) {
        continue;
      }

      let buttonsInRow = 0;
      for (const comp of layoutData.components) {
        // 최상위 버튼 처리
        if (updateButtonStyle(comp)) {
          buttonsInRow++;
        }

        // 탭 위젯 내부 버튼 처리
        if (isTabsWidget(comp)) {
          const tabs = comp.overrides?.tabs || [];
          for (const tab of tabs) {
            const tabComps = tab.components || [];
            for (const tabComp of tabComps) {
              if (updateButtonStyle(tabComp)) {
                buttonsInRow++;
              }
            }
          }
        }
      }

      if (buttonsInRow > 0) {
        await client.query(
          `UPDATE screen_layouts_v2
           SET layout_data = $1, updated_at = NOW()
           WHERE screen_id = $2 AND company_code = $3 AND layer_id = $4`,
          [JSON.stringify(layoutData), row.screen_id, row.company_code, row.layer_id],
        );
        totalUpdated++;
        totalButtons += buttonsInRow;

        console.log(
          `  screen_id=${row.screen_id}, layer_id=${row.layer_id} → 버튼 ${buttonsInRow}개 변경`,
        );

        // 테스트 모드: 변경 전후 비교를 위해 첫 번째 버튼 출력
        if (testMode) {
          const sampleBtn = layoutData.components.find(isButtonComponent);
          if (sampleBtn) {
            console.log("\n--- 변경 후 샘플 버튼 ---");
            console.log(JSON.stringify(sampleBtn, null, 2));
          }
        }
      }
    }

    console.log(`\n--- 결과 ---`);
    console.log(`변경된 레코드: ${totalUpdated}개`);
    console.log(`변경된 버튼: ${totalButtons}개`);

    if (testMode) {
      await client.query("ROLLBACK");
      console.log("\n[테스트 모드] ROLLBACK 완료. 실제 DB 변경 없음.");
    } else {
      await client.query("COMMIT");
      console.log("\nCOMMIT 완료.");
    }
  } catch (err) {
    await client.query("ROLLBACK");
    console.error("\n에러 발생. ROLLBACK 완료.", err);
    throw err;
  } finally {
    client.release();
  }
}

// ── CLI 진입점 ──
async function main() {
  const arg = process.argv[2];

  if (!arg || !["--test", "--run", "--backup", "--restore"].includes(arg)) {
    console.log("사용법:");
    console.log("  --test    : 1건 테스트 (ROLLBACK, DB 변경 없음)");
    console.log("  --run     : 전체 실행 (COMMIT)");
    console.log("  --backup  : 백업 테이블 생성");
    console.log("  --restore : 백업에서 원복");
    process.exit(1);
  }

  try {
    if (arg === "--backup") {
      await createBackup();
    } else if (arg === "--restore") {
      await restoreFromBackup();
    } else if (arg === "--test") {
      await createBackup();
      await updateButtons(true);
    } else if (arg === "--run") {
      await createBackup();
      await updateButtons(false);
    }
  } catch (err) {
    console.error("스크립트 실행 실패:", err);
    process.exit(1);
  } finally {
    await pool.end();
  }
}

main();
