import { supabase } from "@/lib/supabase"

export interface UploadConfig {
  bucket: string
  path: string
  maxSize: number // in bytes
  allowedTypes: string[]
}

export const UPLOAD_CONFIGS: Record<string, UploadConfig> = {
  video: {
    bucket: "workout-videos",
    path: "",
    maxSize: 500 * 1024 * 1024, // 500 MB
    allowedTypes: ["video/mp4", "video/webm", "video/quicktime"],
  },
  thumbnail: {
    bucket: "workout-thumbnails",
    path: "",
    maxSize: 10 * 1024 * 1024, // 10 MB
    allowedTypes: ["image/jpeg", "image/png", "image/webp"],
  },
  avatar: {
    bucket: "trainer-avatars",
    path: "",
    maxSize: 5 * 1024 * 1024, // 5 MB
    allowedTypes: ["image/jpeg", "image/png", "image/webp"],
  },
}

export interface UploadResult {
  url: string
  path: string
}

export interface UploadError {
  message: string
  code: "SIZE_EXCEEDED" | "INVALID_TYPE" | "UPLOAD_FAILED"
}

export function validateFile(
  file: File,
  config: UploadConfig
): { valid: true } | { valid: false; error: UploadError } {
  // Check file size
  if (file.size > config.maxSize) {
    const maxSizeMB = config.maxSize / (1024 * 1024)
    return {
      valid: false,
      error: {
        message: `File too large. Maximum size is ${maxSizeMB} MB.`,
        code: "SIZE_EXCEEDED",
      },
    }
  }

  // Check MIME type
  if (!config.allowedTypes.includes(file.type)) {
    return {
      valid: false,
      error: {
        message: `Invalid file type. Allowed types: ${config.allowedTypes.join(", ")}.`,
        code: "INVALID_TYPE",
      },
    }
  }

  return { valid: true }
}

export async function uploadFile(
  file: File,
  config: UploadConfig,
  workoutId: string,
  onProgress?: (progress: number) => void
): Promise<UploadResult> {
  // Validate file first
  const validation = validateFile(file, config)
  if (!validation.valid) {
    throw validation.error
  }

  // Generate file path: {workoutId}/{filename}
  const fileExt = file.name.split(".").pop()
  const fileName = `${Date.now()}.${fileExt}`
  const filePath = `${workoutId}/${fileName}`

  // Upload to Supabase Storage
  const { data, error } = await supabase.storage
    .from(config.bucket)
    .upload(filePath, file, {
      cacheControl: "3600",
      upsert: false,
    })

  if (error) {
    throw {
      message: error.message,
      code: "UPLOAD_FAILED",
    } as UploadError
  }

  // Get public URL
  const { data: { publicUrl } } = supabase.storage
    .from(config.bucket)
    .getPublicUrl(filePath)

  return {
    url: publicUrl,
    path: filePath,
  }
}

export async function deleteFile(
  bucket: string,
  path: string
): Promise<void> {
  const { error } = await supabase.storage
    .from(bucket)
    .remove([path])

  if (error) {
    throw new Error(`Failed to delete file: ${error.message}`)
  }
}

export function formatFileSize(bytes: number): string {
  if (bytes === 0) return "0 Bytes"
  const k = 1024
  const sizes = ["Bytes", "KB", "MB", "GB"]
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]
}

export interface MovedFile {
  oldPath: string
  newPath: string
  newUrl: string
}

export interface MoveFilesResult {
  thumbnail?: MovedFile
  video?: MovedFile
  errors: string[]
}

/**
 * Move files from temp folder to workout-specific folder after workout creation
 * This updates the URLs in the database
 */
export async function moveFilesFromTempToWorkout(
  tempWorkoutId: string,
  realWorkoutId: string,
  thumbnailUrl?: string,
  videoUrl?: string
): Promise<MoveFilesResult> {
  const result: MoveFilesResult = { errors: [] }

  // Extract bucket and path from URL
  const extractPathFromUrl = (url: string): { bucket: string; path: string } | null => {
    try {
      const urlObj = new URL(url)
      const pathParts = urlObj.pathname.split('/')
      // URL format: /storage/v1/object/public/{bucket}/{path}
      const bucketIndex = pathParts.findIndex(part => part === 'public') + 1
      if (bucketIndex > 0 && bucketIndex < pathParts.length) {
        const bucket = pathParts[bucketIndex]
        const path = pathParts.slice(bucketIndex + 1).join('/')
        return { bucket, path }
      }
      return null
    } catch {
      return null
    }
  }

  // Move thumbnail if exists
  if (thumbnailUrl && thumbnailUrl.includes(`/temp/`)) {
    const extracted = extractPathFromUrl(thumbnailUrl)
    if (extracted) {
      const { bucket, path } = extracted
      const newPath = path.replace(`temp/`, `${realWorkoutId}/`)

      try {
        const { error } = await supabase.storage
          .from(bucket)
          .move(path, newPath)

        if (error) {
          result.errors.push(`Failed to move thumbnail: ${error.message}`)
        } else {
          const { data: { publicUrl } } = supabase.storage
            .from(bucket)
            .getPublicUrl(newPath)

          result.thumbnail = {
            oldPath: path,
            newPath,
            newUrl: publicUrl,
          }
        }
      } catch (err) {
        result.errors.push(`Failed to move thumbnail: ${err}`)
      }
    }
  }

  // Move video if exists
  if (videoUrl && videoUrl.includes(`/temp/`)) {
    const extracted = extractPathFromUrl(videoUrl)
    if (extracted) {
      const { bucket, path } = extracted
      const newPath = path.replace(`temp/`, `${realWorkoutId}/`)

      try {
        const { error } = await supabase.storage
          .from(bucket)
          .move(path, newPath)

        if (error) {
          result.errors.push(`Failed to move video: ${error.message}`)
        } else {
          const { data: { publicUrl } } = supabase.storage
            .from(bucket)
            .getPublicUrl(newPath)

          result.video = {
            oldPath: path,
            newPath,
            newUrl: publicUrl,
          }
        }
      } catch (err) {
        result.errors.push(`Failed to move video: ${err}`)
      }
    }
  }

  return result
}

/**
 * Clean up temp files that weren't associated with any workout
 * Can be called periodically (e.g., daily cron job)
 */
export async function cleanupTempFiles(): Promise<{ deleted: number; errors: string[] }> {
  const result = { deleted: 0, errors: [] as string[] }
  const buckets = ['workout-videos', 'workout-thumbnails']

  for (const bucket of buckets) {
    try {
      const { data, error } = await supabase.storage
        .from(bucket)
        .list('temp')

      if (error) {
        result.errors.push(`Failed to list temp files in ${bucket}: ${error.message}`)
        continue
      }

      if (data && data.length > 0) {
        const pathsToDelete = data.map(file => `temp/${file.name}`)
        const { error: deleteError } = await supabase.storage
          .from(bucket)
          .remove(pathsToDelete)

        if (deleteError) {
          result.errors.push(`Failed to delete temp files in ${bucket}: ${deleteError.message}`)
        } else {
          result.deleted += data.length
        }
      }
    } catch (err) {
      result.errors.push(`Error cleaning up ${bucket}: ${err}`)
    }
  }

  return result
}
