import Logger from '@ioc:Adonis/Core/Logger'
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import UserBalance from 'App/Models/UserBalance'
import PaginationService from 'App/Services/PaginationService'
import { schema, rules } from '@ioc:Adonis/Core/Validator'
import UserBalanceService from 'App/Services/UserBalanceService'
import Decimal from 'decimal.js'
import { BalanceRecordType } from 'App/Models/BalanceRecord'
import qs from 'qs'
import { format } from 'date-fns'
import { createHash } from 'crypto'
import axios from 'axios'
import { InternalServerException } from 'App/Exceptions/Common'
import { Exception } from '@adonisjs/core/build/standalone'
import RechargeOrder, { RechargeOrderStatus } from 'App/Models/RechargeOrder'
import { DateTime } from 'luxon'

export default class UserBalancesController {
    private paginationService = new PaginationService(UserBalance)
    public async index({ request }: HttpContextContract) {
        return await this.paginationService.paginate(request.all())
    }

    public async store({ request }: HttpContextContract) {
        const data: any = await request.validate({
            schema: schema.create({
                userId: schema.number(),
                balance: schema.string()
            })
        })
        const userBalance = await UserBalance.create(data)
        return userBalance
    }

    public async show({ params, bouncer }: HttpContextContract) {
        const row = await UserBalanceService.getBalance(params.id)
        await bouncer.authorize('owner', row)
        return row
    }

    public async update({ params, request }: HttpContextContract) {
        const userBalance = await UserBalance.findOrFail(params.id)
        const data: any = await request.validate({
            schema: schema.create({
                userId: schema.number.optional(),
                amount: schema.number.optional(),
                type: schema.string.optional(),
                description: schema.string.optional()
            })
        })
        userBalance.merge(data)
        await userBalance.save()
        return userBalance
    }

    public async destroy({ params }: HttpContextContract) {
        const userBalance = await UserBalance.findOrFail(params.id)
        await userBalance.delete()
    }

    // public async recharge({ request }: HttpContextContract) {
    //     console.log(JSON.stringify(request.all(), null, 4))
    //     UserBalanceService.modifiyBalance({
    //         userId: parseInt(request.param('userId')),
    //         amount: new Decimal(request.input('id')),
    //         type: BalanceRecordType.Recharge
    //     })
    //     const data = request.all()
    //     return {
    //         ok: true,
    //         data: {
    //             id: data.id,
    //             latest_receipt: true,
    //             transaction: data.transaction
    //         }
    //     }
    // }

    public async recharge({ request, auth }: HttpContextContract) {
        // const data: any = await request.validate({
        //     schema: schema.create({
        //         amount: schema.number(),
        //         type: schema.string.optional()
        //     })
        // })
        const amount = '2000000'
        const order = await RechargeOrder.create({
            userId: auth.user!.id,
            amount: new Decimal(amount),
            status: RechargeOrderStatus.Pending
        })
        const head = {
            mchtId: '2000220000449457',
            version: '20',
            biz: 'wp101'
        }
        const body = {
            orderId: order.id.toString(),
            orderTime: format(new Date(), 'yyyyMMddHHmmss'),
            amount: amount,
            currencyType: 'IDR',
            goods: 'recharge',
            notifyUrl: 'https://kaliartdrama.run.place/api/userBalances/rechargeNotify',
            callBackUrl: 'https://kaliartdrama.run.place',
            email: 'aaabbb@example.com',
            phone: '621111111111',
            name: 'zhang san',
            operator: 'OVO'
        }
        const str = qs.stringify(body, {
            encode: false,
            sort: (a, b) => {
                return a.localeCompare(b)
            }
        })
        Logger.info('param string=%s', str)

        const md5 = createHash('md5')
        const sign = md5.update(str + '&key=83cdc062cba24ea6b166adfdb9b782c1').digest('hex')

        Logger.info('sign=%s', sign)

        Logger.info(
            JSON.stringify(
                {
                    head,
                    body,
                    sign
                },
                null,
                4
            )
        )
        const res = await axios.post('https://api.haodamall.com/gateway/api/commPay', {
            head,
            body,
            sign
        })
        Logger.info('res=%s', JSON.stringify(res.data, null, 4))

        if (res.data.head.respCode === '0000') {
            return res.data.body
        } else {
            throw new Exception(res.data.head.respMsg)
        }
    }

    public async rechargeNotify({ request }: HttpContextContract) {
        const data = request.all()
        Logger.info('rechargeNotify: ' + JSON.stringify(data, null, 4))
        if (data.head.respCode === '0000') {
            try {
                const order = await RechargeOrder.findOrFail(parseInt(data.body.orderId))
                if (order.status === RechargeOrderStatus.Pending) {
                    order.status = RechargeOrderStatus.Success
                    order.transactionId = data.body.tradeId
                    order.payTime = DateTime.now()
                    await order.save()

                    await UserBalanceService.modifiyBalance({
                        userId: order.userId,
                        amount: order.amount,
                        type: BalanceRecordType.Recharge
                    })
                }
            } catch (error) {
                Logger.error(error)
            }
        }
        return 'SUCCESS'
    }
}
