// 출고요청서 작성 (대리점) — status=REQUESTED 로 저장
// v0.4: 택배비/용차비 라인 + 택배 전용 품목 자동 검증 지원
import { NextRequest, NextResponse } from "next/server";
import { pool, queryOne } from "@/lib/db";
import { createObjectId } from "@/lib/utils";
import { requireMomoUser } from "@/lib/momo-guard";
import { calcLine, sumTotals } from "@/lib/momo-pricing";
import { getSupplierByBranch } from "@/lib/momo-branches";

interface InputItemLine {
  itemObjid: string;
  qty: number;
}
interface InputExtraLine {
  kind: "DELIVERY" | "CHARTER";
  // v0.4 단가/수량 분리. 기존 amount 도 받아서 호환 (qty=1, unitPrice=amount).
  unitPrice?: number;
  qty?: number;
  amount?: number;
  label?: string;
}

export async function POST(req: NextRequest) {
  const r = await requireMomoUser();
  if (r instanceof NextResponse) return r;
  const customerObjid = r.user.objid || r.user.userId;
  if (!customerObjid) {
    return NextResponse.json({ success: false, message: "사용자 식별자를 확인할 수 없습니다." }, { status: 400 });
  }

  let lines: InputItemLine[];
  let extras: InputExtraLine[];
  let memo: string | undefined;
  try {
    const body = await req.json() as { lines: InputItemLine[]; extras?: InputExtraLine[]; memo?: string };
    lines = body.lines;
    extras = Array.isArray(body.extras) ? body.extras : [];
    memo = body.memo;
  } catch {
    return NextResponse.json({ success: false, message: "요청 본문을 해석할 수 없습니다." }, { status: 400 });
  }
  if (!Array.isArray(lines) || lines.length === 0) {
    return NextResponse.json({ success: false, message: "발주 품목을 추가하세요." }, { status: 400 });
  }
  for (const ln of lines) {
    if (!ln?.itemObjid || !Number.isFinite(Number(ln.qty)) || Number(ln.qty) <= 0) {
      return NextResponse.json({ success: false, message: "품목/수량 형식이 올바르지 않습니다." }, { status: 400 });
    }
  }
  // 택배/용차 라인 정규화: unitPrice + qty 우선, amount 는 폴백
  const normExtras = extras.map((ex) => {
    const unitPrice = Number(ex.unitPrice ?? ex.amount ?? 0);
    const qty       = Number(ex.qty ?? 1);
    return { kind: ex.kind, unitPrice, qty, label: ex.label };
  });
  for (const ex of normExtras) {
    if (ex.kind !== "DELIVERY" && ex.kind !== "CHARTER") {
      return NextResponse.json({ success: false, message: "택배/용차 라인 종류가 올바르지 않습니다." }, { status: 400 });
    }
    if (!Number.isFinite(ex.unitPrice) || ex.unitPrice < 0
     || !Number.isFinite(ex.qty) || ex.qty <= 0) {
      return NextResponse.json({ success: false, message: "택배/용차 단가/수량 형식이 올바르지 않습니다." }, { status: 400 });
    }
  }

  try {
    const customerRow = await pool.query(
      `SELECT COALESCE(unlimited_qty, 'N') AS unlimited_qty,
              COALESCE(view_hidden, 'N')   AS view_hidden,
              COALESCE(statement_branch, 'HQ') AS statement_branch
         FROM user_info WHERE user_id = $1`,
      [customerObjid]
    );
    const unlimitedQty   = customerRow.rows[0]?.unlimited_qty === "Y";
    const viewHidden     = customerRow.rows[0]?.view_hidden === "Y";
    const customerBranch = customerRow.rows[0]?.statement_branch ?? "HQ";
    // 출고요청 시점의 공급자(거래명세표) 정보를 snapshot — 이후 기준 명세표/사용자
    // 설정을 바꿔도 이미 찍힌 명세표는 그대로 유지됨.
    const supplierSnap = await getSupplierByBranch(customerBranch);

    const itemIds = lines.map((l) => l.itemObjid);
    const placeholders = itemIds.map((_, i) => `$${i + 1}`).join(",");
    const items = await pool.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(items.rows.map((row) => [row.objid as string, row]));

    const missing = lines.find((ln) => !itemMap.has(ln.itemObjid));
    if (missing) {
      return NextResponse.json({ success: false, message: `존재하지 않는 품목입니다: ${missing.itemObjid}` }, { status: 400 });
    }

    // 수량/숨김/택배 검증
    let needsDelivery = false;
    for (const ln of lines) {
      const it = itemMap.get(ln.itemObjid)!;
      const stock = Number(it.stock_qty ?? 0);
      if (Number(ln.qty) > stock) {
        return NextResponse.json({
          success: false,
          message: `${it.item_name} — 재고(${stock})를 초과할 수 없습니다.`,
        }, { status: 400 });
      }
      if (!unlimitedQty) {
        const maxQ = it.max_order_qty == null ? 0 : Number(it.max_order_qty);
        if (maxQ > 0 && Number(ln.qty) > maxQ) {
          return NextResponse.json({
            success: false,
            message: `${it.item_name} — 1회 발주 제한수량(${maxQ})을 초과할 수 없습니다.`,
          }, { status: 400 });
        }
      }
      // 숨김 품목은 view_hidden 권한자만 발주 가능
      if (it.is_hidden === "Y" && !viewHidden) {
        return NextResponse.json({
          success: false,
          message: `${it.item_name} 은 발주 불가 품목입니다.`,
        }, { status: 400 });
      }
      if (it.requires_delivery === "Y") needsDelivery = true;
    }

    // 택배 전용 품목이 있는데 택배 라인이 없으면 차단
    const hasDeliveryLine = normExtras.some((e) => e.kind === "DELIVERY");
    if (needsDelivery && !hasDeliveryLine) {
      return NextResponse.json({
        success: false,
        message: "택배 전용 품목이 포함되어 택배 라인이 필요합니다. 택배 추가 후 다시 시도하세요.",
      }, { status: 400 });
    }

    const orderObjid = createObjectId();
    const orderNo = await genOrderNo();

    // 품목 라인
    const enriched = lines.map((ln, idx) => {
      const it = itemMap.get(ln.itemObjid)!;
      const isFree = it.is_tax_free === "Y";
      const calc = calcLine({ unitPrice: Number(it.unit_price), qty: ln.qty, isTaxFree: isFree });
      return {
        seq: idx + 1,
        itemObjid: ln.itemObjid,
        itemName: it.item_name as string,
        unitPrice: Number(it.unit_price),
        qty: ln.qty,
        isTaxFree: isFree,
        ...calc,
      };
    });

    // 택배/용차 라인 — 단가×수량 = VAT포함 합계, 일반 과세 처리
    let totalDelivery = 0;
    let totalCharter = 0;
    const extraEnriched = normExtras.map((ex, idx) => {
      const unitPrice = Math.round(ex.unitPrice);
      const qty = ex.qty;
      const calc = calcLine({ unitPrice, qty, isTaxFree: false });
      if (ex.kind === "DELIVERY") totalDelivery += calc.totalAmount;
      if (ex.kind === "CHARTER")  totalCharter  += calc.totalAmount;
      return {
        seq: enriched.length + idx + 1,
        kind: ex.kind,
        label: ex.label?.trim() || (ex.kind === "DELIVERY" ? "택배비" : "용차비"),
        unitPrice,
        qty,
        isTaxFree: false,
        ...calc,
      };
    });

    const totals = sumTotals([
      ...enriched,
      ...extraEnriched,
    ]);

    const client = await pool.connect();
    try {
      await client.query("BEGIN");
      await client.query(
        `INSERT INTO momo_orders (
           objid, order_no, customer_objid, order_date, status,
           total_supply, total_vat, total_amount, total_taxfree, total_taxable,
           total_delivery, total_charter,
           memo, regdate, regid,
           supplier_branch, supplier_name, supplier_ceo, supplier_bank_account,
           supplier_phone, supplier_email, supplier_biz_no, supplier_address
         ) VALUES ($1,$2,$3,CURRENT_DATE,'REQUESTED',$4,$5,$6,$7,$8,$9,$10,$11,NOW(),$12,
                   $13,$14,$15,$16,$17,$18,$19,$20)`,
        [orderObjid, orderNo, customerObjid,
         totals.supply, totals.vat, totals.total, totals.taxFree, totals.taxable,
         totalDelivery, totalCharter,
         memo ?? null,
         customerObjid,
         supplierSnap.CODE, supplierSnap.NAME, supplierSnap.CEO, supplierSnap.BANK_ACCOUNT,
         supplierSnap.PHONE, supplierSnap.EMAIL, supplierSnap.BIZ_NO, supplierSnap.ADDRESS]
      );
      for (const ln of enriched) {
        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, ln.itemName, ln.unitPrice, ln.qty,
           ln.isTaxFree ? "Y" : "N", ln.supplyAmount, ln.vatAmount, ln.totalAmount, ln.seq]
        );
      }
      for (const ex of extraEnriched) {
        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, extra_label
           ) VALUES ($1,$2,NULL,$3,$4,$5,'N',$6,$7,$8,$9,$10,$11)`,
          [createObjectId(), orderObjid, ex.label, ex.unitPrice, ex.qty,
           ex.supplyAmount, ex.vatAmount, ex.totalAmount, ex.seq, ex.kind, ex.label]
        );
      }
      await client.query("COMMIT");
      return NextResponse.json({ success: true, objId: orderObjid, orderNo });
    } catch (err) {
      await client.query("ROLLBACK");
      throw err;
    } finally {
      client.release();
    }
  } catch (err) {
    console.error("[order/save]", err);
    const msg = err instanceof Error ? err.message : "발주 저장 중 오류가 발생했습니다.";
    return NextResponse.json({ success: false, message: msg }, { status: 500 });
  }
}

async function genOrderNo(): Promise<string> {
  const today = new Date();
  const ymd = `${today.getFullYear()}${String(today.getMonth() + 1).padStart(2, "0")}${String(today.getDate()).padStart(2, "0")}`;
  const prefix = `ORD-${ymd}-`;
  const row = await queryOne<{ MAX_NO: string }>(
    `SELECT COALESCE(MAX(order_no), '') AS "MAX_NO" FROM momo_orders WHERE order_no LIKE $1 || '%'`,
    [prefix]
  );
  const last = row?.MAX_NO ?? "";
  const lastNum = last ? Number(last.replace(prefix, "")) || 0 : 0;
  return prefix + String(lastNum + 1).padStart(4, "0");
}
