import { getContainer } from '@bytelyst/cosmos';
import { config } from '../config/index.js';
import logger from '../utils/logger.js';
import type { supabaseService } from './SupabaseService.js';

export interface DynamicConfigEntry {
    key: string;
    value: string;
    description?: string;
    updated_at?: string;
}

interface DynamicConfigDocument extends DynamicConfigEntry {
    id: string;
    productId: string;
    updatedAt: string;
}

type LegacySupabaseService = typeof supabaseService;

const CONTAINER_NAME = 'dynamic_config';

function isCosmosConfigured(): boolean {
    return Boolean(config.COSMOS_ENDPOINT && config.COSMOS_KEY);
}

function normalizeEntry(entry: Partial<DynamicConfigEntry> | null | undefined): DynamicConfigEntry | null {
    const key = String(entry?.key || '').trim();
    if (!key) return null;
    return {
        key,
        value: String(entry?.value ?? ''),
        description: entry?.description ? String(entry.description) : '',
        updated_at: entry?.updated_at ? String(entry.updated_at) : undefined,
    };
}

async function listFromCosmos(): Promise<DynamicConfigEntry[]> {
    if (!isCosmosConfigured()) return [];
    const container = getContainer(CONTAINER_NAME);
    const { resources } = await container.items
        .query<DynamicConfigDocument>({
            query: 'SELECT * FROM c WHERE c.productId = @productId ORDER BY c.key',
            parameters: [{ name: '@productId', value: config.PRODUCT_ID }],
        })
        .fetchAll();

    return resources
        .map((resource) => normalizeEntry({
            key: resource.key,
            value: resource.value,
            description: resource.description,
            updated_at: resource.updatedAt,
        }))
        .filter((entry): entry is DynamicConfigEntry => Boolean(entry));
}

async function listFromSupabase(legacyService?: LegacySupabaseService): Promise<DynamicConfigEntry[]> {
    const client = legacyService?.getClient?.();
    if (!client) return [];

    try {
        const { data, error } = await client
            .from('bot_config')
            .select('*')
            .order('key');
        if (error || !Array.isArray(data)) {
            return [];
        }
        return data
            .map((row) => normalizeEntry(row as DynamicConfigEntry))
            .filter((entry): entry is DynamicConfigEntry => Boolean(entry));
    } catch (error) {
        logger.warn(`[DynamicConfig] Legacy Supabase read failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return [];
    }
}

async function mirrorToSupabase(entries: DynamicConfigEntry[], legacyService?: LegacySupabaseService): Promise<void> {
    const client = legacyService?.getClient?.();
    if (!client || entries.length === 0) return;

    try {
        const payload = entries.map((entry) => ({
            key: entry.key,
            value: entry.value,
            description: entry.description || '',
            updated_at: entry.updated_at || new Date().toISOString(),
        }));
        const { error } = await client
            .from('bot_config')
            .upsert(payload, { onConflict: 'key' });
        if (error) {
            logger.warn(`[DynamicConfig] Legacy Supabase mirror failed: ${error.message}`);
        }
    } catch (error) {
        logger.warn(`[DynamicConfig] Legacy Supabase mirror failed: ${error instanceof Error ? error.message : 'unknown error'}`);
    }
}

export async function listDynamicConfigEntries(legacyService?: LegacySupabaseService): Promise<DynamicConfigEntry[]> {
    try {
        const cosmosEntries = await listFromCosmos();
        if (cosmosEntries.length > 0) {
            return cosmosEntries;
        }
    } catch (error) {
        logger.warn(`[DynamicConfig] Cosmos read failed, falling back to legacy store: ${error instanceof Error ? error.message : 'unknown error'}`);
    }

    return listFromSupabase(legacyService);
}

export async function upsertDynamicConfigEntries(
    entries: DynamicConfigEntry[],
    legacyService?: LegacySupabaseService
): Promise<void> {
    const normalized = entries
        .map((entry) => normalizeEntry(entry))
        .filter((entry): entry is DynamicConfigEntry => Boolean(entry));

    if (normalized.length === 0) {
        return;
    }

    const now = new Date().toISOString();
    if (isCosmosConfigured()) {
        try {
            const container = getContainer(CONTAINER_NAME);
            await Promise.all(normalized.map((entry) => container.items.upsert<DynamicConfigDocument>({
                id: entry.key,
                productId: config.PRODUCT_ID,
                key: entry.key,
                value: entry.value,
                description: entry.description || '',
                updated_at: entry.updated_at || now,
                updatedAt: entry.updated_at || now,
            })));
        } catch (error) {
            logger.warn(`[DynamicConfig] Cosmos upsert failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        }
    }

    await mirrorToSupabase(normalized, legacyService);
}
