import { router, protectedProcedure, publicProcedure } from '@/src/trpc/trpc-index'
import { SignJWT } from 'jose'
import { z } from 'zod'
import { ApiError } from '@/src/lib/api-error'
import { getEncodedJwtSecret } from '@/src/lib/env-exporter'
import { scaffoldAssetUrl } from '@/src/lib/s3-client'
import {
  getUserProfileById as getUserProfileByIdInDb,
  getUserProfileDetailById as getUserProfileDetailByIdInDb,
  upsertUserNotifCred as upsertUserNotifCredInDb,
  deleteUserUnloggedToken as deleteUserUnloggedTokenInDb,
  getUserUnloggedToken as getUserUnloggedTokenInDb,
  upsertUserUnloggedToken as upsertUserUnloggedTokenInDb,
} from '@/src/dbService'
import type {
  UserSelfDataResponse,
  UserSavePushTokenResponse,
} from '@packages/shared'

const generateToken = async (userId: number): Promise<string> => {
  return await new SignJWT({ userId })
    .setProtectedHeader({ alg: 'HS256' })
    .setExpirationTime('7d')
    .sign(getEncodedJwtSecret());
};

export const userRouter = router({
  getSelfData: protectedProcedure
    .query(async ({ ctx }): Promise<UserSelfDataResponse> => {
      const userId = ctx.user.userId;

      if (!userId) {
        throw new ApiError('User not authenticated', 401);
      }

      const user = await getUserProfileByIdInDb(userId)

      if (!user) {
        throw new ApiError('User not found', 404);
      }

      // Get user details for profile image
      const userDetail = await getUserProfileDetailByIdInDb(userId)

      // Generate signed URL for profile image if it exists
      const profileImageSignedUrl = userDetail?.profileImage
        ? scaffoldAssetUrl(userDetail.profileImage)
        : null;

      return {
        success: true,
        data: {
          user: {
            id: user.id,
            name: user.name,
            email: user.email,
            mobile: user.mobile,
            profileImage: profileImageSignedUrl,
            bio: userDetail?.bio || null,
            dateOfBirth: userDetail?.dateOfBirth
              ? new Date(userDetail.dateOfBirth as any).toISOString()
              : null,
            gender: userDetail?.gender || null,
            occupation: userDetail?.occupation || null,
          },
        },
      }
    }),

  savePushToken: publicProcedure
    .input(z.object({ token: z.string() }))
    .mutation(async ({ input, ctx }): Promise<UserSavePushTokenResponse> => {
      const { token } = input;
      const userId = ctx.user?.userId;

      if (userId) {
        // AUTHENTICATED USER
        // Check if token exists in notif_creds for this user
        await upsertUserNotifCredInDb(userId, token)
        await deleteUserUnloggedTokenInDb(token)

      } else {
        // UNAUTHENTICATED USER
        // Save/update in unlogged_user_tokens
        const existing = await getUserUnloggedTokenInDb(token)
        if (existing) {
          await upsertUserUnloggedTokenInDb(token)
        } else {
          await upsertUserUnloggedTokenInDb(token)
        }
      }

      return { success: true }
    }),
});
