
import { supabase } from '@/integrations/supabase/client';
import { normalizeTransaction } from './coaNormalizationService';
import { validateTransactionAndAccounts } from './coaValidationService';
import { writeRoutingAudit } from './coaRoutingAuditLogger';

/**
 * Routing Engine Service
 */
export async function postFinancialTransaction({ transactionId, dryRun = false }) {
  try {
    const { data: trx, error: txError } = await supabase
      .from('financial_transactions')
      .select('*')
      .eq('id', transactionId)
      .single();

    if (txError || !trx) {
      throw new Error(`Transaction ${transactionId} not found.`);
    }

    if (trx.status === 'posted' && !dryRun) {
      throw new Error(`Transaction ${transactionId} is already posted.`);
    }

    const { normalizedType, normalizedCategoryKey, fundType } = await normalizeTransaction({
      transaction: trx,
      clientId: trx.client_id
    });

    let query = supabase
      .from('coa_mapping_rules')
      .select(`
        id, priority, description, debit_account_id, credit_account_id,
        debit_account:debit_account_id(*),
        credit_account:credit_account_id(*)
      `)
      .eq('client_id', trx.client_id)
      .eq('transaction_type', normalizedType)
      .eq('is_active', true)
      .order('priority', { ascending: false });

    const { data: rules, error: ruleError } = await query;
    if (ruleError) throw ruleError;

    let bestRule = null;
    if (rules && rules.length > 0) {
      bestRule = rules.find(r => r.category_key === normalizedCategoryKey && r.fund_type === fundType)
        || rules.find(r => r.category_key === normalizedCategoryKey && !r.fund_type)
        || rules.find(r => !r.category_key && r.fund_type === fundType)
        || rules.find(r => !r.category_key && !r.fund_type);
    }

    if (!bestRule) {
      const msg = `No active mapping rule found for type: ${normalizedType}, category: ${normalizedCategoryKey}`;
      if (!dryRun) {
        await writeRoutingAudit({
          transactionId, status: 'failed', errorMessage: msg, explanation: 'Rule resolution failed'
        });
        await supabase.from('financial_transactions').update({ status: 'failed' }).eq('id', transactionId);
      }
      return { success: false, error: msg, dryRun };
    }

    const debitAccount = bestRule.debit_account;
    const creditAccount = bestRule.credit_account;
    const { valid, errors } = validateTransactionAndAccounts({
      financialTransaction: trx,
      debitAccount,
      creditAccount
    });

    if (!valid) {
      const msg = `Validation failed: ${errors.join('; ')}`;
      if (!dryRun) {
        await writeRoutingAudit({
          transactionId, ruleId: bestRule.id, matchedRulePriority: bestRule.priority,
          status: 'failed', errorMessage: msg, explanation: 'Validation failed pre-posting'
        });
        await supabase.from('financial_transactions').update({ status: 'failed' }).eq('id', transactionId);
      }
      return { success: false, error: msg, dryRun, validationErrors: errors };
    }

    const glEntries = [
      {
        client_id: trx.client_id,
        unit_id: trx.unit_id,
        date: trx.transaction_date,
        description: trx.description || `Auto-posted ${normalizedType}`,
        amount: trx.amount,
        type: 'debit',
        chart_of_account_id: debitAccount.id,
        source_type: 'routing_engine',
        source_id: trx.id
      },
      {
        client_id: trx.client_id,
        unit_id: trx.unit_id,
        date: trx.transaction_date,
        description: trx.description || `Auto-posted ${normalizedType}`,
        amount: trx.amount,
        type: 'credit',
        chart_of_account_id: creditAccount.id,
        source_type: 'routing_engine',
        source_id: trx.id
      }
    ];

    const isOwnerImpact = ['owner_charge', 'owner_payment'].includes(normalizedType) && trx.unit_id;
    const ownerLedgerImpact = isOwnerImpact ? {
       client_id: trx.client_id,
       unit_id: trx.unit_id,
       post_date: trx.transaction_date,
       amount: normalizedType === 'owner_charge' ? trx.amount : -trx.amount,
       description: trx.description,
       source_type: normalizedType
    } : null;

    const explanation = `Matched rule ID ${bestRule.id} (Priority ${bestRule.priority}). Routing: Debit [${debitAccount.account_name}] -> Credit [${creditAccount.account_name}].`;

    if (dryRun) {
      return {
        success: true,
        dryRun: true,
        normalizedType,
        normalizedCategoryKey,
        fundType,
        bestRule,
        glEntries,
        ownerLedgerImpact,
        explanation
      };
    }

    const { error: glErr } = await supabase.from('journal_entries').insert(glEntries);
    if (glErr) throw new Error('GL Insertion failed: ' + glErr.message);

    if (ownerLedgerImpact) {
       await supabase.from('transactions').insert([{
         unit_id: ownerLedgerImpact.unit_id,
         amount: Math.abs(ownerLedgerImpact.amount),
         type: normalizedType === 'owner_charge' ? 'Charge' : 'Payment',
         description: ownerLedgerImpact.description,
         date: ownerLedgerImpact.post_date
       }]);
    }

    await supabase.from('financial_transactions').update({ status: 'posted' }).eq('id', transactionId);

    await writeRoutingAudit({
      transactionId,
      ruleId: bestRule.id,
      matchedRulePriority: bestRule.priority,
      debitAccountId: debitAccount.id,
      creditAccountId: creditAccount.id,
      explanation,
      status: 'success'
    });

    return { success: true, dryRun: false, explanation };

  } catch (err) {
    console.error("Routing Engine Error:", err);
    return { success: false, error: err.message, dryRun };
  }
}
