// 국세청 e-세로 직접 연동 어댑터 (어댑터 C)
//
// 동작 모드:
//   - NTS_ESERO_MODE=test  → 테스트 환경 (https://testesero.go.kr)
//   - NTS_ESERO_MODE=prod  → 운영 환경 (https://esero.go.kr)
//   - NTS_ESERO_MODE=stub  → 통신 안 함, mock 응답 (개발/CI)
//
// 필요 환경변수 (운영 모드):
//   - NTS_ESERO_USER_ID, NTS_ESERO_USER_PW           : 국세청 ERP 연계 신청 후 받는 ID/PW
//   - NTS_ESERO_CERT_PATH    : 사업자용 공동인증서 .pfx 파일 경로 (컨테이너 내부 마운트)
//   - NTS_ESERO_CERT_PW      : 인증서 비밀번호
//   - NTS_ESERO_SUPPLIER_BIZNO : 공급자(모모유통) 사업자번호
//
// 주의:
//   - 첫 운영 발행 전 반드시 테스트 환경에서 ≥ 100건 검증 필요
//   - XMLDSig (XML 디지털 서명) — 한국 국세청 변형 표준 사용
//   - 응답 파싱 후 momo_einvoices.nts_invoice_no, status, response_xml 갱신
//
// 현재 상태: 골격 (실제 SOAP 통신 + XMLDSig 구현은 인증서 + 스펙 받은 후 추가)
import type { InvoiceProvider, InvoiceRequest, InvoiceResponse } from "../types";

type Mode = "stub" | "test" | "prod";

const MODE: Mode = (process.env.NTS_ESERO_MODE as Mode) || "stub";
const ENDPOINT = MODE === "prod"
  ? "https://esero.go.kr/svc/IssueService"
  : "https://testesero.go.kr/svc/IssueService";

function ymd(d: string): string {
  return d.replace(/-/g, "");
}

/** 국세청 24자리 승인번호 형식: YYYYMMDD-XXXXXXXX-XXXXXXXX (실제 발행 후 받음) */
function makeStubInvoiceNo(): string {
  const now = new Date();
  const date = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, "0")}${String(now.getDate()).padStart(2, "0")}`;
  const rand = () => Math.random().toString(36).slice(2, 10).toUpperCase();
  return `${date}-${rand()}-${rand()}`;
}

/** XMLDSig + SOAP 페이로드 빌더 (TODO: 국세청 가이드 받은 후 구현) */
function buildSoapEnvelope(req: InvoiceRequest): string {
  // 실제 구현 시:
  //  1. 국세청 표준 TaxInvoice XML 생성 (TaxInvoiceType v3.0+)
  //  2. <ds:Signature> 블록 추가 (XMLDSig, RSA-SHA256, exclusive c14n)
  //  3. SOAP envelope 으로 감싸기
  // 라이브러리 후보: xml-crypto + node-forge
  return `<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <TaxInvoice writeDate="${ymd(req.issueDate)}">
      <Supplier bizNo="${req.supplier.bizNo}" name="${escapeXml(req.supplier.name)}" />
      <Buyer    bizNo="${req.buyer.bizNo}"    name="${escapeXml(req.buyer.name)}" />
      <Total supply="${req.totalSupply}" vat="${req.totalVat}" amount="${req.totalAmount}" />
      <!-- 라인은 실제 구현 시 추가 -->
    </TaxInvoice>
  </soap:Body>
</soap:Envelope>`;
}

function escapeXml(s: string): string {
  return s.replace(/[<>&'"]/g, (c) =>
    ({ "<": "&lt;", ">": "&gt;", "&": "&amp;", "'": "&apos;", '"': "&quot;" }[c]!));
}

export const ntsEseroProvider: InvoiceProvider = {
  method: "NTS",
  async issue(req: InvoiceRequest): Promise<InvoiceResponse> {
    const requestXml = buildSoapEnvelope(req);

    if (MODE === "stub") {
      return {
        success: true,
        status: "ACK",
        ntsInvoiceNo: makeStubInvoiceNo(),
        responseCode: "STUB-OK",
        responseMessage: `[STUB] 국세청 통신 비활성. NTS_ESERO_MODE=test|prod 로 변경 후 인증서 설정 필요.`,
        rawRequest: requestXml,
      };
    }

    // ----- 실제 통신 (인증서 받은 후 활성화) -----
    // TODO:
    //  1. 인증서 로드 (PKCS#12)
    //  2. requestXml 의 SignedInfo 영역에 XMLDSig 서명
    //  3. fetch(ENDPOINT, { method:"POST", headers:{ "SOAPAction": "issue", ... }, body: signed })
    //  4. 응답 XML 파싱 → 승인번호/응답코드 추출
    //  5. ACK / FAIL 반환

    return {
      success: false,
      status: "FAIL",
      responseCode: "NOT_IMPL",
      responseMessage:
        "국세청 e-세로 실통신 미구현 — 사업자 공동인증서 + ERP 연계 신청 승인 후 활성화 예정.",
      rawRequest: requestXml,
    };
  },

  async status(ntsInvoiceNo: string): Promise<InvoiceResponse> {
    if (MODE === "stub") {
      return { success: true, status: "ACK", ntsInvoiceNo };
    }
    return {
      success: false,
      status: "FAIL",
      responseMessage: "상태 조회 미구현",
    };
  },

  async cancel(ntsInvoiceNo: string, reason?: string): Promise<InvoiceResponse> {
    if (MODE === "stub") {
      return {
        success: true,
        status: "CANCELED",
        ntsInvoiceNo,
        responseMessage: `[STUB] 취소 처리 — 사유: ${reason ?? "-"}`,
      };
    }
    return {
      success: false,
      status: "FAIL",
      responseMessage: "취소 미구현",
    };
  },
};

export const NTS_ESERO_INFO = {
  mode: MODE,
  endpoint: ENDPOINT,
  isStub: MODE === "stub",
};
