import { TRPCError } from "@trpc/server"
import { z } from "zod"

import { env } from "@/env/server"
import { protectedProcedure } from "@/server/trpc"

import { getSasToken } from "../../getSasToken"
import { getOTPState } from "../getOTPState"
import {
  parseSASVerifyOtpError,
  type VerifyOtpGeneralError,
} from "./verifyOtpError"

const inputSchema = z.object({
  otp: z.string(),
})

const outputSchema = z.object({
  status: z.enum([
    "VERIFIED",
    "ABUSED",
    "EXPIRED",
    "PENDING",
    "RETRY",
    "SENT",
    "NULL",
    "NOTSENT",
  ]),
  referenceId: z.string().uuid().optional(),
  databaseUUID: z.string().uuid().optional(),
})

export const verifyOtp = protectedProcedure
  .input(inputSchema)
  .output(outputSchema)
  .mutation(async function ({ input }) {
    const sasAuthToken = await getSasToken()

    if (!sasAuthToken) {
      throw createError("AUTH_TOKEN_NOT_FOUND")
    }

    const verifyResponse = await fetchVerifyOtp(input)
    console.log(
      "[SAS] verifyOTP",
      verifyResponse.status,
      verifyResponse.statusText
    )

    if (verifyResponse.status > 499) {
      console.error("[SAS] verifyOTP error", await verifyResponse.text())
      throw new TRPCError({
        code: "SERVICE_UNAVAILABLE",
        message: "Error from downstream SAS service",
      })
    }

    const data = await verifyResponse.json()
    console.log("[SAS] verifyOTP data", data)
    const result = outputSchema.safeParse(data)
    if (!result.success) {
      console.error("[SAS] verifyOTP error", result.error)
      throw createError(data)
    }

    console.log("[SAS] verifyOTP success")
    console.log("[SAS] verifyOTP responding", result.data)

    return result.data
  })

async function fetchVerifyOtp(input: z.infer<typeof inputSchema>) {
  const sasAuthToken = await getSasToken()
  const { referenceId, databaseUUID } = await getOTPState()

  return await fetch(
    `${env.SAS_API_ENDPOINT}/api/scandic-partnership/customer/verify-otp`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Ocp-Apim-Subscription-Key": env.SAS_OCP_APIM,
        Authorization: `Bearer ${sasAuthToken}`,
      },
      body: JSON.stringify({
        referenceId: referenceId,
        otpCode: input.otp,
        databaseUUID: databaseUUID,
      }),
    }
  )
}

function createError(
  errorBody:
    | {
        status: string
        error: string
        errorCode: number
        databaseUUID: string
      }
    | Error
    | VerifyOtpGeneralError
): TRPCError {
  const errorInfo = parseSASVerifyOtpError(errorBody)

  return new TRPCError({
    code: "BAD_REQUEST",
    cause: errorInfo,
  })
}
