// 운영 환경(momo.junggomoa.com) E2E 테스트
// 1. 프로덕션 시드 (품목, 재고)
// 2. chpark@wace.me / 박창현유통 가입
// 3. 엑셀에서 추가 업체 5개 시드 가입
// 4. 각 업체별 발주
// 5. 관리자 로그인 → 승인 → 메일 발송 검증

import pg from "pg";
import bcrypt from "bcryptjs";
import { createRequire } from "node:module";
const require2 = createRequire(import.meta.url);
const XLSX = require2("xlsx");
import path from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const BASE = process.env.E2E_BASE || "http://localhost:3000";
const DB_URL = "postgresql://momo_app:qlalfqjsgh11@183.99.177.40:5432/distribution";
const ADMIN_EMAIL = "admin@momo.com";
const ADMIN_PASS = "admin1234";

const log = (...a) => console.log("[prod-e2e]", ...a);
const fail = (msg) => { console.error("[prod-e2e] ✖", msg); process.exit(1); };

// ===== 0. 운영 사이트 살아있는지 =====
log("0. 운영 사이트 헬스체크");
const health = await fetch(`${BASE}/`).catch((e) => ({ ok: false, error: e.message }));
if (!health.ok) fail(`운영 사이트 접속 실패: ${health.error || health.status}`);
const homeText = await health.text();
const hasLanding = /HOW IT WORKS|회원가입/.test(homeText);
log(`   ${health.status} ${health.url} (랜딩=${hasLanding ? "✔" : "✖ 구버전"})`);
if (!hasLanding) console.warn("[prod-e2e] ⚠ 랜딩 페이지 키워드 없음 — 그래도 진행");

// ===== 1. DB 시드 =====
log("1. DB 시드");
const db = new pg.Client({ connectionString: DB_URL });
await db.connect();

// 관리자 비밀번호 보장
const adminHash = await bcrypt.hash(ADMIN_PASS, 10);
await db.query(
  `UPDATE momo_users SET password_hash = $1, status='ACTIVE' WHERE email = $2`,
  [adminHash, ADMIN_EMAIL]
);

// 품목 (엑셀 라인업 일부 + 면세/과세 혼합)
const seedItems = [
  { code: "PROD-EGG-01",   name: "M 유정란",       price: 10000, taxFree: "Y", stock: 200 },
  { code: "PROD-CHKN-01",  name: "M 꽃계탕",       price: 4500,  taxFree: "Y", stock: 200 },
  { code: "PROD-SOY-01",   name: "M 짜장소스",     price: 2600,  taxFree: "Y", stock: 500 },
  { code: "PROD-CLEAN-R",  name: "빨강 탈취제",    price: 9200,  taxFree: "N", stock: 100 },
  { code: "PROD-CLEAN-G",  name: "초록 탈취제",    price: 9200,  taxFree: "N", stock: 100 },
  { code: "PROD-CLEAN-B",  name: "파랑 탈취제",    price: 9200,  taxFree: "N", stock: 100 },
  { code: "PROD-CRM-01",   name: "선크림",         price: 5400,  taxFree: "N", stock: 80  },
  { code: "PROD-MUSH-01",  name: "M 꽃송이버섯",   price: 4900,  taxFree: "Y", stock: 150 },
];
for (const it of seedItems) {
  await db.query(
    `INSERT INTO momo_items (objid, item_code, item_name, unit, unit_price, is_tax_free, status, regdate)
     VALUES ($1, $2, $3, 'EA', $4, $5, 'ACTIVE', NOW())
     ON CONFLICT (item_code) DO UPDATE SET unit_price=EXCLUDED.unit_price, is_tax_free=EXCLUDED.is_tax_free, status='ACTIVE', is_del='N'`,
    [`PROD-${it.code}`, it.code, it.name, it.price, it.taxFree]
  );
}
const wh = await db.query(`SELECT objid FROM momo_warehouses WHERE wh_type='STOCK' ORDER BY wh_code LIMIT 1`);
if (wh.rowCount === 0) fail("STOCK 창고 없음");
const whObjid = wh.rows[0].objid;
for (const it of seedItems) {
  await db.query(
    `INSERT INTO momo_stocks (objid, wh_objid, item_objid, qty, update_date)
     VALUES ($1, $2, (SELECT objid FROM momo_items WHERE item_code=$3), $4, NOW())
     ON CONFLICT (wh_objid, item_objid) DO UPDATE SET qty=EXCLUDED.qty, update_date=NOW()`,
    [`PROD-STK-${it.code}`, whObjid, it.code, it.stock]
  );
}
log(`   ✔ 품목 ${seedItems.length}개 + 창고 재고 시드 완료`);

// ===== 2. 엑셀 → 추가 업체 5개 추출 =====
const xlsxPath = path.join(__dirname, "..", "docs", "2026_0410_ 금_라인업.xlsx");
const wb = XLSX.readFile(xlsxPath);
const two = XLSX.utils.sheet_to_json(wb.Sheets["TWO"], { header: 1, defval: "" });
const xlCompanies = two
  .slice(6)
  .map((r) => r[0])
  .filter((c) => typeof c === "string" && c.length >= 2 && c.length < 12 && !/[0-9()]/.test(c));
log(`   ✔ 엑셀에서 업체 ${xlCompanies.length}개 추출 (예: ${xlCompanies.slice(0, 5).join(", ")})`);

// ===== 3. 가입할 업체 목록 =====
const accounts = [
  { email: "chpark@wace.me", company: "박창현유통", password: "wace1234" },
  ...xlCompanies.slice(0, 5).map((c, i) => ({
    email: `test${i + 1}@momo.test`,
    company: c,
    password: "test1234",
  })),
];

