/**
 * Environment File Manager
 * 
 * Handles reading and writing .env configuration files.
 * Provides type-safe access to environment variables.
 */

import * as fs from 'fs';
import * as path from 'path';

export interface EnvConfig {
    LLM_BACKEND?: string;
    OLLAMA_HOST?: string;
    OLLAMA_MODEL?: string;
    OLLAMA_EMBEDDING_MODEL?: string;
    OPENAI_API_KEY?: string;
    OPENAI_MODEL?: string;
    OPENAI_EMBEDDING_MODEL?: string;
    DATA_DIR?: string;
    LIGHTRAG_DIR?: string;
    [key: string]: string | undefined;
}

const DEFAULT_ENV: EnvConfig = {
    LLM_BACKEND: 'ollama',
    OLLAMA_HOST: 'http://localhost:11434',
    OLLAMA_MODEL: 'qwen2.5:7b',
    OLLAMA_EMBEDDING_MODEL: 'nomic-embed-text',
    OPENAI_API_KEY: '',
    OPENAI_MODEL: 'gpt-4o-mini',
    OPENAI_EMBEDDING_MODEL: 'text-embedding-3-small',
    DATA_DIR: './data',
    LIGHTRAG_DIR: './data/lightrag'
};

export class EnvManager {
    private workspaceRoot: string;
    private envPath: string;
    
    constructor(workspaceRoot: string) {
        this.workspaceRoot = workspaceRoot;
        this.envPath = path.join(workspaceRoot, '.env');
    }
    
    /**
     * Get the path to the .env file
     */
    getEnvPath(): string {
        return this.envPath;
    }
    
    /**
     * Check if .env file exists
     */
    exists(): boolean {
        return fs.existsSync(this.envPath);
    }
    
    /**
     * Read and parse .env file
     */
    async readEnv(): Promise<EnvConfig> {
        if (!this.exists()) {
            return { ...DEFAULT_ENV };
        }
        
        try {
            const content = fs.readFileSync(this.envPath, 'utf-8');
            return this.parseEnvContent(content);
        } catch (error) {
            console.error('Error reading .env file:', error);
            return { ...DEFAULT_ENV };
        }
    }
    
    /**
     * Parse .env content to object
     */
    private parseEnvContent(content: string): EnvConfig {
        const env: EnvConfig = { ...DEFAULT_ENV };
        const lines = content.split('\n');
        
        for (const line of lines) {
            const trimmed = line.trim();
            
            // Skip empty lines and comments
            if (!trimmed || trimmed.startsWith('#')) {
                continue;
            }
            
            const eqIndex = trimmed.indexOf('=');
            if (eqIndex > 0) {
                const key = trimmed.substring(0, eqIndex).trim();
                let value = trimmed.substring(eqIndex + 1).trim();
                
                // Remove quotes if present
                if ((value.startsWith('"') && value.endsWith('"')) ||
                    (value.startsWith("'") && value.endsWith("'"))) {
                    value = value.slice(1, -1);
                }
                
                env[key] = value;
            }
        }
        
        return env;
    }
    
    /**
     * Create default .env file
     */
    async createDefaultEnv(): Promise<void> {
        const content = this.generateEnvContent(DEFAULT_ENV);
        fs.writeFileSync(this.envPath, content, 'utf-8');
    }
    
    /**
     * Update a single environment variable
     */
    async updateEnv(key: string, value: string): Promise<void> {
        const env = await this.readEnv();
        env[key] = value;
        await this.writeEnv(env);
    }
    
    /**
     * Write entire env config to file
     */
    async writeEnv(env: EnvConfig): Promise<void> {
        const content = this.generateEnvContent(env);
        fs.writeFileSync(this.envPath, content, 'utf-8');
    }
    
    /**
     * Generate .env file content from config
     */
    private generateEnvContent(env: EnvConfig): string {
        const lines: string[] = [
            '# Asset-Aware MCP Configuration',
            '# Generated by VS Code Extension',
            '',
            '# ============================================',
            '# LLM Backend Selection',
            '# ============================================',
            '# Options: "ollama" (local) or "openai" (cloud)',
            `LLM_BACKEND=${env.LLM_BACKEND || 'ollama'}`,
            '',
            '# ============================================',
            '# Ollama Settings (for local LLM)',
            '# ============================================',
            `OLLAMA_HOST=${env.OLLAMA_HOST || 'http://localhost:11434'}`,
            `OLLAMA_MODEL=${env.OLLAMA_MODEL || 'qwen2.5:7b'}`,
            `OLLAMA_EMBEDDING_MODEL=${env.OLLAMA_EMBEDDING_MODEL || 'nomic-embed-text'}`,
            '',
            '# ============================================',
            '# OpenAI Settings (for cloud LLM)',
            '# ============================================',
            `OPENAI_API_KEY=${env.OPENAI_API_KEY || ''}`,
            `OPENAI_MODEL=${env.OPENAI_MODEL || 'gpt-4o-mini'}`,
            `OPENAI_EMBEDDING_MODEL=${env.OPENAI_EMBEDDING_MODEL || 'text-embedding-3-small'}`,
            '',
            '# ============================================',
            '# Storage Settings',
            '# ============================================',
            `DATA_DIR=${env.DATA_DIR || './data'}`,
            `LIGHTRAG_DIR=${env.LIGHTRAG_DIR || './data/lightrag'}`,
            ''
        ];
        
        return lines.join('\n');
    }
    
    /**
     * Get data directory path
     */
    getDataDir(): string {
        const env = this.readEnvSync();
        const dataDir = env.DATA_DIR || './data';
        return path.resolve(this.workspaceRoot, dataDir);
    }
    
    /**
     * Synchronous read for quick access
     */
    private readEnvSync(): EnvConfig {
        if (!this.exists()) {
            return { ...DEFAULT_ENV };
        }
        
        try {
            const content = fs.readFileSync(this.envPath, 'utf-8');
            return this.parseEnvContent(content);
        } catch {
            return { ...DEFAULT_ENV };
        }
    }
    
    /**
     * List ingested documents from data directory
     */
    listDocuments(): { id: string; path: string; manifestExists: boolean }[] {
        const dataDir = this.getDataDir();
        const documents: { id: string; path: string; manifestExists: boolean }[] = [];
        
        if (!fs.existsSync(dataDir)) {
            return documents;
        }
        
        try {
            const entries = fs.readdirSync(dataDir, { withFileTypes: true });
            
            for (const entry of entries) {
                if (entry.isDirectory() && entry.name.startsWith('doc_')) {
                    const docPath = path.join(dataDir, entry.name);
                    const manifestPath = path.join(docPath, 'manifest.json');
                    
                    documents.push({
                        id: entry.name,
                        path: docPath,
                        manifestExists: fs.existsSync(manifestPath)
                    });
                }
            }
        } catch (error) {
            console.error('Error listing documents:', error);
        }
        
        return documents;
    }
    
    /**
     * Read document manifest
     */
    readManifest(docId: string): object | null {
        const dataDir = this.getDataDir();
        const manifestPath = path.join(dataDir, docId, 'manifest.json');
        
        if (!fs.existsSync(manifestPath)) {
            return null;
        }
        
        try {
            const content = fs.readFileSync(manifestPath, 'utf-8');
            return JSON.parse(content);
        } catch {
            return null;
        }
    }
}
