import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import PaginationService from 'App/Services/PaginationService'
import { schema } from '@ioc:Adonis/Core/Validator'
import OcrDevice from 'App/Models/OcrDevice'
import OcrRecord from 'App/Models/OcrRecord'
import { DateTime } from 'luxon'
import * as console from 'node:console'
import Database from '@ioc:Adonis/Lucid/Database'

export default class OcrDevicesController {
    private paginationService = new PaginationService(OcrDevice)

    public async index({ request, auth }: HttpContextContract) {
        const user = auth.user
        const isApiUser = user?.$attributes?.role === 'api'

        const requestData = request.all()
        if (isApiUser) {
            requestData.channel = user.username
        }
        return await this.paginationService.paginate(request.all())
    }

    public async store({ request, bouncer }: HttpContextContract) {
        // await bouncer.authorize('admin')
        const data = await request.validate({
            schema: schema.create({
                id: schema.string(),
                platform: schema.string(),
                channel: schema.string(),
                deviceInfo: schema.string.optional(),
                total: schema.number(),
                scanned: schema.number(),
                ipAddress: schema.string.optional()
            })
        })
        const clientIp = request.ip()
        if (!data.ipAddress) {
            data.ipAddress = clientIp
        }
        const device = await OcrDevice.findBy('id', data.id)
        if (device) {
            device.merge(data)
            return await device.save()
        } else {
            return await OcrDevice.create(data)
        }
    }

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

    public async plusTotal({ request, response }: HttpContextContract) {
        try {
            const device = await OcrDevice.findBy('id', request.param('id'))
            if (!device) {
                return response.notFound({ message: `未找到ID为 ${request.param('id')} 的OCR设备` })
            }
            device.total += 1
            await device.save()
            return response.ok(device)
        } catch (error) {
            return response.internalServerError({
                message: '更新设备记录数量时发生错误',
                error: error.message
            })
        }
    }

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

        try {
            const device = await OcrDevice.findBy('id', request.param('id'))
            if (!device) {
                return response.notFound({
                    message: `未找到 ID 为 ${request.param('id')} 的 OCR 设备`
                })
            }

            device.scanned += scanCount
            await device.save()

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

    public async getStatistics({ request, response, auth }: HttpContextContract) {
        try {
            const user = auth.user
            const isApiUser = user?.$attributes?.role === 'api'
            const deviceQuery = OcrDevice.query()
            const recordQuery = OcrRecord.query()

            if (isApiUser) {
                deviceQuery.where('channel', user.username)
                recordQuery.where('channel', user.username)
            } else {
                const channel = request.input('channel')
                if (channel) {
                    deviceQuery.where('channel', channel)
                    recordQuery.where('channel', channel)
                }
            }

            // 获取近7天的数据
            const sevenDaysAgo = DateTime.now().minus({ days: 7 }).startOf('day').toSQL()
            const devices = await deviceQuery
                .where('createdAt', '>=', sevenDaysAgo)
                .select('id', 'total', 'scanned', 'createdAt', 'channel')

            // 过去7天的日期数组
            const dates: string[] = []
            for (let i = 6; i >= 0; i--) {
                const date = DateTime.now().minus({ days: i }).toFormat('yyyy-MM-dd')
                dates.push(date)
            }
            const dailyStats: Record<
                string,
                { total: number; scanned: number; deviceCount: number }
            > = {}

            dates.forEach((date) => {
                dailyStats[date] = {
                    total: 0,
                    scanned: 0,
                    deviceCount: 0
                }
            })

            // 按设备创建日期统计数据 scanned和deviceCount
            for (const device of devices) {
                const dateStr = device.createdAt.toFormat('yyyy-MM-dd')
                if (dailyStats[dateStr]) {
                    dailyStats[dateStr].scanned += device.scanned
                    dailyStats[dateStr].deviceCount += 1
                }
            }

            // 获取OcrRecord的每日数量
            for (const date of dates) {
                const startDate = DateTime.fromFormat(date, 'yyyy-MM-dd').startOf('day').toSQL()
                const endDate = DateTime.fromFormat(date, 'yyyy-MM-dd').endOf('day').toSQL()
                const recordCount = await Database.from('ocr_records')
                    .where('created_at', '>=', startDate)
                    .where('created_at', '<=', endDate)
                    .count('* as total')
                dailyStats[date].total = Number(recordCount[0].total) || 0
            }

            // 转换为前端需要的数组格式
            const totals = dates.map((date) => dailyStats[date].total)
            const scanned = dates.map((date) => dailyStats[date].scanned)
            const deviceCounts = dates.map((date) => dailyStats[date].deviceCount)

            return response.ok({
                dates,
                total: totals,
                scanned: scanned,
                deviceCount: deviceCounts
            })
        } catch (error) {
            return response.internalServerError({
                message: '获取设备统计数据时发生错误',
                error: error.message
            })
        }
    }

    public async getTodayStatistics({ request, response, auth }: HttpContextContract) {
        try {
            const user = auth.user
            const isApiUser = user?.$attributes?.role === 'api'
            const deviceQuery = OcrDevice.query()
            const recordQuery = OcrRecord.query()

            // 如果是 API 用户，强制使用其 username 作为 channel
            if (isApiUser) {
                deviceQuery.where('channel', user.username)
                recordQuery.where('channel', user.username)
            } else {
                // 如果不是 API 用户，则使用请求中的 channel 参数
                const channel = request.input('channel')
                if (channel) {
                    deviceQuery.where('channel', channel)
                    recordQuery.where('channel', channel)
                }
            }

            // 获取今天的数据
            const today = DateTime.now().startOf('day').toSQL()
            const todayEnd = DateTime.now().endOf('day').toSQL()
            // 获取设备数据
            const deviceData = await deviceQuery.where('createdAt', '>=', today).select('scanned')
            // 获取OcrRecord数据
            const recordCount = await Database.from('ocr_records')
                .where('created_at', '>=', today)
                .where('created_at', '<=', todayEnd)
                .count('* as total')

            // 计算今日统计数据
            const scanned = deviceData.reduce((acc, item) => acc + item.scanned, 0)
            const total = Number(recordCount[0].total) || 0
            const deviceCount = deviceData.length

            return response.ok({
                date: DateTime.now().toFormat('yyyy-MM-dd'),
                total,
                scanned,
                deviceCount
            })
        } catch (error) {
            return response.internalServerError({
                message: '获取今日统计数据时发生错误',
                error: error.message
            })
        }
    }
}
