/**
 * Cloudflare Domain Sync Manager
 *
 * Synchronizes Cloudflare DNS zones with the local Domain table.
 * Automatically imports zones and marks obsolete domains when zones are removed.
 */
import * as plugins from '../plugins.js';
import { logger } from '../logging.js';
import { getErrorMessage } from '../utils/error.js';
import { OneboxDatabase } from '../database/index.js';
export class CloudflareDomainSync {
    database;
    cloudflareAccount = null;
    constructor(database) {
        this.database = database;
    }
    /**
     * Initialize Cloudflare connection
     */
    async init() {
        try {
            const apiKey = await this.database.getSecretSetting('cloudflareToken');
            if (!apiKey) {
                logger.warn('Cloudflare API key not configured. Domain sync will be limited.');
                return;
            }
            this.cloudflareAccount = new plugins.cloudflare.CloudflareAccount(apiKey);
            logger.info('Cloudflare domain sync initialized');
        }
        catch (error) {
            logger.error(`Failed to initialize Cloudflare sync: ${getErrorMessage(error)}`);
            throw error;
        }
    }
    /**
     * Check if Cloudflare is configured
     */
    isConfigured() {
        return this.cloudflareAccount !== null;
    }
    /**
     * Sync all Cloudflare zones with Domain table
     */
    async syncZones() {
        if (!this.isConfigured()) {
            logger.warn('Cloudflare not configured, skipping zone sync');
            return;
        }
        try {
            logger.info('Starting Cloudflare zone synchronization...');
            // Fetch all zones from Cloudflare (v6+ API uses convenience.listZones())
            const zones = await this.cloudflareAccount.convenience.listZones();
            logger.info(`Found ${zones.length} Cloudflare zone(s)`);
            const now = Date.now();
            const syncedZoneIds = new Set();
            // Sync each zone to the Domain table
            for (const zone of zones) {
                try {
                    const domain = zone.name;
                    const zoneId = zone.id;
                    syncedZoneIds.add(zoneId);
                    // Check if domain already exists
                    const existingDomain = await this.database.getDomainByName(domain);
                    if (existingDomain) {
                        // Update existing domain
                        await this.database.updateDomain(existingDomain.id, {
                            dnsProvider: 'cloudflare',
                            cloudflareZoneId: zoneId,
                            isObsolete: false, // Re-activate if it was marked obsolete
                            updatedAt: now,
                        });
                        logger.debug(`Updated domain: ${domain}`);
                    }
                    else {
                        // Create new domain
                        await this.database.createDomain({
                            domain,
                            dnsProvider: 'cloudflare',
                            cloudflareZoneId: zoneId,
                            isObsolete: false,
                            defaultWildcard: true, // Default to wildcard certificates
                            createdAt: now,
                            updatedAt: now,
                        });
                        logger.info(`Added new domain from Cloudflare: ${domain}`);
                    }
                }
                catch (error) {
                    logger.error(`Failed to sync zone ${zone.name}: ${getErrorMessage(error)}`);
                }
            }
            // Mark domains as obsolete if their Cloudflare zones no longer exist
            await this.markObsoleteDomains(syncedZoneIds);
            logger.success(`Cloudflare zone sync completed: ${zones.length} zone(s) synced`);
        }
        catch (error) {
            logger.error(`Cloudflare zone sync failed: ${getErrorMessage(error)}`);
            throw error;
        }
    }
    /**
     * Mark domains as obsolete if their Cloudflare zones have been removed
     */
    async markObsoleteDomains(activeZoneIds) {
        try {
            // Get all domains managed by Cloudflare
            const cloudflareDomains = await this.database.getDomainsByProvider('cloudflare');
            let obsoleteCount = 0;
            for (const domain of cloudflareDomains) {
                // If domain has a Cloudflare zone ID but it's not in the active set, mark obsolete
                if (domain.cloudflareZoneId && !activeZoneIds.has(domain.cloudflareZoneId)) {
                    await this.database.updateDomain(domain.id, {
                        isObsolete: true,
                        updatedAt: Date.now(),
                    });
                    logger.warn(`Marked domain as obsolete (zone removed): ${domain.domain}`);
                    obsoleteCount++;
                }
            }
            if (obsoleteCount > 0) {
                logger.info(`Marked ${obsoleteCount} domain(s) as obsolete`);
            }
        }
        catch (error) {
            logger.error(`Failed to mark obsolete domains: ${getErrorMessage(error)}`);
        }
    }
    /**
     * Get sync status information
     */
    async getSyncStatus() {
        const allDomains = await this.database.getAllDomains();
        const cloudflareDomains = allDomains.filter(d => d.dnsProvider === 'cloudflare');
        const obsoleteDomains = allDomains.filter(d => d.isObsolete);
        return {
            configured: this.isConfigured(),
            totalDomains: allDomains.length,
            cloudflareDomains: cloudflareDomains.length,
            obsoleteDomains: obsoleteDomains.length,
        };
    }
}
//# sourceMappingURL=data:application/json;base64, 