// 전자세금계산서 발행 — 발주(orderObjid)로부터 또는 수동 입력으로
// 관리자 전용. 발행 후 momo_einvoices + momo_einvoice_items 에 이력 기록.
import { NextRequest, NextResponse } from "next/server";
import { pool } from "@/lib/db";
import { createObjectId } from "@/lib/utils";
import { requireMomoAdmin } from "@/lib/momo-guard";
import { getProvider, PROVIDER_NAME } from "@/lib/einvoice";
import type { InvoiceLine, InvoiceParty, InvoiceRequest } from "@/lib/einvoice";

interface IssueBody {
  orderObjid?: string;          // 있으면 자동 채움
  invoiceKind?: "TAX" | "TAXFREE";
  invoiceType?: "NORMAL" | "MODIFIED" | "CANCELED";
  issueDate?: string;           // YYYY-MM-DD
  buyer?: Partial<InvoiceParty>;
  lines?: InvoiceLine[];
  memo?: string;
  // 수정/취소 시 원본 승인번호
  originNtsInvoiceNo?: string;
}

export async function POST(req: NextRequest) {
  const g = await requireMomoAdmin();
  if (g instanceof NextResponse) return g;
  const userId = g.user.objid || g.user.userId;

  const body: IssueBody = await req.json().catch(() => ({}));
  const today = new Date().toISOString().slice(0, 10);

  const supplier: InvoiceParty = {
    bizNo: process.env.NTS_ESERO_SUPPLIER_BIZNO || "0000000000",
    name: process.env.MOMO_COMPANY_NAME || "모모유통",
    ceoName: process.env.MOMO_COMPANY_CEO || "한신숙",
    address: process.env.MOMO_COMPANY_ADDR || "",
    business: "도매",
    item: "식품 유통",
  };

  let buyer: InvoiceParty;
  let lines: InvoiceLine[];
  let totalSupply = 0, totalVat = 0, totalAmount = 0;
  let customerObjid: string | null = null;
  let orderObjid: string | null = body.orderObjid ?? null;
  const invoiceKind = body.invoiceKind ?? "TAX";

  if (orderObjid) {
    // 중복 발행 방지: 같은 발주에 대해 이미 유효한 발행(FAIL/CANCELED 아닌 것)이 있으면 차단
    const existing = await pool.query(
      `SELECT objid, status, nts_invoice_no FROM momo_einvoices
       WHERE order_objid = $1 AND COALESCE(is_del,'N') != 'Y'
         AND status NOT IN ('FAIL','CANCELED')
       LIMIT 1`,
      [orderObjid]
    );
    if (existing.rowCount && existing.rowCount > 0) {
      const e = existing.rows[0];
      return NextResponse.json({
        success: false,
        message: `이미 발행된 발주입니다. (상태: ${e.status}${e.nts_invoice_no ? `, 승인번호: ${e.nts_invoice_no}` : ""})`,
        alreadyIssued: true,
      }, { status: 400 });
    }

    // 발주로부터 자동 채움
    const r = await pool.query(
      `SELECT
         O.customer_objid, O.order_date, O.total_supply, O.total_vat, O.total_amount,
         U.user_name, U.email, U.cell_phone, U.biz_no, U.ceo_name, U.address
       FROM momo_orders O
       LEFT JOIN user_info U ON U.user_id = O.customer_objid
       WHERE O.objid = $1 AND COALESCE(O.is_del,'N') != 'Y'`,
      [orderObjid]
    );
    if (r.rowCount === 0) {
      return NextResponse.json({ success: false, message: "발주를 찾을 수 없습니다." }, { status: 404 });
    }
    const o = r.rows[0];
    customerObjid = o.customer_objid as string;
    buyer = {
      bizNo: o.biz_no || "0000000000",
      name: o.user_name || customerObjid,
      ceoName: o.ceo_name || undefined,
      address: o.address || undefined,
      email: o.email || undefined,
      phone: o.cell_phone || undefined,
    };
    totalSupply = Number(o.total_supply);
    totalVat    = Number(o.total_vat);
    totalAmount = Number(o.total_amount);

    const itemsRes = await pool.query(
      `SELECT seq, item_name_snap, unit_price, qty, supply_amount, vat_amount,
              COALESCE(kind,'ITEM') AS kind, extra_label
       FROM momo_order_items WHERE order_objid = $1 ORDER BY seq`,
      [orderObjid]
    );
    lines = itemsRes.rows.map((row, idx) => ({
      seq: idx + 1,
      itemDate: o.order_date as string,
      itemName: row.kind === "ITEM" ? row.item_name_snap : (row.extra_label || row.item_name_snap),
      qty: Number(row.qty),
      unitPrice: Number(row.unit_price),
      supplyAmount: Number(row.supply_amount),
      vatAmount: Number(row.vat_amount),
    }));
  } else {
    // 수동 발행 — body.buyer + body.lines 필수
    if (!body.buyer?.bizNo || !body.buyer?.name) {
      return NextResponse.json({ success: false, message: "공급받는자 정보가 부족합니다." }, { status: 400 });
    }
    if (!Array.isArray(body.lines) || body.lines.length === 0) {
      return NextResponse.json({ success: false, message: "라인을 1개 이상 입력하세요." }, { status: 400 });
    }
    buyer = body.buyer as InvoiceParty;
    lines = body.lines.map((l, i) => ({ ...l, seq: l.seq ?? i + 1 }));
    for (const ln of lines) {
      totalSupply += Number(ln.supplyAmount) || 0;
      totalVat    += Number(ln.vatAmount) || 0;
    }
    totalAmount = totalSupply + totalVat;
  }

  const invoiceReq: InvoiceRequest = {
    kind: invoiceKind,
    type: body.invoiceType ?? "NORMAL",
    issueDate: body.issueDate ?? today,
    supplier,
    buyer,
    lines,
    totalSupply,
    totalVat: invoiceKind === "TAXFREE" ? 0 : totalVat,
    totalAmount: invoiceKind === "TAXFREE" ? totalSupply : totalAmount,
    memo: body.memo,
    originNtsInvoiceNo: body.originNtsInvoiceNo,
  };

  const provider = getProvider();
  const result = await provider.issue(invoiceReq);

  // 이력 저장 (성공/실패 모두)
  const objid = createObjectId();
  const client = await pool.connect();
  try {
    await client.query("BEGIN");
    await client.query(
      `INSERT INTO momo_einvoices (
         objid, order_objid, customer_objid, invoice_kind, invoice_type, issue_method,
         supplier_biz_no, supplier_name, supplier_ceo, supplier_address,
         supplier_business, supplier_item,
         buyer_biz_no, buyer_name, buyer_ceo, buyer_address, buyer_email, buyer_phone,
         total_supply, total_vat, total_amount,
         nts_invoice_no, nts_response_code, nts_response_msg, nts_sent_at, nts_acknowledged,
         status, issue_date, request_xml, response_xml,
         memo, regdate, regid
       ) VALUES (
         $1,$2,$3,$4,$5,$6,
         $7,$8,$9,$10,
         $11,$12,
         $13,$14,$15,$16,$17,$18,
         $19,$20,$21,
         $22,$23,$24, NOW(), $25,
         $26,$27,$28,$29,
         $30, NOW(), $31
       )`,
      [objid, orderObjid, customerObjid || buyer.bizNo,
       invoiceReq.kind, invoiceReq.type, provider.method,
       supplier.bizNo, supplier.name, supplier.ceoName ?? null, supplier.address ?? null,
       supplier.business ?? null, supplier.item ?? null,
       buyer.bizNo, buyer.name, buyer.ceoName ?? null, buyer.address ?? null,
       buyer.email ?? null, buyer.phone ?? null,
       invoiceReq.totalSupply, invoiceReq.totalVat, invoiceReq.totalAmount,
       result.ntsInvoiceNo ?? null, result.responseCode ?? null, result.responseMessage ?? null,
       result.success ? "Y" : "N",
       result.status, invoiceReq.issueDate,
       result.rawRequest ?? null, result.rawResponse ?? null,
       body.memo ?? null, userId]
    );
    for (const ln of invoiceReq.lines) {
      await client.query(
        `INSERT INTO momo_einvoice_items (
           objid, einvoice_objid, seq, item_date, item_name, spec, qty, unit_price,
           supply_amount, vat_amount, remark
         ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)`,
        [createObjectId(), objid, ln.seq, ln.itemDate ?? null,
         ln.itemName, ln.spec ?? null, ln.qty ?? null, ln.unitPrice ?? null,
         ln.supplyAmount, ln.vatAmount, ln.remark ?? null]
      );
    }
    await client.query("COMMIT");
  } catch (err) {
    await client.query("ROLLBACK");
    console.error("[einvoice/issue] DB 기록 실패:", err);
    return NextResponse.json({
      success: false,
      message: "발행 결과 저장 중 오류가 발생했습니다.",
      providerResult: result,
    }, { status: 500 });
  } finally {
    client.release();
  }

  return NextResponse.json({
    success: result.success,
    objid,
    provider: PROVIDER_NAME,
    status: result.status,
    ntsInvoiceNo: result.ntsInvoiceNo,
    responseCode: result.responseCode,
    message: result.responseMessage,
  });
}
