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

export const logoRouter = router({
  /**
   * Get a pre-signed URL for uploading a project logo
   */
  getUploadUrl: adminProcedure
    .input(
      z.object({
        projectId: z.string(),
        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' })
      }

      // Verify project exists
      const project = await ctx.prisma.project.findUnique({
        where: { id: input.projectId },
        select: { id: true },
      })

      if (!project) {
        throw new TRPCError({ code: 'NOT_FOUND', message: 'Project not found' })
      }

      const key = generateLogoKey(input.projectId, 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 logo upload and update project
   */
  confirmUpload: adminProcedure
    .input(
      z.object({
        projectId: z.string(),
        key: z.string(),
        providerType: z.enum(['s3', 'local']),
      })
    )
    .mutation(async ({ ctx, input }) => {
      // 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 logo if exists (from its original provider)
      const currentProject = await ctx.prisma.project.findUnique({
        where: { id: input.projectId },
        select: { logoKey: true, logoProvider: true },
      })

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

      // Update project with new logo key and provider
      const project = await ctx.prisma.project.update({
        where: { id: input.projectId },
        data: {
          logoKey: input.key,
          logoProvider: input.providerType,
        },
        select: {
          id: true,
          logoKey: true,
          logoProvider: true,
        },
      })

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

      return project
    }),

  /**
   * Get a project's logo URL
   */
  getUrl: adminProcedure
    .input(z.object({ projectId: z.string() }))
    .query(async ({ ctx, input }) => {
      const project = await ctx.prisma.project.findUnique({
        where: { id: input.projectId },
        select: { logoKey: true, logoProvider: true },
      })

      if (!project?.logoKey) {
        return null
      }

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

      return url
    }),

  /**
   * Delete a project's logo
   */
  delete: adminProcedure
    .input(z.object({ projectId: z.string() }))
    .mutation(async ({ ctx, input }) => {
      const project = await ctx.prisma.project.findUnique({
        where: { id: input.projectId },
        select: { logoKey: true, logoProvider: true },
      })

      if (!project?.logoKey) {
        return { success: true }
      }

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

      // Update project - clear both key and provider
      await ctx.prisma.project.update({
        where: { id: input.projectId },
        data: {
          logoKey: null,
          logoProvider: null,
        },
      })

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

      return { success: true }
    }),
})
