import { ipcMain, dialog, app } from 'electron'
import fs from 'fs'
import path from 'path'
import { encrypt, fromEncryptedJson } from './utils/keystore'

const neptuneNative = require('@neptune/native')

// Create keystore into default wallets directory
ipcMain.handle('wallet:createKeystore', async (_event, seed, password) => {
    try {
        const keystore = await encrypt(seed, password)

        const savePath = path.join(process.cwd(), 'wallets')
        fs.mkdirSync(savePath, { recursive: true })

        // Use timestamp for filename
        const timestamp = Date.now()
        const fileName = `neptune-wallet-${timestamp}.json`
        const filePath = path.join(savePath, fileName)
        fs.writeFileSync(filePath, keystore)

        return { filePath }
    } catch (error) {
        console.error('Error creating keystore:', error)
        throw error
    }
})

// New handler: let user choose folder and filename to save keystore
ipcMain.handle('wallet:saveKeystoreAs', async (_event, seed: string, password: string) => {
    try {
        const keystore = await encrypt(seed, password)

        // Use timestamp for default filename
        const timestamp = Date.now()
        const defaultName = `neptune-wallet-${timestamp}.json`
        const { canceled, filePath } = await dialog.showSaveDialog({
            title: 'Save Keystore File',
            defaultPath: path.join(app.getPath('documents'), defaultName),
            filters: [{ name: 'JSON', extensions: ['json'] }],
        })

        if (canceled || !filePath) return { filePath: null }

        fs.mkdirSync(path.dirname(filePath), { recursive: true })
        fs.writeFileSync(filePath, keystore)

        return { filePath }
    } catch (error) {
        console.error('Error saving keystore (Save As):', error)
        throw error
    }
})

ipcMain.handle('wallet:decryptKeystore', async (_event, filePath, password) => {
    try {
        const json = fs.readFileSync(filePath, 'utf-8')
        const phrase = await fromEncryptedJson(json, password)

        return { phrase }
    } catch (error) {
        console.error('Error decrypting keystore ipc:', error)
        throw error
    }
})

ipcMain.handle('wallet:checkKeystore', async () => {
    try {
        const walletDir = path.join(process.cwd(), 'wallets')
        if (!fs.existsSync(walletDir)) return { exists: false, filePath: null }

        const newestFile = fs
            .readdirSync(walletDir)
            .filter((f) => f.endsWith('.json'))
            .sort(
                (a, b) =>
                    fs.statSync(path.join(walletDir, b)).mtime.getTime() -
                    fs.statSync(path.join(walletDir, a)).mtime.getTime()
            )[0]

        if (!newestFile?.length) return { exists: false, filePath: null }

        const resolvedPath = path.join(walletDir, newestFile)
        let minBlockHeight: number | null = null

        try {
            const json = fs.readFileSync(resolvedPath, 'utf-8')
            const data = JSON.parse(json)
            const height = data?.minBlockHeight

            if (Number.isFinite(height)) minBlockHeight = height
        } catch (error) {
            console.warn('Unable to read minBlockHeight from keystore:', error)
            return { exists: true, filePath: resolvedPath }
        }

        return { exists: true, filePath: resolvedPath, minBlockHeight }
    } catch (error) {
        console.error('Error checking keystore ipc:', error)
        return { exists: false, filePath: null, minBlockHeight: null, error: String(error) }
    }
})

ipcMain.handle(
    'wallet:updateMinBlockHeight',
    async (_event, filePath: string | null, minBlockHeight: number | null) => {
        if (!filePath) {
            return { success: false, error: 'No keystore file path provided.' }
        }

        try {
            const normalizedPath = path.isAbsolute(filePath)
                ? filePath
                : path.join(process.cwd(), filePath)

            if (!fs.existsSync(normalizedPath)) {
                return { success: false, error: 'Keystore file not found.' }
            }

            const fileContents = fs.readFileSync(normalizedPath, 'utf-8')
            const walletJson = JSON.parse(fileContents)

            if (minBlockHeight === null || Number.isNaN(minBlockHeight)) {
                walletJson.minBlockHeight = null
            } else {
                walletJson.minBlockHeight = minBlockHeight
            }

            fs.writeFileSync(normalizedPath, JSON.stringify(walletJson, null, 2), 'utf-8')

            return { success: true, minBlockHeight }
        } catch (error) {
            console.error('Error updating min block height:', error)
            return { success: false, error: String(error) }
        }
    }
)

ipcMain.handle('wallet:getMinBlockHeight', async (_event, filePath: string | null) => {
    if (!filePath) {
        return { success: false, error: 'No keystore file path provided.', minBlockHeight: null }
    }

    try {
        const normalizedPath = path.isAbsolute(filePath)
            ? filePath
            : path.join(process.cwd(), filePath)

        if (!fs.existsSync(normalizedPath)) {
            return { success: false, error: 'Keystore file not found.', minBlockHeight: null }
        }

        const fileContents = fs.readFileSync(normalizedPath, 'utf-8')
        const walletJson = JSON.parse(fileContents)
        const height = walletJson?.minBlockHeight

        if (Number.isFinite(height)) {
            return { success: true, minBlockHeight: height }
        }

        return { success: true, minBlockHeight: null }
    } catch (error) {
        console.error('Error reading min block height:', error)
        return { success: false, error: String(error), minBlockHeight: null }
    }
})

ipcMain.handle('wallet:generateKeysFromSeed', async (_event, seedPhrase: string[]) => {
    try {
        const wallet = new neptuneNative.WalletManager()
        return wallet.generateKeysFromSeed(seedPhrase)
    } catch (error) {
        console.error('Error generating keys from seed ipc:', error)
        throw error
    }
})

ipcMain.handle('wallet:buildTransaction', async (_event, args) => {
    const { spendingKeyHex, inputAdditionRecords, outputAddresses, outputAmounts, fee } = args

    try {
        const builder = new neptuneNative.SimpleTransactionBuilder()
        const result = await builder.buildTransaction(
            import.meta.env.VITE_APP_API,
            spendingKeyHex,
            inputAdditionRecords,
            typeof args?.minBlockHeight === 'number' && Number.isFinite(args.minBlockHeight)
                ? args.minBlockHeight
                : 0,
            outputAddresses,
            outputAmounts,
            fee
        )
        return JSON.parse(result)
    } catch (error) {
        console.error('Error building transaction with primitive proof ipc:', error)
        throw error
    }
})
