import dotenv from 'dotenv';
import path from 'path';
import fs from 'fs';

// Load environment variables from .env file
dotenv.config();

/**
 * Default RPC URL from nano.to
 * High-performance public enterprise node for the Nano blockchain
 * Visit https://rpc.nano.to/ to get your free API key
 */
const DEFAULT_RPC_URL = 'https://rpc.nano.to/';

/**
 * Default representative address
 * This address is used when no representative is specified
 * 
 * To choose a different representative:
 * 1. Visit https://nanexplorer.com/nano/representatives
 * 2. Select a representative with good uptime and reasonable voting weight
 * 3. Copy their address and use it in your configuration
 * 
 * Choosing a good representative helps maintain network decentralization
 */
const DEFAULT_REPRESENTATIVE = 'nano_3arg3asgtigae3xckabaaewkx3bzsh7nwz7jkmjos79ihyaxwphhm6qgjps4';

const DEFAULT_RPC_KEY = 'RPC-KEY-BAB822FCCDAE42ECB7A331CCAAAA23';

export interface NanoConfig {
    rpcUrl: string;
    rpcKey: string;
    gpuKey: string;
    defaultRepresentative: string;
}

export interface ConfigValidationResult {
    isValid: boolean;
    errors: string[];
    warnings: string[];
}

class GlobalConfig {
    private static instance: GlobalConfig;
    private config: NanoConfig;
    private initialized: boolean = false;

    private constructor() {
        this.config = {
            rpcUrl: process.env.NANO_RPC_URL || DEFAULT_RPC_URL,
            rpcKey: process.env.NANO_RPC_KEY || DEFAULT_RPC_KEY,
            gpuKey: process.env.NANO_GPU_KEY || DEFAULT_RPC_KEY,
            defaultRepresentative: process.env.NANO_DEFAULT_REPRESENTATIVE || DEFAULT_REPRESENTATIVE
        };
    }

    public static getInstance(): GlobalConfig {
        if (!GlobalConfig.instance) {
            GlobalConfig.instance = new GlobalConfig();
        }
        return GlobalConfig.instance;
    }

    public getNanoConfig(): NanoConfig {
        if (!this.initialized) {
            throw new Error('Configuration not initialized. Call initializeConfig() first.');
        }
        return { ...this.config };
    }

    public initializeConfig(config?: Partial<NanoConfig>): ConfigValidationResult {
        if (config) {
            this.config = {
                ...this.config,
                ...config
            };
        }

        const validation = this.validateConfig();
        if (validation.isValid) {
            this.initialized = true;
        }
        return validation;
    }

    public validateConfig(): ConfigValidationResult {
        const errors: string[] = [];
        const warnings: string[] = [];
        
        // Required parameters
        if (!this.config.rpcUrl) {
            errors.push('NANO_RPC_URL is required but not set');
        }
        if (!this.config.rpcKey) {
            errors.push('NANO_RPC_KEY is required but not set');
        }
        if (!this.config.gpuKey) {
            errors.push('NANO_GPU_KEY is required but not set');
        }

        // Optional parameters with defaults
        if (!this.config.defaultRepresentative) {
            this.config.defaultRepresentative = DEFAULT_REPRESENTATIVE;
            warnings.push('Using default representative address');
        }

        // URL format validation
        try {
            new URL(this.config.rpcUrl);
        } catch {
            errors.push('NANO_RPC_URL must be a valid URL');
        }

        return {
            isValid: errors.length === 0,
            errors,
            warnings
        };
    }

    public static generateEnvTemplate(): void {
        const template = `# NANO Configuration
# Required Parameters
NANO_RPC_URL=https://rpc.nano.to/     # Required: URL of the NANO RPC server
NANO_RPC_KEY=your-rpc-key-here        # Required: Your RPC authentication key
NANO_GPU_KEY=your-gpu-key-here        # Required: Your GPU service key for work generation

# Optional Parameters
# To choose a different representative, visit: https://nanexplorer.com/nano/representatives
# Select a representative with good uptime and reasonable voting weight
NANO_DEFAULT_REPRESENTATIVE=${DEFAULT_REPRESENTATIVE}  # Optional: Default representative for new accounts
`;

        const envPath = path.join(process.cwd(), '.env.example');
        fs.writeFileSync(envPath, template);
    }

    public getConfigStatus(): string {
        const validation = this.validateConfig();
        let status = 'Configuration Status:\n';
        
        if (validation.errors.length > 0) {
            status += '\nErrors:\n' + validation.errors.map(err => `- ${err}`).join('\n');
        }
        
        if (validation.warnings.length > 0) {
            status += '\nWarnings:\n' + validation.warnings.map(warn => `- ${warn}`).join('\n');
        }

        if (validation.isValid) {
            status += '\nConfiguration is valid and ready to use.';
        }

        return status;
    }
}

export const config = GlobalConfig.getInstance();
export default GlobalConfig; 