import { getContainer } from '@bytelyst/cosmos';
import { config } from '../config/index.js';
import logger from '../utils/logger.js';
import { getLegacySupabaseClient } from './legacySupabaseClient.js';
import type { UserConfig } from './tradingUserTypes.js';

const USER_PROFILE_CONTAINER = 'trading_users';

interface TradingUserDocument extends UserConfig {
    id: string;
    productId: string;
    type: 'trading_user';
}

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

function normalizeUser(row: Partial<UserConfig> | null | undefined): UserConfig | null {
    const userId = String(row?.user_id || '').trim();
    if (!userId) {
        return null;
    }

    return {
        user_id: userId,
        first_name: String(row?.first_name || ''),
        last_name: String(row?.last_name || ''),
        email: String(row?.email || ''),
        FMP_API_KEY: String(row?.FMP_API_KEY || ''),
        ALPACA_API_KEY: String(row?.ALPACA_API_KEY || ''),
        ALPACA_SECRET_KEY: String(row?.ALPACA_SECRET_KEY || ''),
        REAL_ALPACA_API_KEY: String(row?.REAL_ALPACA_API_KEY || ''),
        REAL_ALPACA_SECRET_KEY: String(row?.REAL_ALPACA_SECRET_KEY || ''),
        role: String(row?.role || 'member'),
        trade_enable: Boolean(row?.trade_enable),
        drop_threshold_for_buy: Number(row?.drop_threshold_for_buy || 0),
        gain_threshold_for_sell: Number(row?.gain_threshold_for_sell || 0),
        market_poll_interval_in_seconds: Number(row?.market_poll_interval_in_seconds || 0),
    };
}

function mergeUsers(primary: Partial<UserConfig> | null | undefined, fallback: Partial<UserConfig> | null | undefined): UserConfig | null {
    const userId = String(primary?.user_id || fallback?.user_id || '').trim();
    if (!userId) {
        return null;
    }

    const take = (...values: Array<unknown>): string => {
        for (const value of values) {
            const normalized = String(value || '').trim();
            if (normalized) return normalized;
        }
        return '';
    };

    const takeNumber = (...values: Array<unknown>): number => {
        for (const value of values) {
            if (value === null || value === undefined || value === '') continue;
            const normalized = Number(value);
            if (Number.isFinite(normalized)) return normalized;
        }
        return 0;
    };

    return {
        user_id: userId,
        first_name: take(primary?.first_name, fallback?.first_name),
        last_name: take(primary?.last_name, fallback?.last_name),
        email: take(primary?.email, fallback?.email),
        FMP_API_KEY: take(primary?.FMP_API_KEY, fallback?.FMP_API_KEY),
        ALPACA_API_KEY: take(primary?.ALPACA_API_KEY, fallback?.ALPACA_API_KEY),
        ALPACA_SECRET_KEY: take(primary?.ALPACA_SECRET_KEY, fallback?.ALPACA_SECRET_KEY),
        REAL_ALPACA_API_KEY: take(primary?.REAL_ALPACA_API_KEY, fallback?.REAL_ALPACA_API_KEY),
        REAL_ALPACA_SECRET_KEY: take(primary?.REAL_ALPACA_SECRET_KEY, fallback?.REAL_ALPACA_SECRET_KEY),
        role: take(primary?.role, fallback?.role, 'member'),
        trade_enable: Boolean(primary?.trade_enable ?? fallback?.trade_enable ?? true),
        drop_threshold_for_buy: takeNumber(primary?.drop_threshold_for_buy, fallback?.drop_threshold_for_buy, 0),
        gain_threshold_for_sell: takeNumber(primary?.gain_threshold_for_sell, fallback?.gain_threshold_for_sell, 0),
        market_poll_interval_in_seconds: takeNumber(primary?.market_poll_interval_in_seconds, fallback?.market_poll_interval_in_seconds, 0),
    };
}

export async function listActiveTradingUsers(): Promise<UserConfig[]> {
    if (isCosmosConfigured()) {
        try {
            const container = getContainer(USER_PROFILE_CONTAINER);
            const { resources } = await container.items.query<TradingUserDocument>({
                query: 'SELECT * FROM c WHERE c.productId = @productId AND c.type = @type AND c.trade_enable = true',
                parameters: [
                    { name: '@productId', value: config.PRODUCT_ID },
                    { name: '@type', value: 'trading_user' },
                ],
            }).fetchAll();

            const normalized = resources
                .map((row) => normalizeUser(row as UserConfig))
                .filter((user): user is UserConfig => Boolean(user));
            if (normalized.length > 0) {
                const client = getLegacySupabaseClient();
                if (!client) {
                    return normalized;
                }

                try {
                    const { data, error } = await client
                        .from('users')
                        .select('*')
                        .eq('trade_enable', true);

                    if (error || !Array.isArray(data) || data.length === 0) {
                        return normalized;
                    }

                    const legacyById = new Map(
                        data
                            .map((row) => normalizeUser(row as UserConfig))
                            .filter((user): user is UserConfig => Boolean(user))
                            .map((user) => [user.user_id, user])
                    );

                    return normalized.map((user) => mergeUsers(user, legacyById.get(user.user_id)) || user);
                } catch (error) {
                    logger.warn(`[Users] Legacy user merge failed: ${error instanceof Error ? error.message : 'unknown error'}`);
                    return normalized;
                }
            }
        } catch (error) {
            logger.warn(`[Users] Cosmos active trading user lookup failed: ${error instanceof Error ? error.message : 'unknown error'}`);
            return [];
        }
    }

    const client = getLegacySupabaseClient();
    if (!client) {
        return [];
    }

    try {
        const { data, error } = await client
            .from('users')
            .select('*')
            .eq('trade_enable', true);

        if (error || !Array.isArray(data)) {
            return [];
        }

        const normalized = data
            .map((row) => normalizeUser(row as UserConfig))
            .filter((user): user is UserConfig => Boolean(user));
        if (isCosmosConfigured() && normalized.length > 0) {
            try {
                const container = getContainer(USER_PROFILE_CONTAINER);
                await Promise.all(normalized.map((user) => container.items.upsert({
                    ...user,
                    id: user.user_id,
                    productId: config.PRODUCT_ID,
                    type: 'trading_user',
                } as TradingUserDocument)));
            } catch (error) {
                logger.warn(`[Users] Cosmos user seed failed: ${error instanceof Error ? error.message : 'unknown error'}`);
            }
        }
        return normalized;
    } catch (error) {
        logger.warn(`[Users] Active trading user lookup failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return [];
    }
}
