import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Series from 'App/Models/Series'
import PaginationService from 'App/Services/PaginationService'
import { schema } from '@ioc:Adonis/Core/Validator'
import Decimal from 'decimal.js'

export default class SeriesController {
    private paginationService = new PaginationService(Series)
    public async index({ request }: HttpContextContract) {
        const data = request.all()
        return await this.paginationService.paginate(request.all(), (q) => {
            q.preload('categories')
            this.queryCategories(q, data.categories)
        })
    }

    private queryCategories(q: any, categories: any) {
        if (categories) {
            if (categories instanceof Array) {
                categories.forEach((item, index) => {
                    if (index === 0)
                        q.whereHas('categories', (wh) => {
                            wh.where('categories.id', item)
                        })
                    else
                        q.orWhereHas('categories', (wh) => {
                            wh.where('categories.id', item)
                        })
                })
            } else {
                q.whereHas('categories', (wh) => {
                    wh.where('categories.id', categories)
                })
            }
        }
    }

    public async store({ request, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        await request.validate({
            schema: schema.create({
                title: schema.string(),
                description: schema.string.optional(),
                cover: schema.string.optional(),
                landscapeCover: schema.string.optional(),
                tags: schema.array.optional().members(schema.string()),
                releaseDate: schema.date.optional(),
                meta: schema.object.optional().anyMembers()
            })
        })
        return await Series.create(request.all())
    }

    public async show({ params }: HttpContextContract) {
        const data = await Series.findOrFail(params.id)
        await data.load('categories')
        return data
    }

    public async update({ params, request, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        const serie = await Series.findOrFail(params.id)
        const payload = (await request.validate({
            schema: schema.create({
                title: schema.string.optional(),
                description: schema.string.optional(),
                cover: schema.string.optional(),
                landscapeCover: schema.string.optional(),
                tags: schema.array.optional().members(schema.string()),
                releaseDate: schema.date.optional(),
                meta: schema.object.optional().anyMembers(),
                price: schema.string.optional(),
                categories: schema.array.optional().anyMembers(),
                totalEpisodes: schema.number.optional()
            })
        })) as any
        if (payload.price) {
            payload.price = new Decimal(payload.price)
        }
        if (payload.categories) {
            await serie.related('categories').sync(payload.categories.map((item: any) => item.id))
            delete payload.categories
        }
        serie.merge(payload)
        return await serie.save()
    }

    public async destroy({ params, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        const serie = await Series.findOrFail(params.id)
        await serie.delete()
    }

    public async search({ request }: HttpContextContract) {
        const data = request.all()
        return await this.paginationService.paginate(data, (q) => {
            if (data.title) {
                q.where('title', 'like', `%${data.title}%`)
            }
            this.queryCategories(q, data.categories)
        })
    }
}
