import fs from 'fs';
import path from 'path';
import os from 'os';
import yaml from 'js-yaml';
import crypto from 'crypto';

const BASE_DIR = path.join(os.homedir(), 'WaifuBoards');
const CONFIG_PATH = path.join(BASE_DIR, 'config.yaml');

const DEFAULT_CONFIG = {
    library: {
        anime: null,
        manga: null,
        novels: null
    },
    paths: {
        mpv: null,
        ffmpeg: null,
        ffprobe: null,
        cloudflared: null,
    },
    server: {
        jwt_secret: null
    }
};

export const CONFIG_SCHEMA = {
    library: {
        anime: { description: "Path where anime is stored" },
        manga: { description: "Path where manga is stored" },
        novels: { description: "Path where novels are stored" }
    },
    paths: {
        mpv: { description: "Required to open anime episodes in mpv on desktop version." },
        ffmpeg: { description: "Required for downloading anime episodes." },
        ffprobe: { description: "Required for watching local anime episodes." },
        cloudflared: { description: "Required for creating pubic rooms." }
    }
};

function ensureConfigFile() {
    if (!fs.existsSync(BASE_DIR)) {
        fs.mkdirSync(BASE_DIR, { recursive: true });
    }

    let configExists = fs.existsSync(CONFIG_PATH);

    if (!configExists) {
        fs.writeFileSync(
            CONFIG_PATH,
            yaml.dump(DEFAULT_CONFIG),
            'utf8'
        );
    }

    const raw = fs.readFileSync(CONFIG_PATH, 'utf8');
    const loaded = yaml.load(raw) || {};

    if (!loaded.server) loaded.server = {};
    if (!loaded.server.jwt_secret) {
        loaded.server.jwt_secret = crypto.randomBytes(32).toString('hex');
        fs.writeFileSync(CONFIG_PATH, yaml.dump(deepMerge(structuredClone(DEFAULT_CONFIG), loaded)), 'utf8');
    }
}

export function getPublicConfig() {
    const { values } = getConfig();
    const publicConfig = structuredClone(values);
    if (publicConfig.server) delete publicConfig.server.jwt_secret;
    return publicConfig;
}

export function getConfig() {
    ensureConfigFile();
    const raw = fs.readFileSync(CONFIG_PATH, 'utf8');
    const loaded = yaml.load(raw) || {};

    return {
        values: deepMerge(structuredClone(DEFAULT_CONFIG), loaded),
        schema: CONFIG_SCHEMA
    };
}

function sanitizeLoadedConfig(loaded) {
    return {
        library: loaded.library,
        paths: loaded.paths
    };
}

export function setConfig(partialConfig) {
    ensureConfigFile();

    const raw = fs.readFileSync(CONFIG_PATH, 'utf8');
    const loadedRaw = yaml.load(raw) || {};
    const loaded = sanitizeLoadedConfig(loadedRaw);

    const next = deepMerge(
        structuredClone(DEFAULT_CONFIG),
        deepMerge(loaded, partialConfig)
    );

    const toSave = {
        library: next.library,
        paths: next.paths
    };

    fs.writeFileSync(CONFIG_PATH, yaml.dump(toSave), 'utf8');
    return next;
}

function deepMerge(target, source) {
    for (const key in source) {
        if (
            source[key] &&
            typeof source[key] === 'object' &&
            !Array.isArray(source[key])
        ) {
            target[key] = deepMerge(target[key] || {}, source[key]);
        } else {
            target[key] = source[key];
        }
    }
    return target;
}

module.exports = {
    ensureConfigFile,
    getConfig,
    setConfig,
};