import * as fs from 'fs';
import { promises as pfs } from 'fs';
import { INPUT_SYSTEM_PROMPT_FILE, MODEL_PROVIDER } from './common.js';

export let CONFIG = {}; // Make CONFIG exportable
export let PROMPT_LOG_FILENAME = ''; // Make PROMPT_LOG_FILENAME exportable

const ALL_MODEL_PROVIDERS = Object.values(MODEL_PROVIDER);

function normalizeConfiguredProviders(config) {
    const fallbackProvider = MODEL_PROVIDER.GEMINI_CLI;
    const dedupedProviders = [];

    const addProvider = (value) => {
        if (typeof value !== 'string') {
            return;
        }
        const trimmed = value.trim();
        if (!trimmed) {
            return;
        }
        const matched = ALL_MODEL_PROVIDERS.find((provider) => provider.toLowerCase() === trimmed.toLowerCase());
        if (!matched) {
            console.warn(`[Config Warning] Unknown model provider '${trimmed}'. This entry will be ignored.`);
            return;
        }
        if (!dedupedProviders.includes(matched)) {
            dedupedProviders.push(matched);
        }
    };

    const rawValue = config.MODEL_PROVIDER;
    if (Array.isArray(rawValue)) {
        rawValue.forEach((entry) => addProvider(typeof entry === 'string' ? entry : String(entry)));
    } else if (typeof rawValue === 'string') {
        rawValue.split(',').forEach(addProvider);
    } else if (rawValue != null) {
        addProvider(String(rawValue));
    }

    if (dedupedProviders.length === 0) {
        dedupedProviders.push(fallbackProvider);
    }

    config.DEFAULT_MODEL_PROVIDERS = dedupedProviders;
    config.MODEL_PROVIDER = dedupedProviders[0];
}

/**
 * Initializes the server configuration from config.json and command-line arguments.
 * @param {string[]} args - Command-line arguments.
 * @param {string} [configFilePath='configs/config.json'] - Path to the configuration file.
 * @returns {Object} The initialized configuration object.
 */
