// 발주에 ITEM 라인 추가 — 본인 또는 admin, REQUESTED/APPROVED 상태.
// 재고/숨김/한도 검증 후 momo_order_items INSERT + 합계 재집계.
import { NextRequest, NextResponse } from "next/server";
import { pool } from "@/lib/db";
import { createObjectId } from "@/lib/utils";
import { requireMomoUser } from "@/lib/momo-guard";
import { calcLine } from "@/lib/momo-pricing";

let lockColsEnsured = false;
async function ensureLockCols() {
  if (lockColsEnsured) return;
  try {
    await pool.query(`
      ALTER TABLE momo_orders
        ADD COLUMN IF NOT EXISTS editing_by TEXT,
        ADD COLUMN IF NOT EXISTS editing_at TIMESTAMP;
    `);
    lockColsEnsured = true;
  } catch { /* ignore */ }
}

interface AddItem { itemObjid: string; qty: number }

export async function POST(req: NextRequest) {
  const r = await requireMomoUser();
  if (r instanceof NextResponse) return r;
  await ensureLockCols();

  const body = await req.json().catch(() => ({}));
  const { orderObjid, items } = body as { orderObjid?: string; items?: AddItem[] };
  if (!orderObjid || !Array.isArray(items) || items.length === 0) {
    return NextResponse.json({ success: false, message: "잘못된 요청입니다." }, { status: 400 });
  }
  for (const it of items) {
    if (!it.itemObjid || !Number.isFinite(Number(it.qty)) || Number(it.qty) <= 0) {
      return NextResponse.json({ success: false, message: "품목/수량 형식이 올바르지 않습니다." }, { status: 400 });
    }
  }
  const isAdmin = r.user.isAdmin || r.user.role === "ADMIN" || r.user.userType === "A";

  const client = await pool.connect();
  try {
    await client.query("BEGIN");
    const orderRes = await client.query(
      `SELECT customer_objid, status, editing_by, editing_at,
              (editing_at IS NOT NULL AND editing_at > NOW() - INTERVAL '2 minutes') AS lock_alive
         FROM momo_orders WHERE objid = $1 FOR UPDATE`,
      [orderObjid]
    );
    if (orderRes.rowCount === 0) {
      await client.query("ROLLBACK");
      return NextResponse.json({ success: false, message: "발주를 찾을 수 없습니다." }, { status: 404 });
    }
    const order = orderRes.rows[0];
    const userOwn = r.user.objid ?? r.user.userId;
    if (!isAdmin && order.customer_objid !== userOwn && order.customer_objid !== r.user.userId) {
      await client.query("ROLLBACK");
      return NextResponse.json({ success: false, message: "권한이 없습니다." }, { status: 403 });
    }
    // admin: 입금완료(PAID) 까지 품목 추가 허용. USER: 출고완료(APPROVED) 까지만.
    // 계산서발행(INVOICED) / 취소(CANCELLED) 이후는 누구도 추가 불가.
    if (isAdmin) {
      if (!["REQUESTED", "APPROVED", "PAID"].includes(order.status)) {
        await client.query("ROLLBACK");
        return NextResponse.json({ success: false, message: "계산서발행 이후 발주는 품목 추가 불가." }, { status: 400 });
      }
    } else {
      if (order.status !== "REQUESTED" && order.status !== "APPROVED") {
        await client.query("ROLLBACK");
        return NextResponse.json({ success: false, message: "입금완료 이후 발주는 품목 추가 불가." }, { status: 400 });
      }
    }
    // 편집 락 체크
    const myId = String(r.user.objid || r.user.userId);
    if (order.lock_alive && order.editing_by && order.editing_by !== myId) {
      await client.query("ROLLBACK");
      const lockName = await client.query<{ user_name: string }>(
        `SELECT user_name FROM user_info WHERE user_id = $1`, [order.editing_by]
      );
      const name = lockName.rows[0]?.user_name || order.editing_by;
      return NextResponse.json({
        success: false,
        locked: true,
        message: `${name} 담당자가 수정 중입니다. 잠시 후 다시 시도하세요.`,
      }, { status: 409 });
    }

    // 품목 정보 조회 (재고/단가 등)
    const itemIds = items.map((i) => i.itemObjid);
    const placeholders = itemIds.map((_, i) => `$${i + 1}`).join(",");
    const itemsRes = await client.query(
      `SELECT
         I.objid, I.item_name, I.unit_price, I.is_tax_free, I.max_order_qty,
         COALESCE(I.is_hidden, 'N') AS is_hidden,
         COALESCE(I.requires_delivery, 'N') AS requires_delivery,
         COALESCE((
           SELECT SUM(S.qty) FROM momo_stocks S
           JOIN momo_warehouses W ON S.wh_objid = W.objid
           WHERE S.item_objid = I.objid AND COALESCE(W.is_del,'N') != 'Y'
         ), 0) AS stock_qty
       FROM momo_items I
       WHERE I.objid IN (${placeholders}) AND COALESCE(I.is_del, 'N') != 'Y'`,
      itemIds
    );
    const itemMap = new Map(itemsRes.rows.map((row) => [row.objid as string, row]));

    // 검증 (admin 은 재고/한도 우회)
    if (!isAdmin) {
      // 사용자별 권한
      const u = await client.query(
        `SELECT COALESCE(unlimited_qty,'N') AS u, COALESCE(view_hidden,'N') AS v FROM user_info WHERE user_id = $1`,
        [order.customer_objid]
      );
      const unlimited = u.rows[0]?.u === "Y";
      const viewHidden = u.rows[0]?.v === "Y";
      for (const ln of items) {
        const it = itemMap.get(ln.itemObjid);
        if (!it) {
          await client.query("ROLLBACK");
          return NextResponse.json({ success: false, message: `존재하지 않는 품목: ${ln.itemObjid}` }, { status: 400 });
        }
        if (it.is_hidden === "Y" && !viewHidden) {
          await client.query("ROLLBACK");
          return NextResponse.json({ success: false, message: `${it.item_name} 은 발주 불가 품목입니다.` }, { status: 400 });
        }
        const stock = Number(it.stock_qty ?? 0);
        // 택배 전용 품목은 재고 무관하게 추가 가능
        const isDeliveryItem = it.requires_delivery === "Y";
        if (!isDeliveryItem && Number(ln.qty) > stock) {
          await client.query("ROLLBACK");
          return NextResponse.json({ success: false, message: `${it.item_name} — 재고(${stock}) 초과` }, { status: 400 });
        }
        if (!unlimited) {
          const maxQ = it.max_order_qty == null ? 0 : Number(it.max_order_qty);
          if (maxQ > 0 && Number(ln.qty) > maxQ) {
            await client.query("ROLLBACK");
            return NextResponse.json({ success: false, message: `${it.item_name} — 1회 발주 한도(${maxQ}) 초과` }, { status: 400 });
          }
        }
      }
    }

    // 다음 seq
    const seqRes = await client.query(
      `SELECT COALESCE(MAX(seq), 0) AS m FROM momo_order_items WHERE order_objid = $1`,
      [orderObjid]
    );
    let nextSeq = Number(seqRes.rows[0]?.m ?? 0) + 1;

    for (const ln of items) {
      const it = itemMap.get(ln.itemObjid);
      if (!it) continue;
      const unitPrice = Number(it.unit_price);
      const qty = Number(ln.qty);
      const isFree = it.is_tax_free === "Y";
      const calc = calcLine({ unitPrice, qty, isTaxFree: isFree });
      await client.query(
        `INSERT INTO momo_order_items (
           objid, order_objid, item_objid, item_name_snap, unit_price, qty,
           is_tax_free, supply_amount, vat_amount, total_amount, seq, kind
         ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, 'ITEM')`,
        [createObjectId(), orderObjid, ln.itemObjid, it.item_name, unitPrice, qty,
         isFree ? "Y" : "N", calc.supplyAmount, calc.vatAmount, calc.totalAmount, nextSeq]
      );
      nextSeq++;
    }

    // 합계 재집계
    const sumRes = await client.query(
      `SELECT
         COALESCE(SUM(supply_amount), 0) AS supply,
         COALESCE(SUM(vat_amount), 0)    AS vat,
         COALESCE(SUM(total_amount), 0)  AS total,
         COALESCE(SUM(CASE WHEN is_tax_free='Y' THEN supply_amount ELSE 0 END), 0) AS taxfree,
         COALESCE(SUM(CASE WHEN is_tax_free='N' THEN supply_amount ELSE 0 END), 0) AS taxable,
         COALESCE(SUM(CASE WHEN kind='DELIVERY' THEN total_amount ELSE 0 END), 0) AS delivery,
         COALESCE(SUM(CASE WHEN kind='CHARTER'  THEN total_amount ELSE 0 END), 0) AS charter
       FROM momo_order_items WHERE order_objid = $1`,
      [orderObjid]
    );
    const t = sumRes.rows[0];
    await client.query(
      `UPDATE momo_orders SET
         total_supply=$2, total_vat=$3, total_amount=$4,
         total_taxfree=$5, total_taxable=$6,
         total_delivery=$7, total_charter=$8,
         update_date=NOW(), update_id=$9
       WHERE objid = $1`,
      [orderObjid, t.supply, t.vat, t.total, t.taxfree, t.taxable, t.delivery, t.charter,
       r.user.objid || r.user.userId]
    );

    await client.query("COMMIT");
    return NextResponse.json({ success: true });
  } catch (err) {
    await client.query("ROLLBACK");
    console.error("[orders/items/add]", err);
    return NextResponse.json({ success: false, message: err instanceof Error ? err.message : "오류" }, { status: 500 });
  } finally {
    client.release();
  }
}
