import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import PaginationService from 'App/Services/PaginationService'
import OcrChannel from 'App/Models/OcrChannel'
import { schema } from '@ioc:Adonis/Core/Validator'
import { DateTime } from 'luxon'
import Database from '@ioc:Adonis/Lucid/Database'
import User, { UserRoles } from 'App/Models/User'
import UserService from 'App/Services/UserService'
import * as console from 'node:console'

export default class OcrChannelController {
    private paginationService = new PaginationService(OcrChannel)

    public async index({ request, response, auth }: HttpContextContract) {
        try {
            const { page = 1, size = 20, id, deviceId, channel } = request.qs()
            const user = auth.user
            const role = user?.$attributes?.role

            if (!role) {
                return response.forbidden({
                    error: 'Forbidden',
                    message: 'Unauthorized access'
                })
            }

            let userChannel: string | undefined

            if (role === UserRoles.Api) {
                userChannel = user!.username
            } else if (['admin', 'operator'].includes(role)) {
                const apiUsers = await UserService.findReferredUsers(user!.id)
                const allowedChannels = apiUsers.map((user) => user.username as string)

                // 如果请求中指定了channel，检查是否在允许的channel列表中
                if (channel) {
                    if (!allowedChannels.includes(channel)) {
                        return response.ok({
                            data: [],
                            meta: {
                                total: 0,
                                per_page: Number(size),
                                current_page: Number(page),
                                last_page: 0,
                                first_page: 1,
                                first_page_url: '/?page=1',
                                last_page_url: '/?page=0',
                                next_page_url: null,
                                previous_page_url: null
                            }
                        })
                    }
                    userChannel = channel
                } else {
                    userChannel = allowedChannels.join(',')
                }
            } else {
                return response.forbidden({
                    error: 'Forbidden',
                    message: 'You are not authorized to access this resource'
                })
            }

            // 构建查询条件
            const query = OcrChannel.query()

            if (id) {
                query.where('id', id)
            }

            if (deviceId) {
                query.whereIn('name', function (builder) {
                    builder.select('channel').from('ocr_devices').where('id', deviceId)
                })
            }

            if (userChannel) {
                query.whereIn('name', userChannel.split(','))
            }

            // 执行分页查询
            const result = await query.orderBy('created_at', 'desc').paginate(page, size)

            return response.ok(result)
        } catch (error) {
            return response.internalServerError({
                message: '获取OCR渠道列表时发生错误',
                error: error.message
            })
        }
    }

    public async store({ request, bouncer }: HttpContextContract) {
        await request.validate({
            schema: schema.create({
                name: schema.string.optional(),
                deviceNum: schema.number(),
                recordNum: schema.number(),
                scanNum: schema.number()
            })
        })
        const ocrChannel = await OcrChannel.create(request.all())
        await this.updateChannelStats(ocrChannel)
        return ocrChannel
    }

