import { z } from 'zod'
import { TRPCError } from '@trpc/server'
import { router, protectedProcedure } from '../trpc'
import {
  getStorageProviderWithType,
  createStorageProvider,
  generateAvatarKey,
  getContentType,
  isValidImageType,
  type StorageProviderType,
} from '@/lib/storage'

export const avatarRouter = router({
  /**
   * Get a pre-signed URL for uploading an avatar
   */
  getUploadUrl: protectedProcedure
    .input(
      z.object({
        fileName: z.string(),
        contentType: z.string(),
      })
    )
    .mutation(async ({ ctx, input }) => {
      // Validate content type
      if (!isValidImageType(input.contentType)) {
        throw new TRPCError({ code: 'BAD_REQUEST', message: 'Invalid image type. Allowed: JPEG, PNG, GIF, WebP' })
      }

      const userId = ctx.user.id
      const key = generateAvatarKey(userId, input.fileName)
      const contentType = getContentType(input.fileName)

      const { provider, providerType } = await getStorageProviderWithType()
      const uploadUrl = await provider.getUploadUrl(key, contentType)

      return {
        uploadUrl,
        key,
        providerType, // Return so client can pass it back on confirm
      }
    }),

  /**
   * Confirm avatar upload and update user profile
   */
  confirmUpload: protectedProcedure
    .input(
      z.object({
        key: z.string(),
        providerType: z.enum(['s3', 'local']),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const userId = ctx.user.id

      // Use the provider that was used for upload
      const provider = createStorageProvider(input.providerType)
      const exists = await provider.objectExists(input.key)
      if (!exists) {
        throw new TRPCError({ code: 'NOT_FOUND', message: 'Upload not found. Please try uploading again.' })
      }

      // Delete old avatar if exists (from its original provider)
      const currentUser = await ctx.prisma.user.findUnique({
        where: { id: userId },
        select: { profileImageKey: true, profileImageProvider: true },
      })

      if (currentUser?.profileImageKey) {
        try {
          const oldProvider = createStorageProvider(
            (currentUser.profileImageProvider as StorageProviderType) || 's3'
          )
          await oldProvider.deleteObject(currentUser.profileImageKey)
        } catch (error) {
          // Log but don't fail if old avatar deletion fails
          console.warn('Failed to delete old avatar:', error)
        }
      }

      // Update user with new avatar key and provider
      const user = await ctx.prisma.user.update({
        where: { id: userId },
        data: {
          profileImageKey: input.key,
          profileImageProvider: input.providerType,
        },
        select: {
          id: true,
          profileImageKey: true,
          profileImageProvider: true,
        },
      })

      // Audit log
      await ctx.prisma.auditLog.create({
        data: {
          userId: ctx.user.id,
          action: 'UPDATE',
          entityType: 'User',
          entityId: userId,
          detailsJson: {
            field: 'profileImageKey',
            newValue: input.key,
            provider: input.providerType,
          },
          ipAddress: ctx.ip,
          userAgent: ctx.userAgent,
        },
      })

      return user
    }),

  /**
   * Get the current user's avatar URL
   */
  getUrl: protectedProcedure.query(async ({ ctx }) => {
    const userId = ctx.user.id

    const user = await ctx.prisma.user.findUnique({
      where: { id: userId },
      select: { profileImageKey: true, profileImageProvider: true },
    })

    if (!user?.profileImageKey) {
      return null
    }

    // Use the provider that was used when the file was stored
    const providerType = (user.profileImageProvider as StorageProviderType) || 's3'
    const provider = createStorageProvider(providerType)
    const url = await provider.getDownloadUrl(user.profileImageKey)

    return url
  }),

  /**
   * Delete the current user's avatar
   */
  delete: protectedProcedure.mutation(async ({ ctx }) => {
    const userId = ctx.user.id

    const user = await ctx.prisma.user.findUnique({
      where: { id: userId },
      select: { profileImageKey: true, profileImageProvider: true },
    })

    if (!user?.profileImageKey) {
      return { success: true }
    }

    // Delete from the provider that was used when the file was stored
    const providerType = (user.profileImageProvider as StorageProviderType) || 's3'
    const provider = createStorageProvider(providerType)
    try {
      await provider.deleteObject(user.profileImageKey)
    } catch (error) {
      console.warn('Failed to delete avatar from storage:', error)
    }

    // Update user - clear both key and provider
    await ctx.prisma.user.update({
      where: { id: userId },
      data: {
        profileImageKey: null,
        profileImageProvider: null,
      },
    })

    // Audit log
    await ctx.prisma.auditLog.create({
      data: {
        userId: ctx.user.id,
        action: 'DELETE',
        entityType: 'User',
        entityId: userId,
        detailsJson: { field: 'profileImageKey' },
        ipAddress: ctx.ip,
        userAgent: ctx.userAgent,
      },
    })

    return { success: true }
  }),
})