export async function initializeConfig(args = process.argv.slice(2), configFilePath = 'configs/config.json') {
    let currentConfig = {};

    try {
        const configData = fs.readFileSync(configFilePath, 'utf8');
        currentConfig = JSON.parse(configData);
        console.log('[Config] Loaded configuration from configs/config.json');
    } catch (error) {
        console.error('[Config Error] Failed to load configs/config.json:', error.message);
        // Fallback to default values if config.json is not found or invalid
        currentConfig = {
            REQUIRED_API_KEY: "123456",
            SERVER_PORT: 3000,
            HOST: '0.0.0.0',
            MODEL_PROVIDER: MODEL_PROVIDER.GEMINI_CLI,
            OPENAI_API_KEY: null,
            OPENAI_BASE_URL: null,
            CLAUDE_API_KEY: null,
            CLAUDE_BASE_URL: null,
            GEMINI_OAUTH_CREDS_BASE64: null,
            GEMINI_OAUTH_CREDS_FILE_PATH: null,
            KIRO_OAUTH_CREDS_BASE64: null,
            KIRO_OAUTH_CREDS_FILE_PATH: null,
            QWEN_OAUTH_CREDS_FILE_PATH: null,
            PROJECT_ID: null,
            // Provider URLs
            QWEN_BASE_URL: null,
            QWEN_OAUTH_BASE_URL: null,
            GEMINI_BASE_URL: null,
            ANTIGRAVITY_BASE_URL_DAILY: null,
            ANTIGRAVITY_BASE_URL_AUTOPUSH: null,
            KIRO_REFRESH_URL: null,
            KIRO_REFRESH_IDC_URL: null,
            KIRO_BASE_URL: null,
            SYSTEM_PROMPT_FILE_PATH: INPUT_SYSTEM_PROMPT_FILE, // Default value
            SYSTEM_PROMPT_MODE: 'append',
            PROMPT_LOG_BASE_NAME: "prompt_log",
            PROMPT_LOG_MODE: "none",
            REQUEST_MAX_RETRIES: 3,
            REQUEST_BASE_DELAY: 1000,
            CRON_NEAR_MINUTES: 15,
            CRON_REFRESH_TOKEN: false,
            PROVIDER_POOLS_FILE_PATH: null, // 新增号池配置文件路径
            MAX_ERROR_COUNT: 3, // 提供商最大错误次数
            providerFallbackChain: {} // 跨类型 Fallback 链配置
        };
        console.log('[Config] Using default configuration.');
    }

    // Parse command-line arguments
    for (let i = 0; i < args.length; i++) {
        if (args[i] === '--api-key') {
            if (i + 1 < args.length) {
                currentConfig.REQUIRED_API_KEY = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --api-key flag requires a value.`);
            }
        } else if (args[i] === '--log-prompts') {
            if (i + 1 < args.length) {
                const mode = args[i + 1];
                if (mode === 'console' || mode === 'file') {
                    currentConfig.PROMPT_LOG_MODE = mode;
                } else {
                    console.warn(`[Config Warning] Invalid mode for --log-prompts. Expected 'console' or 'file'. Prompt logging is disabled.`);
                }
                i++;
            } else {
                console.warn(`[Config Warning] --log-prompts flag requires a value.`);
            }
        } else if (args[i] === '--port') {
            if (i + 1 < args.length) {
                currentConfig.SERVER_PORT = parseInt(args[i + 1], 10);
                i++;
            } else {
                console.warn(`[Config Warning] --port flag requires a value.`);
            }
        } else if (args[i] === '--model-provider') {
            if (i + 1 < args.length) {
                currentConfig.MODEL_PROVIDER = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --model-provider flag requires a value.`);
            }
        } else if (args[i] === '--openai-api-key') {
            if (i + 1 < args.length) {
                currentConfig.OPENAI_API_KEY = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --openai-api-key flag requires a value.`);
            }
        } else if (args[i] === '--openai-base-url') {
            if (i + 1 < args.length) {
                currentConfig.OPENAI_BASE_URL = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --openai-base-url flag requires a value.`);
            }
        } else if (args[i] === '--claude-api-key') {
            if (i + 1 < args.length) {
                currentConfig.CLAUDE_API_KEY = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --claude-api-key flag requires a value.`);
            }
        } else if (args[i] === '--claude-base-url') {
            if (i + 1 < args.length) {
                currentConfig.CLAUDE_BASE_URL = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --claude-base-url flag requires a value.`);
            }
        }
        // Provider URL arguments
        else if (args[i] === '--qwen-base-url') {
            if (i + 1 < args.length) {
                currentConfig.QWEN_BASE_URL = args[i + 1];
                i++;
            }
        } else if (args[i] === '--qwen-oauth-base-url') {
            if (i + 1 < args.length) {
                currentConfig.QWEN_OAUTH_BASE_URL = args[i + 1];
                i++;
            }
        } else if (args[i] === '--gemini-base-url') {
            if (i + 1 < args.length) {
                currentConfig.GEMINI_BASE_URL = args[i + 1];
                i++;
            }
        } else if (args[i] === '--antigravity-base-url-daily') {
            if (i + 1 < args.length) {
                currentConfig.ANTIGRAVITY_BASE_URL_DAILY = args[i + 1];
                i++;
            }
        } else if (args[i] === '--antigravity-base-url-autopush') {
            if (i + 1 < args.length) {
                currentConfig.ANTIGRAVITY_BASE_URL_AUTOPUSH = args[i + 1];
                i++;
            }
        } else if (args[i] === '--kiro-refresh-url') {
            if (i + 1 < args.length) {
                currentConfig.KIRO_REFRESH_URL = args[i + 1];
                i++;
            }
        } else if (args[i] === '--kiro-refresh-idc-url') {
            if (i + 1 < args.length) {
                currentConfig.KIRO_REFRESH_IDC_URL = args[i + 1];
                i++;
            }
        } else if (args[i] === '--kiro-base-url') {
            if (i + 1 < args.length) {
                currentConfig.KIRO_BASE_URL = args[i + 1];
                i++;
            }
        }
        // Gemini-specific arguments
        else if (args[i] === '--gemini-oauth-creds-base64') {
            if (i + 1 < args.length) {
                currentConfig.GEMINI_OAUTH_CREDS_BASE64 = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --gemini-oauth-creds-base64 flag requires a value.`);
            }
        } else if (args[i] === '--gemini-oauth-creds-file') {
            if (i + 1 < args.length) {
                currentConfig.GEMINI_OAUTH_CREDS_FILE_PATH = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --gemini-oauth-creds-file flag requires a value.`);
            }
        } else if (args[i] === '--project-id') {
            if (i + 1 < args.length) {
                currentConfig.PROJECT_ID = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --project-id flag requires a value.`);
            }
        } else if (args[i] === '--system-prompt-file') {
            if (i + 1 < args.length) {
                currentConfig.SYSTEM_PROMPT_FILE_PATH = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --system-prompt-file flag requires a value.`);
            }
        } else if (args[i] === '--system-prompt-mode') {
            if (i + 1 < args.length) {
                const mode = args[i + 1];
                if (mode === 'overwrite' || mode === 'append') {
                    currentConfig.SYSTEM_PROMPT_MODE = mode;
                } else {
                    console.warn(`[Config Warning] Invalid mode for --system-prompt-mode. Expected 'overwrite' or 'append'. Using default 'overwrite'.`);
                }
                i++;
            } else {
                console.warn(`[Config Warning] --system-prompt-mode flag requires a value.`);
            }
        } else if (args[i] === '--host') {
            if (i + 1 < args.length) {
                currentConfig.HOST = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --host flag requires a value.`);
            }
        } else if (args[i] === '--prompt-log-base-name') {
            if (i + 1 < args.length) {
                currentConfig.PROMPT_LOG_BASE_NAME = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --prompt-log-base-name flag requires a value.`);
            }
        } else if (args[i] === '--kiro-oauth-creds-base64') {
            if (i + 1 < args.length) {
                currentConfig.KIRO_OAUTH_CREDS_BASE64 = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --kiro-oauth-creds-base64 flag requires a value.`);
            }
        } else if (args[i] === '--kiro-oauth-creds-file') {
            if (i + 1 < args.length) {
                currentConfig.KIRO_OAUTH_CREDS_FILE_PATH = args[i + 1];
                i++;
            } else {
               console.warn(`[Config Warning] --kiro-oauth-creds-file flag requires a value.`);
           }
       } else if (args[i] === '--qwen-oauth-creds-file') {
           if (i + 1 < args.length) {
               currentConfig.QWEN_OAUTH_CREDS_FILE_PATH = args[i + 1];
               i++;
           } else {
               console.warn(`[Config Warning] --qwen-oauth-creds-file flag requires a value.`);
           }
       } else if (args[i] === '--cron-near-minutes') {
            if (i + 1 < args.length) {
                currentConfig.CRON_NEAR_MINUTES = parseInt(args[i + 1], 10);
                i++;
            } else {
                console.warn(`[Config Warning] --cron-near-minutes flag requires a value.`);
            }
        } else if (args[i] === '--cron-refresh-token') {
            if (i + 1 < args.length) {
                currentConfig.CRON_REFRESH_TOKEN = args[i + 1].toLowerCase() === 'true';
                i++;
            } else {
                console.warn(`[Config Warning] --cron-refresh-token flag requires a value.`);
            }
        } else if (args[i] === '--provider-pools-file') {
            if (i + 1 < args.length) {
                currentConfig.PROVIDER_POOLS_FILE_PATH = args[i + 1];
                i++;
            } else {
                console.warn(`[Config Warning] --provider-pools-file flag requires a value.`);
            }
        } else if (args[i] === '--max-error-count') {
            if (i + 1 < args.length) {
                currentConfig.MAX_ERROR_COUNT = parseInt(args[i + 1], 10);
                i++;
            } else {
                console.warn(`[Config Warning] --max-error-count flag requires a value.`);
            }
        }
    }

    normalizeConfiguredProviders(currentConfig);

    if (!currentConfig.SYSTEM_PROMPT_FILE_PATH) {
        currentConfig.SYSTEM_PROMPT_FILE_PATH = INPUT_SYSTEM_PROMPT_FILE;
    }
    currentConfig.SYSTEM_PROMPT_CONTENT = await getSystemPromptFileContent(currentConfig.SYSTEM_PROMPT_FILE_PATH);

    // 加载号池配置
    if (!currentConfig.PROVIDER_POOLS_FILE_PATH) {
        currentConfig.PROVIDER_POOLS_FILE_PATH = 'configs/provider_pools.json';
    }
    if (currentConfig.PROVIDER_POOLS_FILE_PATH) {
        try {
            const poolsData = await pfs.readFile(currentConfig.PROVIDER_POOLS_FILE_PATH, 'utf8');
            currentConfig.providerPools = JSON.parse(poolsData);
            console.log(`[Config] Loaded provider pools from ${currentConfig.PROVIDER_POOLS_FILE_PATH}`);
        } catch (error) {
            console.error(`[Config Error] Failed to load provider pools from ${currentConfig.PROVIDER_POOLS_FILE_PATH}: ${error.message}`);
            currentConfig.providerPools = {};
        }
    } else {
        currentConfig.providerPools = {};
    }

    // Set PROMPT_LOG_FILENAME based on the determined config
    if (currentConfig.PROMPT_LOG_MODE === 'file') {
        const now = new Date();
        const pad = (num) => String(num).padStart(2, '0');
        const timestamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
        PROMPT_LOG_FILENAME = `${currentConfig.PROMPT_LOG_BASE_NAME}-${timestamp}.log`;
    } else {
        PROMPT_LOG_FILENAME = ''; // Clear if not logging to file
    }

    // Assign to the exported CONFIG
    Object.assign(CONFIG, currentConfig);
    return CONFIG;
}

/**
 * Gets system prompt content from the specified file path.
 * @param {string} filePath - Path to the system prompt file.
 * @returns {Promise<string|null>} File content, or null if the file does not exist, is empty, or an error occurs.
 */
export async function getSystemPromptFileContent(filePath) {
    try {
        await pfs.access(filePath, pfs.constants.F_OK);
    } catch (error) {
        if (error.code === 'ENOENT') {
            console.warn(`[System Prompt] Specified system prompt file not found: ${filePath}`);
        } else {
            console.error(`[System Prompt] Error accessing system prompt file ${filePath}: ${error.message}`);
        }
        return null;
    }

    try {
        const content = await pfs.readFile(filePath, 'utf8');
        if (!content.trim()) {
            return null;
        }
        console.log(`[System Prompt] Loaded system prompt from ${filePath}`);
        return content;
    } catch (error) {
        console.error(`[System Prompt] Error reading system prompt file ${filePath}: ${error.message}`);
        return null;
    }
}

/**
 * Logs provider-specific configuration details
 * @param {string} provider - The model provider
 * @param {Object} config - The configuration object
 */
export function logProviderSpecificDetails(provider, config) {
    switch (provider) {
        case MODEL_PROVIDER.OPENAI_CUSTOM:
            console.log(`  [openai-custom] API Key: ${config.OPENAI_API_KEY ? '******' : 'Not Set'}`);
            console.log(`  [openai-custom] Base URL: ${config.OPENAI_BASE_URL || 'Default'}`);
            break;
        case MODEL_PROVIDER.CLAUDE_CUSTOM:
            console.log(`  [claude-custom] API Key: ${config.CLAUDE_API_KEY ? '******' : 'Not Set'}`);
            console.log(`  [claude-custom] Base URL: ${config.CLAUDE_BASE_URL || 'Default'}`);
            break;
        case MODEL_PROVIDER.GEMINI_CLI:
            if (config.GEMINI_OAUTH_CREDS_FILE_PATH) {
                console.log(`  [gemini-cli-oauth] OAuth Creds File Path: ${config.GEMINI_OAUTH_CREDS_FILE_PATH}`);
            } else if (config.GEMINI_OAUTH_CREDS_BASE64) {
                console.log(`  [gemini-cli-oauth] OAuth Creds Source: Provided via Base64 string`);
            } else {
                console.log(`  [gemini-cli-oauth] OAuth Creds: Default discovery`);
            }
            // console.log(`  [gemini-cli-oauth] Project ID: ${config.PROJECT_ID || 'Auto-discovered'}`);
            break;
        case MODEL_PROVIDER.KIRO_API:
            if (config.KIRO_OAUTH_CREDS_FILE_PATH) {
                console.log(`  [claude-kiro-oauth] OAuth Creds File Path: ${config.KIRO_OAUTH_CREDS_FILE_PATH}`);
            } else if (config.KIRO_OAUTH_CREDS_BASE64) {
                console.log(`  [claude-kiro-oauth] OAuth Creds Source: Provided via Base64 string`);
            } else {
                console.log(`  [claude-kiro-oauth] OAuth Creds: Default`);
            }
            break;
        case MODEL_PROVIDER.QWEN_API:
            console.log(`  [openai-qwen-oauth] OAuth Creds File Path: ${config.QWEN_OAUTH_CREDS_FILE_PATH || 'Default'}`);
            break;
        default:
            console.log(`  [${provider}] Provider initialized.`);
    }
}

export { ALL_MODEL_PROVIDERS };
