import 'dotenv/config';
import { config, loadDynamicConfig } from '../src/config/index.js';
import { reconciliationSubTagRepairService } from '../src/services/reconciliationSubTagRepairService.js';
import { supabaseService } from '../src/services/SupabaseService.js';

type CliOptions = {
    apply: boolean;
    profileIds: Set<string>;
    lookbackHours?: number;
    maxUpdatesPerProfile?: number;
    ignoreFeatureFlag: boolean;
};

type ProfileSummary = {
    profileId: string;
    userId: string;
    attempted: boolean;
    skippedReason?: string;
    unsupported?: boolean;
    dryRun: boolean;
    scannedRows: number;
    eligibleRows: number;
    updatedRows: number;
    skippedNoProfile: number;
    skippedNoTrade: number;
    skippedTagDisabled: number;
    skippedAlreadyTagged: number;
};

const parseOptions = (argv: string[]): CliOptions => {
    const options: CliOptions = {
        apply: false,
        profileIds: new Set<string>(),
        ignoreFeatureFlag: false
    };

    for (const arg of argv) {
        if (arg === '--apply') {
            options.apply = true;
            continue;
        }
        if (arg === '--ignore-feature-flag') {
            options.ignoreFeatureFlag = true;
            continue;
        }
        if (arg.startsWith('--profile=')) {
            const profileId = String(arg.slice('--profile='.length) || '').trim();
            if (profileId) options.profileIds.add(profileId);
            continue;
        }
        if (arg.startsWith('--lookback-hours=')) {
            const parsed = Number(arg.slice('--lookback-hours='.length));
            if (Number.isFinite(parsed) && parsed > 0) options.lookbackHours = Math.floor(parsed);
            continue;
        }
        if (arg.startsWith('--max-updates-per-profile=')) {
            const parsed = Number(arg.slice('--max-updates-per-profile='.length));
            if (Number.isFinite(parsed) && parsed > 0) options.maxUpdatesPerProfile = Math.floor(parsed);
            continue;
        }
    }

    return options;
};

const normalizeProfileIds = (profileIds: Set<string>): string[] => {
    return Array.from(profileIds)
        .map((value) => String(value || '').trim())
        .filter(Boolean);
};

const run = async (): Promise<void> => {
    const options = parseOptions(process.argv.slice(2));
    await loadDynamicConfig(supabaseService);

    const originalEnabled = config.ENABLE_RECON_SUBTAG_REPAIR;
    const originalDryRun = config.RECON_SUBTAG_REPAIR_DRY_RUN;
    const originalLookback = config.RECON_SUBTAG_REPAIR_LOOKBACK_HOURS;
    const originalMaxUpdates = config.RECON_SUBTAG_REPAIR_MAX_UPDATES_PER_PROFILE;

    if (!config.ENABLE_RECON_SUBTAG_REPAIR && !options.ignoreFeatureFlag) {
        throw new Error('ENABLE_RECON_SUBTAG_REPAIR=false. Enable it or pass --ignore-feature-flag for one-shot run.');
    }

    if (options.ignoreFeatureFlag) {
        config.ENABLE_RECON_SUBTAG_REPAIR = true;
    }
    config.RECON_SUBTAG_REPAIR_DRY_RUN = !options.apply;
    if (Number.isFinite(options.lookbackHours)) {
        config.RECON_SUBTAG_REPAIR_LOOKBACK_HOURS = Number(options.lookbackHours);
    }
    if (Number.isFinite(options.maxUpdatesPerProfile)) {
        config.RECON_SUBTAG_REPAIR_MAX_UPDATES_PER_PROFILE = Number(options.maxUpdatesPerProfile);
    }

    const effectiveDryRun = config.RECON_SUBTAG_REPAIR_DRY_RUN;
    const effectiveLookback = config.RECON_SUBTAG_REPAIR_LOOKBACK_HOURS;
    const effectiveMaxUpdates = config.RECON_SUBTAG_REPAIR_MAX_UPDATES_PER_PROFILE;

    const profiles = await supabaseService.getActiveProfiles();
    const selectedProfiles = (profiles || []).filter((profile: any) => {
        const profileId = String(profile?.id || '').trim();
        if (!profileId) return false;
        if (options.profileIds.size === 0) return true;
        return options.profileIds.has(profileId);
    });

    const results: ProfileSummary[] = [];
    for (const profile of selectedProfiles) {
        const profileId = String(profile?.id || '').trim();
        const userId = String(profile?.user_id || '').trim();
        if (!profileId || !userId) continue;

        const result = await reconciliationSubTagRepairService.runProfile({
            profileId,
            userId
        });
        results.push({
            profileId,
            userId,
            attempted: result.attempted,
            skippedReason: result.skippedReason,
            unsupported: result.unsupported,
            dryRun: result.dryRun,
            scannedRows: result.scannedRows,
            eligibleRows: result.eligibleRows,
            updatedRows: result.updatedRows,
            skippedNoProfile: result.skippedNoProfile,
            skippedNoTrade: result.skippedNoTrade,
            skippedTagDisabled: result.skippedTagDisabled,
            skippedAlreadyTagged: result.skippedAlreadyTagged
        });
    }

    config.ENABLE_RECON_SUBTAG_REPAIR = originalEnabled;
    config.RECON_SUBTAG_REPAIR_DRY_RUN = originalDryRun;
    config.RECON_SUBTAG_REPAIR_LOOKBACK_HOURS = originalLookback;
    config.RECON_SUBTAG_REPAIR_MAX_UPDATES_PER_PROFILE = originalMaxUpdates;

    const aggregate = results.reduce((acc, row) => {
        if (row.attempted) acc.attemptedProfiles += 1;
        if (!row.attempted && row.skippedReason) {
            acc.skippedProfiles[row.skippedReason] = (acc.skippedProfiles[row.skippedReason] || 0) + 1;
        }
        if (row.unsupported) acc.unsupportedProfiles += 1;
        acc.scannedRows += row.scannedRows;
        acc.eligibleRows += row.eligibleRows;
        acc.updatedRows += row.updatedRows;
        acc.skippedNoProfile += row.skippedNoProfile;
        acc.skippedNoTrade += row.skippedNoTrade;
        acc.skippedTagDisabled += row.skippedTagDisabled;
        acc.skippedAlreadyTagged += row.skippedAlreadyTagged;
        return acc;
    }, {
        attemptedProfiles: 0,
        skippedProfiles: {} as Record<string, number>,
        unsupportedProfiles: 0,
        scannedRows: 0,
        eligibleRows: 0,
        updatedRows: 0,
        skippedNoProfile: 0,
        skippedNoTrade: 0,
        skippedTagDisabled: 0,
        skippedAlreadyTagged: 0
    });

    console.log(JSON.stringify({
        mode: options.apply ? 'apply' : 'dry-run',
        profileFilter: normalizeProfileIds(options.profileIds),
        ignoreFeatureFlag: options.ignoreFeatureFlag,
        configuredLookbackHours: effectiveLookback,
        configuredMaxUpdatesPerProfile: effectiveMaxUpdates,
        dryRunFlagUsed: effectiveDryRun,
        aggregate,
        results
    }, null, 2));
};

run().catch((error) => {
    const message = error instanceof Error ? error.message : String(error);
    console.error(JSON.stringify({ error: message }, null, 2));
    process.exit(1);
});
