import { NextResponse } from 'next/server';

import jwt from 'jsonwebtoken';
import { z } from 'zod';

import { enhanceRouteHandler } from '@kit/next/routes';
import { getLogger } from '@kit/shared/logger';

interface MontonioOrderToken {
  uuid: string;
  accessKey: string;
  merchantReference: string;
  merchantReferenceDisplay: string;
  paymentStatus:
    | 'PAID'
    | 'FAILED'
    | 'CANCELLED'
    | 'PENDING'
    | 'EXPIRED'
    | 'REFUNDED';
  paymentMethod: string;
  grandTotal: number;
  currency: string;
  senderIban?: string;
  senderName?: string;
  paymentProviderName?: string;
  paymentLinkUuid: string;
  iat: number;
  exp: number;
}

const BodySchema = z.object({
  token: z.string(),
});

export const POST = enhanceRouteHandler(
  async ({ request }) => {
    const logger = await getLogger();
    const body = await request.json();
    const namespace = 'montonio.verify-token';

    try {
      const { token } = BodySchema.parse(body);

      const secretKey = process.env.MONTONIO_SECRET_KEY as string;

      if (!secretKey) {
        logger.error(
          {
            name: namespace,
          },
          `Missing MONTONIO_SECRET_KEY`,
        );

        throw new Error('Server misconfiguration.');
      }

      const decoded = jwt.verify(token, secretKey, {
        algorithms: ['HS256'],
      }) as MontonioOrderToken;

      logger.info(
        {
          name: namespace,
          status: decoded.paymentStatus,
          orderId: decoded.uuid,
        },
        `Successfully verified Montonio token.`,
      );

      return NextResponse.json({
        status: decoded.paymentStatus,
      });
    } catch (error) {
      logger.error(
        {
          name: namespace,
          error,
        },
        `Failed to verify Montonio token`,
      );

      const message = error instanceof Error ? error.message : 'Invalid token';

      return NextResponse.json(
        {
          error: message,
        },
        {
          status: 400,
        },
      );
    }
  },
  {
    auth: false,
  },
);
