import axios from 'axios'
import { scaffoldProducts } from '@/src/trpc/apis/common-apis/common'
import { scaffoldEssentialConsts } from '@/src/trpc/apis/common-apis/common-trpc-index'
import { scaffoldStores } from '@/src/trpc/apis/user-apis/apis/stores'
import { scaffoldSlotsWithProducts } from '@/src/trpc/apis/user-apis/apis/slots'
import { scaffoldBanners } from '@/src/trpc/apis/user-apis/apis/banners'
import { scaffoldStoreWithProducts } from '@/src/trpc/apis/user-apis/apis/stores'
import { storeInfo } from '@/src/db/schema'
import { db } from '@/src/db/db_index'
import { imageUploadS3 } from '@/src/lib/s3-client'
import { apiCacheKey, cloudflareApiToken, cloudflareZoneId, assetsDomain } from '@/src/lib/env-exporter'
import { CACHE_FILENAMES } from '@packages/shared'
import { retryWithExponentialBackoff } from '@/src/lib/retry'

function constructCacheUrl(path: string): string {
  return `${assetsDomain}${apiCacheKey}/${path}`
}

export async function createProductsFile(): Promise<string> {
  // Get products data from the API method
  const productsData = await scaffoldProducts()

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(productsData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.products}`)

  // Purge cache with retry
  const url = constructCacheUrl(CACHE_FILENAMES.products)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createEssentialConstsFile(): Promise<string> {
  // Get essential consts data from the API method
  const essentialConstsData = await scaffoldEssentialConsts()

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(essentialConstsData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.essentialConsts}`)

  // Purge cache with retry
  const url = constructCacheUrl(CACHE_FILENAMES.essentialConsts)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createStoresFile(): Promise<string> {
  // Get stores data from the API method
  const storesData = await scaffoldStores()

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(storesData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.stores}`)

  // Purge cache with retry
  const url = constructCacheUrl(CACHE_FILENAMES.stores)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createSlotsFile(): Promise<string> {
  // Get slots data from the API method
  const slotsData = await scaffoldSlotsWithProducts()

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(slotsData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.slots}`)

  // Purge cache with retry
  const url = constructCacheUrl(CACHE_FILENAMES.slots)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createBannersFile(): Promise<string> {
  // Get banners data from the API method
  const bannersData = await scaffoldBanners()

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(bannersData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.banners}`)

  // Purge cache with retry
  const url = constructCacheUrl(CACHE_FILENAMES.banners)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createStoreFile(storeId: number): Promise<string> {
  // Get store data from the API method
  const storeData = await scaffoldStoreWithProducts(storeId)

  // Convert to JSON string with pretty formatting
  const jsonContent = JSON.stringify(storeData, null, 2)

  // Convert to Buffer for S3 upload
  const buffer = Buffer.from(jsonContent, 'utf-8')

  // Upload to S3 at the specified path using apiCacheKey
  const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/stores/${storeId}.json`)

  // Purge cache with retry
  const url = constructCacheUrl(`stores/${storeId}.json`)
  try {
    await retryWithExponentialBackoff(() => clearUrlCache([url]))
    console.log(`Cache purged for ${url}`)
  } catch (error) {
    console.error(`Failed to purge cache for ${url} after 3 retries:`, error)
  }

  return s3Key
}

export async function createAllStoresFiles(): Promise<string[]> {
  // Fetch all store IDs from database
  const stores = await db.select({ id: storeInfo.id }).from(storeInfo)

  // Create cache files for all stores and collect URLs
  const results: string[] = []
  const urls: string[] = []
  
  for (const store of stores) {
    const s3Key = await createStoreFile(store.id)
    results.push(s3Key)
    urls.push(constructCacheUrl(`stores/${store.id}.json`))
  }

  console.log(`Created ${results.length} store cache files`)
  
  // Purge all store caches in one batch with retry
  try {
    await retryWithExponentialBackoff(() => clearUrlCache(urls))
    console.log(`Cache purged for ${urls.length} store files`)
  } catch (error) {
    console.error(`Failed to purge cache for store files after 3 retries. URLs: ${urls.join(', ')}`, error)
  }
  
  return results
}

export interface CreateAllCacheFilesResult {
  products: string
  essentialConsts: string
  stores: string
  slots: string
  banners: string
  individualStores: string[]
}

export async function createAllCacheFiles(): Promise<CreateAllCacheFilesResult> {
  console.log('Starting creation of all cache files...')
  
  // Create all global cache files in parallel
  const [
    productsKey,
    essentialConstsKey,
    storesKey,
    slotsKey,
    bannersKey,
    individualStoreKeys,
  ] = await Promise.all([
    createProductsFileInternal(),
    createEssentialConstsFileInternal(),
    createStoresFileInternal(),
    createSlotsFileInternal(),
    createBannersFileInternal(),
    createAllStoresFilesInternal(),
  ])
  
  // Collect all URLs for batch cache purge
  const urls = [
    constructCacheUrl(CACHE_FILENAMES.products),
    constructCacheUrl(CACHE_FILENAMES.essentialConsts),
    constructCacheUrl(CACHE_FILENAMES.stores),
    constructCacheUrl(CACHE_FILENAMES.slots),
    constructCacheUrl(CACHE_FILENAMES.banners),
    ...individualStoreKeys.map((_, index) => constructCacheUrl(`stores/${index + 1}.json`)),
  ]
  
  // Purge all caches in one batch with retry
  try {
    await retryWithExponentialBackoff(() => clearUrlCache(urls))
    console.log(`Cache purged for all ${urls.length} files`)
  } catch (error) {
    console.error(`Failed to purge cache for all files after 3 retries`, error)
  }
  
  console.log('All cache files created successfully')
  
  return {
    products: productsKey,
    essentialConsts: essentialConstsKey,
    stores: storesKey,
    slots: slotsKey,
    banners: bannersKey,
    individualStores: individualStoreKeys,
  }
}

