import NextAuth, { NextAuthConfig, Session, User } from "next-auth";
import axios from "axios";
import CredentialsProvider from "next-auth/providers/credentials";
import { JWT } from "next-auth/jwt";
import { SignJWT } from "jose";

const SMSOTPProvider = CredentialsProvider({
  id: "sms-otp",
  name: "SMS OTP",
  credentials: {
    phoneNumber: { label: "Phone Number", type: "tel" },
    otp: { label: "OTP", type: "text" },
  },
  authorize: async (credentials) => {
    const { phoneNumber, otp } = credentials as Record<string, string>;

    try {
      if (!otp) {
        const tokenGenerated = await generateToken(phoneNumber);
        if (!tokenGenerated) {
          throw new Error("Failed to generate OTP");
        }
        return null; // No user returned yet
      }

      const isValid = await verifyOTP(phoneNumber, otp);
      if (isValid) {
        const response = await axios.post(
          "http://192.168.31.187:8000/api/login/verify_otp",
          { mobile_no: phoneNumber, otp: otp },
          {
            headers: {
              "Content-Type": "application/json",
              accept: "application/json",
            },
          },
        );
        const authToken = response.data.auth_token;
        return { id: phoneNumber, phoneNumber, authToken } as User;
      }
      return null;
    } catch (error) {
      console.error("Error in authorize function:", error);
      throw new Error("Authorization error");
    }
  },
});

export const authOptions: NextAuthConfig = {
  providers: [SMSOTPProvider],
  debug: true,
  jwt: {
    async encode({ token }: { token: JWT }) {
      const secret = new TextEncoder().encode(
        process.env.NEXT_PUBLIC_JWT_SECRET!,
      );
      const jwt = await new SignJWT(token as Record<string, unknown>)
        .setProtectedHeader({ alg: "HS256" })
        .sign(secret);
      return jwt;
    },
  },
  callbacks: {
    async jwt({ token, user }: { token: JWT; user?: User }) {
      if (user) {
        token.authToken = (user as any).authToken;
      }
      return token;
    },
    async session({ session, token }: { session: Session; token: JWT }) {
      session.user.authToken = token.authToken;
      return session;
    },
  },
};

export default async (req: any, res: any) => NextAuth(req, res, authOptions);

async function generateToken(phoneNumber: string): Promise<boolean> {
  try {
    const response = await axios.post(
      "http://192.168.31.187:8000/api/login/generate_token",
      { mobile_no: phoneNumber },
      {
        headers: {
          "Content-Type": "application/json",
          accept: "application/json",
        },
      },
    );
    return response.status === 200;
  } catch (error) {
    console.error("Error generating OTP:", error);
    return false;
  }
}

async function verifyOTP(phoneNumber: string, otp: string): Promise<boolean> {
  try {
    const response = await axios.post(
      "http://192.168.31.187:8000/api/login/verify_otp",
      { mobile_no: phoneNumber, otp: otp },
      {
        headers: {
          "Content-Type": "application/json",
          accept: "application/json",
        },
      },
    );
    return response.status === 200;
  } catch (error) {
    console.error("Error verifying OTP:", error);
    return false;
  }
}
TS2322: Type
({token}: {   token: JWT; }) => Promise<string>
is not assignable to type
(params: JWTEncodeParams<JWT>) => Awaitable<string>
Types of parameters __0 and params are incompatible.
Type JWTEncodeParams<JWT> is not assignable to type { token: JWT; }
Types of property token are incompatible.
Type JWT | undefined is not assignable to type JWT
Type undefined is not assignable to type JWT
TS2339: Property authToken does not exist on type User
TS2554: Expected 1 arguments, but got 3 =>  NextAuth(req, res, authOptions);