    public async show({ params, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        return await OcrChannel.findOrFail(params.id)
    }

    public async update({ params, request, bouncer }: HttpContextContract) {
        await bouncer.authorize('admin')
        const ocrChannel = await OcrChannel.findOrFail(params.id)
        const data = await request.validate({
            schema: schema.create({
                name: schema.string.optional(),
                deviceNum: schema.number.optional(),
                recordNum: schema.number.optional(),
                scanNum: schema.number.optional()
            })
        })
        return await ocrChannel.merge(data).save()
    }

    public async findApiChannel({ auth, response }: HttpContextContract) {
        if (!auth.user) {
            return response.unauthorized({ message: 'unauthorized' })
        }
        return await OcrChannel.findBy('name', auth.user.username)
    }

    public async plusDeviceNum({ request, response }: HttpContextContract) {
        try {
            const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
            if (!ocrChannel) {
                return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` })
            }

            ocrChannel.deviceNum += 1
            await ocrChannel.save()
            return ocrChannel
        } catch (error) {
            return response.internalServerError({
                message: '更新设备数量时发生错误',
                error: error.message
            })
        }
    }

    public async plusRecordNum({ request, response }: HttpContextContract) {
        try {
            const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
            if (!ocrChannel) {
                return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR渠道` })
            }
            ocrChannel.recordNum += 1
            await ocrChannel.save()
            return ocrChannel
        } catch (error) {
            return response.internalServerError({
                message: '更新记录数量时发生错误',
                error: error.message
            })
        }
    }

    public async plusScanNum({ request, response }: HttpContextContract) {
        const scanCount = Number(request.param('scanCount'))
        if (isNaN(scanCount)) {
            return response.badRequest({ message: 'scanCount 参数必须是有效数字' })
        }

        try {
            const ocrChannel = await OcrChannel.findBy('id', request.param('id'))
            if (!ocrChannel) {
                return response.notFound({
                    message: `未找到 ID 为 ${request.param('id')} 的 OCR 渠道`
                })
            }

            ocrChannel.scanNum = (Number(ocrChannel.scanNum) || 0) + scanCount
            await ocrChannel.save()

            return response.ok(ocrChannel)
        } catch (error) {
            return response.internalServerError({
                message: '更新扫描数量时发生错误',
                error: error.message
            })
        }
    }

    public async getStatistics({ request, response }: HttpContextContract) {
        try {
            const name = request.input('name')
            let query = Database.from('ocr_channels')

            if (name) {
                query = query.where('name', name)
            }

            const sevenDaysAgo = DateTime.now().minus({ days: 7 }).startOf('day').toSQL()
            const data = await query
                .where('created_at', '>=', sevenDaysAgo)
                .orderBy('created_at', 'asc')
                .select(
                    'created_at',
                    'device_num as deviceNum',
                    'record_num as recordNum',
                    'scan_num as scanNum'
                )

            const result = {
                dates: data.map((item) => DateTime.fromISO(item.created_at).toFormat('yyyy-MM-dd')),
                deviceNum: data.map((item) => item.deviceNum),
                recordNum: data.map((item) => item.recordNum),
                scanNum: data.map((item) => item.scanNum)
            }

            return response.ok(result)
        } catch (error) {
            return response.internalServerError({
                message: '获取统计数据时发生错误',
                error: error.message
            })
        }
    }

    public async getChannelNames({ auth, response }: HttpContextContract) {
        try {
            const user = auth.user
            const role = user?.$attributes?.role

            if (!role) {
                return response.forbidden({
                    error: 'Forbidden',
                    message: 'Unauthorized access'
                })
            }

            let channel: string = ''
            if (['admin', 'operator'].includes(role)) {
                const apiUsers = await UserService.findReferredUsers(user!.id)
                const allowedChannels = apiUsers.map((user) => user.username as string)
                channel = allowedChannels.join(',')
            } else {
                return response.forbidden({
                    error: 'Forbidden',
                    message: 'You are not authorized to access this resource'
                })
            }

            // 获取指定渠道名称
            const channels = await OcrChannel.query()
                .select('name')
                .whereIn('name', channel.split(','))
                .orderBy('name', 'asc')

            return response.ok({
                data: channels.map((channel) => channel.name)
            })
        } catch (error) {
            return response.internalServerError({
                message: '获取渠道名称列表时发生错误',
                error: error.message
            })
        }
    }

    private async updateChannelStats(channel: OcrChannel) {
        // 获取设备数量
        const deviceCountResult = await Database.from('ocr_devices')
            .where('channel', channel.name)
            .count('* as total')

        // 获取记录数量
        const recordCountResult = await Database.from('ocr_records')
            .where('channel', channel.name)
            .count('* as total')

        // 获取扫描数量总和
        const scanSumResult = await Database.from('ocr_devices')
            .where('channel', channel.name)
            .sum('scanned as total')

        // 更新渠道数据
        channel.deviceNum = parseInt(deviceCountResult[0].total || '0', 10)
        channel.recordNum = parseInt(recordCountResult[0].total || '0', 10)
        channel.scanNum = parseInt(scanSumResult[0].total || '0', 10)

        await channel.save()

        return {
            id: channel.id,
            name: channel.name,
            deviceNum: channel.deviceNum,
            recordNum: channel.recordNum,
            scanNum: channel.scanNum
        }
    }

    public async updateStatistics({ response }: HttpContextContract) {
        try {
            // 获取所有渠道
            const channels = await OcrChannel.all()
            const results = await Promise.all(
                channels.map((channel) => this.updateChannelStats(channel))
            )

            return response.ok({
                message: '所有渠道统计数据已更新',
                data: results
            })
        } catch (error) {
            return response.internalServerError({
                message: '更新所有渠道统计数据时发生错误',
                error: error.message
            })
        }
    }

    public async getChannelOcrLevel({ params, response }: HttpContextContract) {
        try {
            const { name } = params
            if (!name) {
                return response.ok({ level: 0 })
            }

            const ocrChannel = await OcrChannel.findBy('name', name)
            if (!ocrChannel) {
                return response.ok({ level: 0 })
            }
            return response.ok({ level: ocrChannel.ocrLevel })
        } catch (error) {
            return response.ok({ level: 0 })
        }
    }
}
