import fs from 'fs/promises'
import path from 'path'
import { app } from 'electron'

const USER_DATA_STRING = '__DEFAULT_USER_DATA__'

export default class Config {
    constructor(defaultPlugin) {
        this.defaultPlugin = defaultPlugin
        this.configPath = path.join(app.getPath('userData'), 'config.json')
    }

    // Helper to replace placeholders with dynamic values
    _resolveDefaults(config) {
        if (Array.isArray(config)) {
            return config.map((item) => this._resolveDefaults(item))
        } else if (config && typeof config === 'object') {
            const resolved = {}
            for (const [key, value] of Object.entries(config)) {
                resolved[key] = this._resolveDefaults(value)
            }
            return resolved
        } else if (
            typeof config === 'string' &&
            config.includes(USER_DATA_STRING)
        ) {
            return config.replace(USER_DATA_STRING, app.getPath('userData'))
        } else {
            return config
        }
    }

    async load() {
        let parsed

        try {
            const raw = await fs.readFile(this.configPath, 'utf8')
            parsed = JSON.parse(raw)
        } catch (err) {
            parsed = null
        }

        if (!parsed || !parsed.activeAdapter) {
            const defaultConfig = {}

            for (const field of this.defaultPlugin.configSchema) {
                defaultConfig[field.key] = field.default ?? null
            }

            parsed = {
                ...(parsed ? parsed : {}),
                activeAdapter: this.defaultPlugin.id,
            }
            parsed.adapters[this.defaultPlugin.id] = defaultConfig

            await this.write(parsed)
        } else {
            // Ensure any "__DEFAULT_USER_DATA__" values are resolved on load
            parsed.adapterConfig = this._resolveDefaults(parsed.adapterConfig)
        }

        return parsed
    }

    async write(configObject) {
        const dir = path.dirname(this.configPath)

        // Ensure directory exists
        await fs.mkdir(dir, { recursive: true })

        // Resolve defaults before writing
        const resolvedConfig = {
            ...configObject,
            adapterConfig: this._resolveDefaults(configObject.adapterConfig),
        }

        await fs.writeFile(
            this.configPath,
            JSON.stringify(resolvedConfig, null, 2),
            'utf8',
        )
    }
}