// ===== 4. 가입 + 발주 (각 업체) =====
const apiClient = (cookieJar) => async (path, init = {}) => {
  const res = await fetch(`${BASE}${path}`, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(cookieJar.value ? { Cookie: cookieJar.value } : {}),
      ...(init.headers ?? {}),
    },
    redirect: "manual",
  });
  const sc = res.headers.getSetCookie?.() || [];
  for (const c of sc) {
    const kv = c.split(";")[0];
    const k = kv.split("=")[0];
    cookieJar.value = cookieJar.value
      ? cookieJar.value.split("; ").filter((p) => !p.startsWith(k + "=")).concat(kv).join("; ")
      : kv;
  }
  const text = await res.text();
  let json;
  try { json = JSON.parse(text); } catch { json = { raw: text.slice(0, 200) }; }
  return { status: res.status, body: json };
};

const orderIds = [];
for (const acc of accounts) {
  log(`2.${accounts.indexOf(acc) + 1}. ${acc.company} (${acc.email})`);

  // 기존 데이터 정리 — 재실행 가능하게
  await db.query(`DELETE FROM momo_order_items WHERE order_objid IN (SELECT objid FROM momo_orders WHERE customer_objid IN (SELECT objid FROM momo_users WHERE email = $1))`, [acc.email]);
  await db.query(`DELETE FROM momo_orders WHERE customer_objid IN (SELECT objid FROM momo_users WHERE email = $1)`, [acc.email]);
  await db.query(`DELETE FROM momo_users WHERE email = $1`, [acc.email]);

  const jar = { value: "" };
  const api = apiClient(jar);
  const sup = await api("/api/auth/signup", {
    method: "POST",
    body: JSON.stringify({
      email: acc.email, password: acc.password, companyName: acc.company,
      ceoName: acc.company === "박창현유통" ? "박창현" : acc.company.slice(0, 2),
      bizNo: "123-45-67890", phone: "010-1234-5678",
    }),
  });
  if (!sup.body.success) fail(`가입 실패 (${acc.email}): ${JSON.stringify(sup.body)}`);
  log(`     ✔ 가입`);

  // 품목 조회
  const list = await api("/api/m/items/list", { method: "POST", body: JSON.stringify({ keyword: "PROD-" }) });
  const items = (list.body.RESULTLIST || []).filter((r) => r.ITEM_CODE.startsWith("PROD-"));
  if (items.length === 0) fail("품목 조회 결과 없음");

  // 발주: 면세 1종 + 과세 1종 (랜덤 수량)
  const free = items.find((i) => i.IS_TAX_FREE === "Y");
  const taxable = items.find((i) => i.IS_TAX_FREE === "N");
  const qty1 = 5 + Math.floor(Math.random() * 10);
  const qty2 = 3 + Math.floor(Math.random() * 5);
  const order = await api("/api/m/orders/save", {
    method: "POST",
    body: JSON.stringify({
      lines: [
        { itemObjid: free.OBJID, qty: qty1 },
        { itemObjid: taxable.OBJID, qty: qty2 },
      ],
      memo: `프로덕션 E2E 테스트 - ${acc.company}`,
    }),
  });
  if (!order.body.success) fail(`발주 실패: ${JSON.stringify(order.body)}`);
  log(`     ✔ 발주 ${order.body.orderNo} (면세 ${qty1} + 과세 ${qty2})`);
  orderIds.push({ orderObjid: order.body.objId, orderNo: order.body.orderNo, customer: acc });
}

// ===== 5. 관리자 로그인 + 일괄 승인 =====
log(`3. 관리자 로그인`);
const adminJar = { value: "" };
const adminApi = apiClient(adminJar);
const al = await adminApi("/api/auth/login", {
  method: "POST",
  body: JSON.stringify({ userId: ADMIN_EMAIL, password: ADMIN_PASS }),
});
if (!al.body.success) fail(`관리자 로그인 실패: ${JSON.stringify(al.body)}`);
log(`     ✔ 관리자 세션`);

log(`4. 발주 승인 + 메일 발송`);
let mailSentCount = 0;
for (const o of orderIds) {
  const r = await adminApi("/api/m/orders/approve", {
    method: "POST",
    body: JSON.stringify({ objid: o.orderObjid }),
  });
  if (!r.body.success) {
    console.error(`     ✖ ${o.orderNo} 승인 실패: ${JSON.stringify(r.body)}`);
    continue;
  }
  if (r.body.mailSent) mailSentCount++;
  log(`     ✔ ${o.orderNo} (${o.customer.company}) — 메일=${r.body.mailSent ? "✔" : "✖"} ${r.body.mailError ?? ""}`);
}

// ===== 6. 후속 검증 =====
log(`5. 검증`);
const finals = await db.query(
  `SELECT O.order_no, O.status, O.total_amount, U.company_name, U.email,
          (SELECT status FROM momo_mail_logs WHERE ref_objid = O.objid ORDER BY regdate DESC LIMIT 1) AS mail_status
   FROM momo_orders O JOIN momo_users U ON O.customer_objid = U.objid
   WHERE O.regid IS NULL OR O.customer_objid IN (SELECT objid FROM momo_users WHERE email IN (${accounts.map((_, i) => `$${i + 1}`).join(",")}))
   ORDER BY O.regdate DESC LIMIT 20`,
  accounts.map((a) => a.email)
);
console.table(finals.rows.map((r) => ({
  주문번호: r.order_no, 업체: r.company_name, 이메일: r.email,
  상태: r.status, 합계: Number(r.total_amount).toLocaleString("ko-KR"),
  메일: r.mail_status,
})));

log(`✔ E2E 완료 — ${orderIds.length}건 발주 / ${mailSentCount}건 메일 발송`);
await db.end();
