import {readFile} from 'node:fs/promises';

export interface WorkerConfig {
    salesforceLoginUrl: string;
    salesforceClientId: string;
    salesforceUsername: string;
    salesforcePrivateKey: string;
    salesforceApiVersion: string;
    azureTenantId: string;
    azureClientId: string;
    azureClientSecret: string;
    graphSiteId: string;
    allowedObjects: string[];
    contentVersionRetentionMonths: number;
    attachmentRetentionMonths: number;
    deleteAfterArchive: boolean;
    workerId: string;
    concurrency: number;
    scanIntervalMs: number;
    tempDir: string;
    failureStateFile: string;
}

function required(name: string): string {
    const value = process.env[name]?.trim();
    if (!value) throw new Error(`Required environment variable ${name} is missing.`);
    return value;
}

function positiveInteger(name: string, defaultValue: number): number {
    const raw = process.env[name];
    if (!raw) return defaultValue;
    const value = Number.parseInt(raw, 10);
    if (!Number.isSafeInteger(value) || value <= 0)
        throw new Error(`${name} must be a positive integer.`);
    return value;
}

function booleanValue(name: string, defaultValue: boolean): boolean {
    const raw = process.env[name]?.trim().toLowerCase();
    if (!raw) return defaultValue;
    if (raw === 'true') return true;
    if (raw === 'false') return false;
    throw new Error(`${name} must be true or false.`);
}

export async function loadConfig(): Promise<WorkerConfig> {
    const salesforcePrivateKey = await readFile(required('SALESFORCE_PRIVATE_KEY_FILE'), 'utf8');
    const allowedObjects = (
        process.env.ALLOWED_OBJECTS ?? 'Case,Opportunity,Account,Quote,rdcc__ReedProject__c'
    )
        .split(',')
        .map((value) => value.trim())
        .filter(Boolean);
    if (allowedObjects.length === 0)
        throw new Error('ALLOWED_OBJECTS must contain at least one API name.');

    return {
        salesforceLoginUrl: (
            process.env.SALESFORCE_LOGIN_URL ?? 'https://login.salesforce.com'
        ).replace(/\/$/, ''),
        salesforceClientId: required('SALESFORCE_CLIENT_ID'),
        salesforceUsername: required('SALESFORCE_USERNAME'),
        salesforcePrivateKey,
        salesforceApiVersion: process.env.SALESFORCE_API_VERSION?.trim() || '63.0',
        azureTenantId: required('AZURE_TENANT_ID'),
        azureClientId: required('AZURE_CLIENT_ID'),
        azureClientSecret: required('AZURE_CLIENT_SECRET'),
        graphSiteId: required('GRAPH_SITE_ID'),
        allowedObjects,
        contentVersionRetentionMonths: positiveInteger('CONTENT_VERSION_RETENTION_MONTHS', 7),
        attachmentRetentionMonths: positiveInteger('ATTACHMENT_RETENTION_MONTHS', 6),
        deleteAfterArchive: booleanValue('DELETE_AFTER_ARCHIVE', false),
        workerId: process.env.WORKER_ID?.trim() || `sharepoint-worker-${process.pid}`,
        concurrency: positiveInteger('WORKER_CONCURRENCY', 2),
        scanIntervalMs: positiveInteger('SCAN_INTERVAL_MS', 900_000),
        tempDir: process.env.TEMP_DIR?.trim() || '/var/lib/sharepoint-archive-worker/tmp',
        failureStateFile:
            process.env.FAILURE_STATE_FILE?.trim() ||
            '/var/lib/sharepoint-archive-worker/failures.json',
    };
}
