import DirectusSDK from '@directus/sdk-js'
import { IFile } from '@directus/sdk-js/dist/types/schemes/directus/File'
import bent from 'bent'
import fs from 'fs'
import getConfig from 'next/config'
import path from 'path'
import { promisify } from 'util'

const { serverRuntimeConfig } = getConfig()
const writeFile = promisify(fs.writeFile)
const getBuffer = bent('buffer')

const assetsDir = path.join(serverRuntimeConfig.PROJECT_ROOT, '/src/assets/')

const notasImagesDir = path.join(assetsDir, '/notas/')
const workImagesDir = path.join(assetsDir, '/work/')
const avatarImagesDir = path.join(assetsDir, '/avatar/')

const createDir = (dir: string) => {
  if (!fs.existsSync(dir)) {
    console.info(`Creating directory ${dir}`)
    fs.mkdirSync(dir)
  }
}

createDir(assetsDir)
createDir(notasImagesDir)
createDir(workImagesDir)
createDir(avatarImagesDir)

export interface IFileWithData extends IFile {
  filename_disk: string
  data: {
    full_url: string
  }
}

export async function getImage(id: number) {
  const images = ((await client.getFiles()) as unknown) as { data: Array<IFileWithData> }
  return images.data.find((file) => file.id === id)
}

export async function downloadFile(id: number, dir: string): Promise<string | null> {
  const imageData = await getImage(id)
  if (!imageData) return null
  const fileDir = path.join(dir, imageData.filename_disk)

  if (!fs.existsSync(fileDir)) {
    console.info(`Downloading image with id ${id} as ${fileDir}`)
    const buffer = await getBuffer(imageData.data.full_url.replace('http', 'https'))
    await writeFile(fileDir, buffer as Buffer)
    console.info(`Succesfully downloaded image with ${fileDir}`)
  } else {
    console.info(`Image ${fileDir} exists. Skipping download`)
  }

  return imageData.filename_disk
}

export async function extractUrlAndDownloadImage(element, imageKey: string, dir: string) {
  const data = element.data ? element.data : element
  const imageId = await data[imageKey]
  const imagenUrl = imageId ? await downloadFile(imageId, dir) : null
  const returnValue = { ...data, [`${imageKey}_file`]: imagenUrl }

  return returnValue
}

const client = new DirectusSDK({
  mode: 'jwt',
  project: '_',
  url: process.env.DIRECTUS_HOST,
})

export async function login() {
  return client.login({
    email: process.env.DIRECTUS_API_USER,
    password: process.env.DIRECTUS_API_PASSWORD,
  })
}

export interface IWork {
  id: number
  titulo: string
  banner: number
  tags: string[]
  cliente: string
  pais: string
  year: string
  texto_descripcion: string
  color1: string
  color2: string
  imagenes: number[]
  slug: string
}

export interface IWorkWithBanner extends IWork {
  banner_file: string | null
}

export interface IWorkWithImages extends IWorkWithBanner {
  imagenes_files: string[] | null
}

export async function getAllWorks() {
  return client.getItems<IWork[]>('work')
}

export async function getWorkById(id: number) {
  return client.getItem<IWork>('work', id)
}

export async function getWorkBySlug(slug: string) {
  return client.getItems<IWork[]>('work', {
    filter: {
      slug: {
        eq: slug,
      },
    },
  })
}

export async function getNotaBySlug(slug: string) {
  return client.getItems<INota[]>('notas', {
    filter: {
      slug: {
        eq: slug,
      },
    },
  })
}

export interface IAbout {
  texto_about: string
  texto_team: string
}

export async function getAbout() {
  return client.getItem<IAbout>('about', 1)
}

export interface IInicio {
  mensaje_inspirador: string
  fondo: number
}

export interface IInicioWithImage extends IInicio {
  fondo_file: string
}

export async function getInicio() {
  return client.getItem<IInicio[]>('inicio', 1)
}

interface IWorkImageIds {
  id: number
  work_id: number
  directus_files_id: number
}

export async function getWorkImageIds(id: number) {
  return client.getItems<IWorkImageIds[]>('work_directus_files', {
    filter: {
      work_id: {
        eq: id,
      },
    },
  })
}

export interface ITeamMember {
  id: number
  nombre: string
  cita: string
  avatar: number
}

export interface ITeamMemberWithImage extends ITeamMember {
  avatar_file: string
}

export async function getAllTeam() {
  return client.getItems<ITeamMember[]>('el_team')
}

export async function getTeamById(id: number) {
  return client.getItem<ITeamMember>('team', id)
}

export interface INota {
  id: number
  titulo: string
  tiempo_lectura: number
  cuerpo: string
  tags: string[]
  slug: string
  imagen: number
}

export interface INotaWithImage extends INota {
  imagen_file: string | null
}

export async function getAllNotas() {
  return client.getItems<INota[]>('notas')
}

export async function getNotaById(id: number) {
  return client.getItem<INota>('notas', id)
}

export async function getAllNotasWithImages(): Promise<INotaWithImage[]> {
  const notas = await getAllNotas()

  const notasWithImages: INotaWithImage[] = await Promise.all(
    notas.data.map(async (nota) =>
      extractUrlAndDownloadImage(nota, 'imagen', notasImagesDir),
    ),
  )

  return notasWithImages
}

export async function getNotaWithImage(slug: string): Promise<INotaWithImage> {
  const _nota = await getNotaBySlug(slug)
  const nota = _nota.data[0]

  const notaWithImage = await extractUrlAndDownloadImage(nota, 'imagen', notasImagesDir)
  return notaWithImage
}

export async function getAllWorksWithBanners(): Promise<IWorkWithBanner[]> {
  const works = await getAllWorks()

  const worksWithBanners: IWorkWithBanner[] = await Promise.all(
    works.data.map(async (work) =>
      extractUrlAndDownloadImage(work, 'banner', workImagesDir),
    ),
  )

  return worksWithBanners
}

export async function getInicioWithImage(): Promise<IInicioWithImage> {
  const inicio = await getInicio()
  const inicioWithImage = await extractUrlAndDownloadImage(inicio, 'fondo', assetsDir)
  return inicioWithImage
}

export async function getWorkWithImages(slug: string): Promise<IWorkWithImages> {
  const _work = await getWorkBySlug(slug)
  const work = _work.data[0]

  const workImageIds = await getWorkImageIds(work.id)

  const workWithBanner = await extractUrlAndDownloadImage(work, 'banner', workImagesDir)
  const imageNames: string[] = await Promise.all(
    workImageIds.data.map(async (image) =>
      downloadFile(image.directus_files_id, workImagesDir),
    ),
  )

  return { ...workWithBanner, imagenes_files: imageNames }
}

export async function getTeamMembersWithImages(): Promise<ITeamMemberWithImage[]> {
  const team = await getAllTeam()

  const teamWithAvatars: ITeamMemberWithImage[] = await Promise.all(
    team.data.map(async (member) =>
      extractUrlAndDownloadImage(member, 'avatar', avatarImagesDir),
    ),
  )

  return teamWithAvatars
}

export default client
