import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Collection from 'App/Models/Collection'
import PaginationService from 'App/Services/PaginationService'
import { schema } from '@ioc:Adonis/Core/Validator'
import Episode from 'App/Models/Episode'
import Series from 'App/Models/Series'

export default class CollectionsController {
    private paginationService = new PaginationService(Collection)
    public async index({ request, auth }: HttpContextContract) {
        const page = await this.paginationService.paginate({
            ...request.all(),
            userId: auth.user!.id
        })
        const seriesIds = new Set(
            page
                .all()
                .map((record) => record.seriesId)
                .filter((id) => !!id)
        )
        const series = await Series.findMany(Array.from(seriesIds))
        const episodeIds = new Set(
            page
                .all()
                .map((record) => record.curEpId)
                .filter((id) => !!id)
        )
        const episodes = await Episode.findMany(Array.from(episodeIds))
        page.all().forEach((record) => {
            if (record.seriesId) {
                record.series = series.find((s) => s.id === record.seriesId)
            }
            if (record.curEpId) {
                record.episode = episodes.find((e) => e.id === record.curEpId)
            }
        })
        return page
    }

    public async store({ request, auth }: HttpContextContract) {
        const data = await request.validate({
            schema: schema.create({
                seriesId: schema.number(),
                curEpId: schema.number()
            })
        })
        let collection = await Collection.query()
            .where('user_id', auth.user!.id)
            .where('series_id', data.seriesId)
            .first()
        const ep = await Episode.findOrFail(data.curEpId)
        if (collection) {
            collection.curEpId = data.curEpId
            collection.curEpNum = ep.episodeNum
            await collection.save()
        } else {
            collection = await Collection.create({
                userId: auth.user!.id,
                seriesId: data.seriesId,
                curEpId: data.curEpId,
                curEpNum: ep.episodeNum
            })
        }
        return collection
    }

    public async show({ params, auth }: HttpContextContract) {
        return await Collection.query()
            .where('userId', auth.user!.id)
            .where('seriesId', params.id)
            .firstOrFail()
    }

    public async update({ request, params, bouncer }: HttpContextContract) {
        const data = await request.validate({
            schema: schema.create({
                userId: schema.number.optional(),
                seriesId: schema.number.optional(),
                curEpId: schema.number.optional()
            })
        })
        const collection = await Collection.findOrFail(params.id)
        await bouncer.authorize('owner', collection)
        collection.merge(data)
        return await collection.save()
    }

    public async destroy({ params, auth }: HttpContextContract) {
        await Collection.query()
            .where('userId', auth.user!.id)
            .where('seriesId', params.id)
            .delete()
    }
}
