import { getSessionUser } from "@/lib/auth";
import { recordTossPaymentsCheckoutChargeByOwnerEmail } from "@/lib/toss-pay";
import {
  TOSS_CONFIRM_API_URL,
  encodeTossSecretKey,
  getExpectedTossBillingAmountByEmail,
  getTossPaymentsSecretKey,
} from "@/lib/toss-payments";

type TossConfirmRequest = {
  amount?: number;
  orderId?: string;
  paymentKey?: string;
  simulate?: boolean;
};

type TossConfirmError = {
  code?: string;
  message?: string;
};

type TossConfirmSuccess = {
  approvedAt?: string;
  easyPay?: {
    provider?: string;
  };
  method?: string;
  orderId?: string;
  orderName?: string;
  paymentKey?: string;
  status?: string;
  totalAmount?: number;
};

export async function POST(request: Request) {
  const user = await getSessionUser();

  if (!user) {
    return Response.json({ error: "unauthorized", message: "로그인이 필요합니다." }, { status: 401 });
  }

  let body: TossConfirmRequest | null = null;

  try {
    body = (await request.json()) as TossConfirmRequest;
  } catch {
    return Response.json({ error: "invalid-json", message: "잘못된 요청 형식입니다." }, { status: 400 });
  }

  const paymentKey = body?.paymentKey?.trim() ?? "";
  const orderId = body?.orderId?.trim() ?? "";
  const amount = Number(body?.amount ?? Number.NaN);
  const simulate = body?.simulate === true;

  if (!paymentKey || !orderId || !Number.isFinite(amount) || amount < 1) {
    return Response.json(
      { error: "invalid-params", message: "결제 승인에 필요한 정보가 올바르지 않습니다." },
      { status: 400 },
    );
  }

  const expected = await getExpectedTossBillingAmountByEmail(user.email);

  if (amount !== expected.chargeAmount) {
    return Response.json(
      {
        error: "amount-mismatch",
        message: "승인 금액이 현재 결제 예정 금액과 일치하지 않습니다.",
      },
      { status: 400 },
    );
  }

  const secretKey = getTossPaymentsSecretKey();

  if (!secretKey || simulate) {
    const payment = {
      amount,
      approvedAt: new Date().toISOString(),
      method: "토스페이",
      orderId,
      orderName:
        `성장플랜 ${expected.billableSeats}명`,
      paymentKey,
      provider: null,
      simulated: true,
      status: "DONE",
    } as const;

    await recordTossPaymentsCheckoutChargeByOwnerEmail({
      email: user.email,
      amount: payment.amount,
      approvedAt: payment.approvedAt,
      method: payment.method,
      orderId: payment.orderId,
      orderName: payment.orderName,
      paymentKey: payment.paymentKey,
      provider: payment.provider,
      simulated: payment.simulated,
    });

    return Response.json({
      ok: true,
      payment,
    });
  }

  const idempotencyKey = `${paymentKey}:${orderId}:${amount}`;
  const response = await fetch(TOSS_CONFIRM_API_URL, {
    method: "POST",
    headers: {
      Authorization: `Basic ${encodeTossSecretKey(secretKey)}`,
      "Content-Type": "application/json",
      "Idempotency-Key": idempotencyKey,
    },
    body: JSON.stringify({
      amount,
      orderId,
      paymentKey,
    }),
  });

  if (!response.ok) {
    const error = (await response.json().catch(() => null)) as TossConfirmError | null;
    return Response.json(
      {
        error: error?.code ?? "confirm-failed",
        message: error?.message ?? "결제 승인 확인에 실패했습니다.",
      },
      { status: response.status },
    );
  }

  const payment = (await response.json()) as TossConfirmSuccess;
  const normalizedPayment = {
    amount: payment.totalAmount ?? amount,
    approvedAt: payment.approvedAt ?? new Date().toISOString(),
    method: payment.method ?? "CARD",
    orderId: payment.orderId ?? orderId,
    orderName:
      payment.orderName ??
      `성장플랜 ${expected.billableSeats}명`,
    paymentKey: payment.paymentKey ?? paymentKey,
    provider: payment.easyPay?.provider ?? null,
    simulated: false,
    status: payment.status ?? "DONE",
  } as const;

  await recordTossPaymentsCheckoutChargeByOwnerEmail({
    email: user.email,
    amount: normalizedPayment.amount,
    approvedAt: normalizedPayment.approvedAt,
    method: normalizedPayment.method,
    orderId: normalizedPayment.orderId,
    orderName: normalizedPayment.orderName,
    paymentKey: normalizedPayment.paymentKey,
    provider: normalizedPayment.provider,
    simulated: normalizedPayment.simulated,
  });

  return Response.json({
    ok: true,
    payment: normalizedPayment,
  });
}
