import { parseArticles, parseArticle } from './util.mjs'
import { uploadMedia, uploadFile, deleteFile } from '../media/upload.mjs'
import { mediaToDatabase } from '../media/util.mjs'

export default class ArticleRoutes {
  constructor(opts = {}) {
    Object.assign(this, {
      uploadMedia: uploadMedia,
      uploadFile: uploadFile,
      deleteFile: deleteFile,
    })
  }

  register(server) {
    server.flaska.get('/api/articles/:path', this.getArticle.bind(this))
    server.flaska.get('/api/auth/articles', server.authenticate(), this.auth_getAllArticles.bind(this))
    server.flaska.get('/api/auth/articles/:id', server.authenticate(), this.auth_getSingleArticle.bind(this))
    server.flaska.put('/api/auth/articles/:id', [
      server.authenticate(),
      server.formidable({ maxFileSize: 20 * 1024 * 1024, }),
    ], this.auth_updateCreateSingleArticle.bind(this))
    server.flaska.delete('/api/auth/articles/:id', server.authenticate(), this.auth_removeSingleArticle.bind(this))
  }

  /** GET: /api/articles/[path] */
  async getArticle(ctx) {
    let res = await ctx.db.safeCallProc('article_get_single', [ctx.params.path])

    ctx.body = this.getArticle_resOutput(res)
  }

  getArticle_resOutput(res) {
    return {
      article: parseArticle(res.results[0][0]),
    }
  }

  /** GET: /api/auth/articles */
  async auth_getAllArticles(ctx) {
    let res = await ctx.db.safeCallProc('article_auth_get_all', [
      ctx.state.auth_token,
      Math.max(ctx.query.get('page') || 1, 1),
      Math.min(ctx.query.get('per_page') || 20, 100)
    ])

    let out = {
      articles: parseArticles(res.results[0]),
      total_articles: res.results[1][0].total_articles,
    }
    
    ctx.body = out
  }

  async private_getUpdateArticle(ctx, body = null, banner = null, media = null) {
    let params = [
      ctx.state.auth_token,
      ctx.params.id === '0' ? null : ctx.params.id
    ]
    if (body) {
      params = params.concat([
        body.name,
        body.page_id === 'null' ? null : Number(body.page_id),
        body.path,
        body.content,
        new Date(body.publish_at),
        Number(body.admin_id),
        body.is_featured === 'true' ? 1 : 0,
        0,
      ])
      params = params.concat(mediaToDatabase(banner, body.remove_banner === 'true'))
      params = params.concat(mediaToDatabase(media, body.remove_media === 'true'))
    }
    let res = await ctx.db.safeCallProc('article_auth_get_update_create', params)

    ctx.body = this.private_getUpdateArticle_resOutput(res)
  }

  private_getUpdateArticle_resOutput(res) {
    return {
      article: parseArticle(res.results[0][0] || {}),
      staff: res.results[1],
    }
  }

  /** GET: /api/auth/articles/:id */
  auth_getSingleArticle(ctx) {
    return this.private_getUpdateArticle(ctx)
  }

  /** PUT: /api/auth/articles/:id */
  async auth_updateCreateSingleArticle(ctx) {
    let newBanner = null
    let newMedia = null

    let promises = []

    if (ctx.req.files.banner) {
      promises.push(
        this.uploadMedia(ctx.req.files.banner)
          .then(res => { newBanner = res })
      )
    }
    if (ctx.req.files.media) {
      promises.push(
        this.uploadMedia(ctx.req.files.media)
          .then(res => { newMedia = res })
      )
    }

    await Promise.all(promises)

    return this.private_getUpdateArticle(ctx, ctx.req.body, newBanner, newMedia)
  }

  /** DELETE: /api/auth/articles/:id */
  async auth_removeSingleArticle(ctx) {
    let params = [
      ctx.state.auth_token,
      ctx.params.id,
      // Article data
      null,
      null,
      null,
      null,
      null,
      null,
      null,
      1,
    ]
    params = params.concat(mediaToDatabase(null, true))
    params = params.concat(mediaToDatabase(null, true))

    await ctx.db.safeCallProc('article_auth_get_update_create', params)

    ctx.status = 204
  }
}