// Internal versions that skip cache purging (for batch operations)
async function createProductsFileInternal(): Promise<string> {
  const productsData = await scaffoldProducts()
  const jsonContent = JSON.stringify(productsData, null, 2)
  const buffer = Buffer.from(jsonContent, 'utf-8')
  return await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.products}`)
}

async function createEssentialConstsFileInternal(): Promise<string> {
  const essentialConstsData = await scaffoldEssentialConsts()
  const jsonContent = JSON.stringify(essentialConstsData, null, 2)
  const buffer = Buffer.from(jsonContent, 'utf-8')
  return await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.essentialConsts}`)
}

async function createStoresFileInternal(): Promise<string> {
  const storesData = await scaffoldStores()
  const jsonContent = JSON.stringify(storesData, null, 2)
  const buffer = Buffer.from(jsonContent, 'utf-8')
  return await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.stores}`)
}

async function createSlotsFileInternal(): Promise<string> {
  const slotsData = await scaffoldSlotsWithProducts()
  const jsonContent = JSON.stringify(slotsData, null, 2)
  const buffer = Buffer.from(jsonContent, 'utf-8')
  return await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.slots}`)
}

async function createBannersFileInternal(): Promise<string> {
  const bannersData = await scaffoldBanners()
  const jsonContent = JSON.stringify(bannersData, null, 2)
  const buffer = Buffer.from(jsonContent, 'utf-8')
  return await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/${CACHE_FILENAMES.banners}`)
}

async function createAllStoresFilesInternal(): Promise<string[]> {
  const stores = await db.select({ id: storeInfo.id }).from(storeInfo)
  const results: string[] = []
  
  for (const store of stores) {
    const storeData = await scaffoldStoreWithProducts(store.id)
    const jsonContent = JSON.stringify(storeData, null, 2)
    const buffer = Buffer.from(jsonContent, 'utf-8')
    const s3Key = await imageUploadS3(buffer, 'application/json', `${apiCacheKey}/stores/${store.id}.json`)
    results.push(s3Key)
  }
  
  console.log(`Created ${results.length} store cache files`)
  return results
}

export async function clearUrlCache(urls: string[]): Promise<{ success: boolean; errors?: string[] }> {
  if (!cloudflareApiToken || !cloudflareZoneId) {
    console.warn('Cloudflare credentials not configured, skipping cache clear')
    return { success: false, errors: ['Cloudflare credentials not configured'] }
  }

  try {
    const response = await axios.post(
      `https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`,
      { files: urls },
      {
        headers: {
          'Authorization': `Bearer ${cloudflareApiToken}`,
          'Content-Type': 'application/json',
        },
      }
    )

    const result = response.data as { success: boolean; errors?: { message: string }[] }

    if (!result.success) {
      const errorMessages = result.errors?.map(e => e.message) || ['Unknown error']
      console.error(`Cloudflare cache purge failed for URLs: ${urls.join(', ')}`, errorMessages)
      return { success: false, errors: errorMessages }
    }

    console.log(`Successfully purged ${urls.length} URLs from Cloudflare cache: ${urls.join(', ')}`)
    return { success: true }
  } catch (error) {
    console.log(error)
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    console.error(`Error clearing Cloudflare cache for URLs: ${urls.join(', ')}`, errorMessage)
    return { success: false, errors: [errorMessage] }
  }
}

export async function clearAllCache(): Promise<{ success: boolean; errors?: string[] }> {
  if (!cloudflareApiToken || !cloudflareZoneId) {
    console.warn('Cloudflare credentials not configured, skipping cache clear')
    return { success: false, errors: ['Cloudflare credentials not configured'] }
  }

  try {
    const response = await axios.post(
      `https://api.cloudflare.com/client/v4/zones/${cloudflareZoneId}/purge_cache`,
      { purge_everything: true },
      {
        headers: {
          'Authorization': `Bearer ${cloudflareApiToken}`,
          'Content-Type': 'application/json',
        },
      }
    )

    const result = response.data as { success: boolean; errors?: { message: string }[] }

    if (!result.success) {
      const errorMessages = result.errors?.map(e => e.message) || ['Unknown error']
      console.error('Cloudflare cache purge failed:', errorMessages)
      return { success: false, errors: errorMessages }
    }

    console.log('Successfully purged all cache from Cloudflare')
    return { success: true }
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    console.error('Error clearing Cloudflare cache:', errorMessage)
    return { success: false, errors: [errorMessage] }
  }
}
