<?php
defined('BASEPATH') or exit('No direct script access allowed');

class Finance_sync_model extends MY_Model
{
    public function backfill_legacy_finance_bridge()
    {
        $this->sync_all_account_charts();
        $this->sync_all_category_charts();
        $this->sync_all_transaction_journals(false);
        $this->sync_all_transfer_journals(false);
        finance_report_model()->refresh_global_finance_rollup();
    }

    public function sync_account_by_id($account_id)
    {
        return $this->sync_account_chart_of_account($account_id);
    }

    public function sync_income_category_by_id($category_id)
    {
        return $this->sync_income_category_chart_of_account($category_id);
    }

    public function sync_expense_category_by_id($category_id)
    {
        return $this->sync_expense_category_chart_of_account($category_id);
    }

    public function sync_transaction_by_id($transactions_id)
    {
        $transaction = $this->db->where('transactions_id', (int) $transactions_id)->get('tbl_transactions')->row_array();
        if (empty($transaction)) {
            return null;
        }
        if (!empty($transaction['type']) && $transaction['type'] === 'Transfer' && !empty($transaction['transfer_id'])) {
            return $this->attach_transfer_transaction_to_journal($transaction);
        }
        return $this->sync_transaction_journal($transaction);
    }

    public function sync_transfer_by_id($transfer_id)
    {
        $transfer = $this->db->where('transfer_id', (int) $transfer_id)->get('tbl_transfer')->row_array();
        if (empty($transfer)) {
            return null;
        }
        return $this->sync_transfer_journal($transfer);
    }

    public function delete_transaction_by_id($transactions_id)
    {
        $transaction = $this->db->where('transactions_id', (int) $transactions_id)->get('tbl_transactions')->row_array();
        if (empty($transaction) || (!empty($transaction['type']) && $transaction['type'] === 'Transfer' && !empty($transaction['transfer_id']))) {
            return;
        }
        if (!empty($transaction['date']) && !finance_accounting_period_is_open($transaction['date'])) {
            return false;
        }
        $this->delete_journal_by_source('transaction', $transaction, 'transactions_id');
        finance_report_model()->refresh_finance_rollup_from_transaction($transaction);
        finance_report_model()->refresh_project_finance_summary_from_transaction($transaction);
        return true;
    }

    public function delete_transfer_by_id($transfer_id)
    {
        $transfer = $this->db->where('transfer_id', (int) $transfer_id)->get('tbl_transfer')->row_array();
        if (empty($transfer)) {
            return;
        }
        if (!empty($transfer['date']) && !finance_accounting_period_is_open($transfer['date'])) {
            return false;
        }
        $this->delete_journal_by_source('transfer', $transfer, 'transfer_id');
        return true;
    }

    public function sync_account_chart_of_account($account_id)
    {
        if (empty($account_id)) {
            return null;
        }
        $account = $this->db->where('account_id', $account_id)->get('tbl_accounts')->row_array();
        if (empty($account)) {
            return null;
        }

        $chart_of_account_id = $this->resolve_account_chart_of_account_id($account);
        if (!empty($chart_of_account_id)) {
            $this->db->where('account_id', $account_id)->update('tbl_accounts', array('chart_of_account_id' => $chart_of_account_id));
        }
        return $chart_of_account_id;
    }

    public function sync_income_category_chart_of_account($category_id)
    {
        if (empty($category_id)) {
            return null;
        }
        $category = $this->db->where('income_category_id', $category_id)->get('tbl_income_category')->row_array();
        if (empty($category)) {
            return null;
        }

        $chart_of_account_id = $this->resolve_category_chart_of_account_id($category['income_category'], $category_id, 'income');
        if (!empty($chart_of_account_id)) {
            $this->db->where('income_category_id', $category_id)->update('tbl_income_category', array('chart_of_account_id' => $chart_of_account_id));
        }
        return $chart_of_account_id;
    }

    public function sync_expense_category_chart_of_account($category_id)
    {
        if (empty($category_id)) {
            return null;
        }
        $category = $this->db->where('expense_category_id', $category_id)->get('tbl_expense_category')->row_array();
        if (empty($category)) {
            return null;
        }

        $chart_of_account_id = $this->resolve_category_chart_of_account_id($category['expense_category'], $category_id, 'expense');
        if (!empty($chart_of_account_id)) {
            $this->db->where('expense_category_id', $category_id)->update('tbl_expense_category', array('chart_of_account_id' => $chart_of_account_id));
        }
        return $chart_of_account_id;
    }

    public function sync_transaction_journal(array $transaction, $refresh_rollup = true)
    {
        if (empty($transaction) || empty($transaction['transactions_id'])) {
            return null;
        }

        if (!empty($transaction['type']) && $transaction['type'] === 'Transfer' && !empty($transaction['transfer_id'])) {
            return null;
        }

        $amount = (float) $transaction['amount'];
        if ($amount <= 0) {
            return null;
        }

        $account_coa_id = $this->resolve_account_coa_id($transaction['account_id']);
        $offset_coa_id = $this->resolve_transaction_offset_coa_id($transaction);
        if (empty($account_coa_id) || empty($offset_coa_id)) {
            return null;
        }

        $reference_no = $this->normalize_reference_no($transaction);
        $notes = $this->normalize_notes($transaction);
        $journal_id = $this->post_double_entry(array(
            'source_module' => 'transaction',
            'source_id' => (int) $transaction['transactions_id'],
            'reference_no' => $reference_no,
            'date' => $transaction['date'],
            'created_by' => !empty($transaction['added_by']) ? (int) $transaction['added_by'] : $this->current_user_id(),
            'status' => $this->map_posting_status($transaction),
            'notes' => $notes,
        ), array(
            array(
                'chart_of_account_id' => ($transaction['type'] === 'Income') ? $account_coa_id : $offset_coa_id,
                'debit' => ($transaction['type'] === 'Income') ? $amount : 0,
                'credit' => ($transaction['type'] === 'Expense') ? $amount : 0,
                'description' => $notes,
            ),
            array(
                'chart_of_account_id' => ($transaction['type'] === 'Income') ? $offset_coa_id : $account_coa_id,
                'debit' => ($transaction['type'] === 'Expense') ? $amount : 0,
                'credit' => ($transaction['type'] === 'Income') ? $amount : 0,
                'description' => $notes,
            ),
        ));

        if (!empty($journal_id) && !empty($refresh_rollup)) {
            finance_report_model()->refresh_finance_rollup_from_transaction($transaction);
            finance_report_model()->refresh_project_finance_summary_from_transaction($transaction);
        }

        return $journal_id;
    }

    public function sync_transfer_journal(array $transfer)
    {
        if (empty($transfer) || empty($transfer['transfer_id'])) {
            return null;
        }

        $amount = (float) $transfer['amount'];
        if ($amount <= 0) {
            return null;
        }

        $from_account_coa_id = $this->resolve_account_coa_id($transfer['from_account_id']);
        $to_account_coa_id = $this->resolve_account_coa_id($transfer['to_account_id']);
        if (empty($from_account_coa_id) || empty($to_account_coa_id)) {
            return null;
        }

        $reference_no = $this->normalize_reference_no($transfer);
        $notes = $this->normalize_notes($transfer);
        $journal_id = $this->post_double_entry(array(
            'source_module' => 'transfer',
            'source_id' => (int) $transfer['transfer_id'],
            'reference_no' => $reference_no,
            'date' => $transfer['date'],
            'created_by' => !empty($transfer['created_by']) ? (int) $transfer['created_by'] : $this->current_user_id(),
            'status' => $this->map_posting_status($transfer),
            'notes' => $notes,
        ), array(
            array(
                'chart_of_account_id' => $to_account_coa_id,
                'debit' => $amount,
                'credit' => 0,
                'description' => $notes,
            ),
            array(
                'chart_of_account_id' => $from_account_coa_id,
                'debit' => 0,
                'credit' => $amount,
                'description' => $notes,
            ),
        ));

        $this->attach_transfer_transaction_to_journal(array('transfer_id' => $transfer['transfer_id'], 'journal_id' => $journal_id));
        return $journal_id;
    }

    private function post_double_entry(array $journal_data, array $items)
    {
        $journal_id = $this->upsert_journal($journal_data, $items);
        if (!empty($journal_id) && !empty($journal_data['source_module']) && !empty($journal_data['source_id'])) {
            if ($journal_data['source_module'] === 'transaction') {
                $this->link_source_to_journal('tbl_transactions', 'transactions_id', (int) $journal_data['source_id'], $journal_id);
            } elseif ($journal_data['source_module'] === 'transfer') {
                $this->link_source_to_journal('tbl_transfer', 'transfer_id', (int) $journal_data['source_id'], $journal_id);
            }
        }
        return $journal_id;
    }

    private function sync_all_account_charts()
    {
        $rows = $this->db->get('tbl_accounts')->result_array();
        foreach ($rows as $row) {
            $this->sync_account_chart_of_account($row['account_id']);
        }
    }

    private function sync_all_category_charts()
    {
        $income_rows = $this->db->get('tbl_income_category')->result_array();
        foreach ($income_rows as $row) {
            $this->sync_income_category_chart_of_account($row['income_category_id']);
        }

        $expense_rows = $this->db->get('tbl_expense_category')->result_array();
        foreach ($expense_rows as $row) {
            $this->sync_expense_category_chart_of_account($row['expense_category_id']);
        }
    }

    private function sync_all_transaction_journals($refresh_rollups = true)
    {
        $rows = $this->db->where_in('type', array('Income', 'Expense'))->get('tbl_transactions')->result_array();
        $client_ids = array();
        foreach ($rows as $row) {
            if (!empty($row['paid_by'])) {
                $client_ids[] = (int) $row['paid_by'];
            }
            $this->sync_transaction_journal($row, $refresh_rollups);
        }

        if (empty($refresh_rollups)) {
            $client_ids = array_values(array_unique(array_filter($client_ids)));
            foreach ($client_ids as $client_id) {
                finance_report_model()->refresh_client_finance_rollup($client_id);
            }
            finance_report_model()->refresh_global_finance_rollup();
        }
    }

    private function sync_all_transfer_journals($refresh_rollups = true)
    {
        if (!$this->db->table_exists('tbl_transfer')) {
            return;
        }
        $rows = $this->db->get('tbl_transfer')->result_array();
        foreach ($rows as $row) {
            $this->sync_transfer_journal($row);
        }
    }

    private function resolve_account_chart_of_account_id(array $account)
    {
        if (!empty($account['chart_of_account_id'])) {
            $existing = $this->db->where('chart_of_account_id', $account['chart_of_account_id'])->get('tbl_chart_of_accounts')->row_array();
            if (!empty($existing)) {
                $this->db->where('chart_of_account_id', $existing['chart_of_account_id'])->update('tbl_chart_of_accounts', array(
                    'name' => $account['account_name'],
                    'notes' => $this->build_mapping_notes('tbl_accounts', $account['account_id'], $account['account_name']),
                    'status' => 1,
                ));
                return (int) $existing['chart_of_account_id'];
            }
        }

        $existing = $this->db->where('notes', $this->build_mapping_notes('tbl_accounts', $account['account_id'], $account['account_name']))->get('tbl_chart_of_accounts')->row_array();
        if (!empty($existing)) {
            return (int) $existing['chart_of_account_id'];
        }

        $code = $this->generate_unique_coa_code('BANK', $account['account_id'], $account['account_name']);
        $chart_of_account = array(
            'account_type_id' => 1,
            'account_sub_type_id' => 1,
            'code' => $code,
            'name' => $account['account_name'],
            'notes' => $this->build_mapping_notes('tbl_accounts', $account['account_id'], $account['account_name']),
            'status' => 1,
        );
        $this->db->insert('tbl_chart_of_accounts', $chart_of_account);
        return (int) $this->db->insert_id();
    }

    private function resolve_category_chart_of_account_id($category_name, $category_id, $module)
    {
        $table_name = $module === 'income' ? 'tbl_income_category' : 'tbl_expense_category';
        $account_type_id = $module === 'income' ? 4 : 3;
        $account_sub_type_id = $module === 'income' ? 16 : 12;

        $existing = $this->db->where('notes', $this->build_mapping_notes($table_name, $category_id, $category_name))->get('tbl_chart_of_accounts')->row_array();
        if (!empty($existing)) {
            return (int) $existing['chart_of_account_id'];
        }

        $code = $this->generate_unique_coa_code($module === 'income' ? 'INC' : 'EXP', $category_id, $category_name);
        $chart_of_account = array(
            'account_type_id' => $account_type_id,
            'account_sub_type_id' => $account_sub_type_id,
            'code' => $code,
            'name' => $category_name,
            'notes' => $this->build_mapping_notes($table_name, $category_id, $category_name),
            'status' => 1,
        );
        $this->db->insert('tbl_chart_of_accounts', $chart_of_account);
        return (int) $this->db->insert_id();
    }

    private function resolve_account_coa_id($account_id)
    {
        $account = $this->db->where('account_id', $account_id)->get('tbl_accounts')->row_array();
        if (empty($account)) {
            return $this->get_fallback_coa_id('Bank & Cash', 1);
        }
        return $this->sync_account_chart_of_account($account_id);
    }

    private function resolve_transaction_offset_coa_id(array $transaction)
    {
        $type = !empty($transaction['type']) ? $transaction['type'] : 'Expense';
        if ($type === 'Income') {
            if (!empty($transaction['category_id'])) {
                return $this->resolve_income_category_coa_id((int) $transaction['category_id']);
            }
            return $this->get_fallback_coa_id('Other Revenue', 4);
        }

        if ($type === 'Expense') {
            if (!empty($transaction['category_id'])) {
                return $this->resolve_expense_category_coa_id((int) $transaction['category_id']);
            }
            return $this->get_fallback_coa_id('Expense', 3);
        }

        return null;
    }

    private function resolve_income_category_coa_id($category_id)
    {
        $category = $this->db->where('income_category_id', $category_id)->get('tbl_income_category')->row_array();
        if (empty($category)) {
            return $this->get_fallback_coa_id('Other Revenue', 4);
        }
        if (!empty($category['chart_of_account_id'])) {
            $existing = $this->db->where('chart_of_account_id', $category['chart_of_account_id'])->get('tbl_chart_of_accounts')->row_array();
            if (!empty($existing)) {
                return (int) $existing['chart_of_account_id'];
            }
        }
        return $this->sync_income_category_chart_of_account($category_id);
    }

    private function resolve_expense_category_coa_id($category_id)
    {
        $category = $this->db->where('expense_category_id', $category_id)->get('tbl_expense_category')->row_array();
        if (empty($category)) {
            return $this->get_fallback_coa_id('Expense', 3);
        }
        if (!empty($category['chart_of_account_id'])) {
            $existing = $this->db->where('chart_of_account_id', $category['chart_of_account_id'])->get('tbl_chart_of_accounts')->row_array();
            if (!empty($existing)) {
                return (int) $existing['chart_of_account_id'];
            }
        }
        return $this->sync_expense_category_chart_of_account($category_id);
    }

    private function get_fallback_coa_id($name, $account_type_id)
    {
        $row = $this->db
            ->where('account_type_id', $account_type_id)
            ->where('name', $name)
            ->order_by('chart_of_account_id', 'asc')
            ->limit(1)
            ->get('tbl_chart_of_accounts')
            ->row_array();
        if (!empty($row)) {
            return (int) $row['chart_of_account_id'];
        }

        $fallback = $this->db
            ->where('account_type_id', $account_type_id)
            ->order_by('chart_of_account_id', 'asc')
            ->limit(1)
            ->get('tbl_chart_of_accounts')
            ->row_array();
        if (!empty($fallback)) {
            return (int) $fallback['chart_of_account_id'];
        }
        return null;
    }

    private function upsert_journal(array $journal_data, array $items)
    {
        $existing = $this->db
            ->where('source_module', $journal_data['source_module'])
            ->where('source_id', $journal_data['source_id'])
            ->order_by('journal_id', 'desc')
            ->limit(1)
            ->get('tbl_journals')
            ->row_array();

        $this->db->trans_start();

        if (!empty($existing)) {
            $journal_id = (int) $existing['journal_id'];
            $this->db->where('journal_id', $journal_id)->update('tbl_journals', $journal_data);
            $this->db->where('journal_id', $journal_id)->delete('tbl_journal_items');
        } else {
            $this->db->insert('tbl_journals', $journal_data);
            $journal_id = (int) $this->db->insert_id();
        }

        $total_debit = 0;
        $total_credit = 0;
        foreach ($items as $item) {
            $journal_item = array(
                'journal_id' => $journal_id,
                'chart_of_account_id' => (int) $item['chart_of_account_id'],
                'debit' => (float) $item['debit'],
                'credit' => (float) $item['credit'],
                'description' => !empty($item['description']) ? $item['description'] : null,
            );
            $total_debit += (float) $journal_item['debit'];
            $total_credit += (float) $journal_item['credit'];
            $this->db->insert('tbl_journal_items', $journal_item);
        }

        $this->db->where('journal_id', $journal_id)->update('tbl_journals', array(
            'total_debit' => $total_debit,
            'total_credit' => $total_credit,
            'total_amount' => max($total_debit, $total_credit),
        ));

        $this->db->trans_complete();
        return $journal_id;
    }

    private function delete_journal_by_source($source_module, ?array $row = null, $source_id_field = null)
    {
        if (empty($row)) {
            return;
        }

        $journal = null;
        if (!empty($row['journal_id'])) {
            $journal = $this->db->where('journal_id', $row['journal_id'])->get('tbl_journals')->row_array();
        }

        if (empty($journal) && !empty($source_id_field) && !empty($row[$source_id_field])) {
            $journal = $this->db
                ->where('source_module', $source_module)
                ->where('source_id', (int) $row[$source_id_field])
                ->order_by('journal_id', 'desc')
                ->limit(1)
                ->get('tbl_journals')
                ->row_array();
        }

        if (empty($journal)) {
            return;
        }

        $this->db->where('journal_id', $journal['journal_id'])->delete('tbl_journal_items');
        $this->db->where('journal_id', $journal['journal_id'])->delete('tbl_journals');
    }

    private function attach_transfer_transaction_to_journal(array $transaction)
    {
        if (empty($transaction['transfer_id'])) {
            return;
        }

        $journal_id = !empty($transaction['journal_id']) ? (int) $transaction['journal_id'] : null;
        if (empty($journal_id)) {
            $transfer = $this->db->where('transfer_id', (int) $transaction['transfer_id'])->get('tbl_transfer')->row_array();
            if (!empty($transfer['journal_id'])) {
                $journal_id = (int) $transfer['journal_id'];
            } else {
                $journal = $this->db
                    ->where('source_module', 'transfer')
                    ->where('source_id', (int) $transaction['transfer_id'])
                    ->order_by('journal_id', 'desc')
                    ->limit(1)
                    ->get('tbl_journals')
                    ->row_array();
                if (!empty($journal['journal_id'])) {
                    $journal_id = (int) $journal['journal_id'];
                }
            }
        }

        if (empty($journal_id)) {
            return;
        }

        if ($this->db->table_exists('tbl_transactions') && $this->db->field_exists('journal_id', 'tbl_transactions')) {
            $this->db->where('transactions_id', (int) $transaction['transactions_id'])->update('tbl_transactions', array('journal_id' => $journal_id));
        }
    }

    private function link_source_to_journal($table, $primary_key, $source_id, $journal_id)
    {
        if (empty($journal_id) || empty($source_id) || !$this->db->table_exists($table)) {
            return;
        }
        if ($this->db->field_exists('journal_id', $table)) {
            $this->db->where($primary_key, $source_id)->update($table, array('journal_id' => $journal_id));
        }
    }

    private function normalize_reference_no(array $row)
    {
        if (!empty($row['reference_no'])) {
            return $row['reference_no'];
        }
        if (!empty($row['transaction_prefix'])) {
            return $row['transaction_prefix'];
        }
        if (!empty($row['reference'])) {
            return $row['reference'];
        }
        if (!empty($row['type']) && !empty($row['transactions_id'])) {
            return strtoupper($row['type']) . '-' . $row['transactions_id'];
        }
        if (!empty($row['transfer_id'])) {
            return 'TRANSFER-' . $row['transfer_id'];
        }
        return 'JRN-' . date('YmdHis');
    }

    private function normalize_notes(array $row)
    {
        $notes = '';
        if (!empty($row['notes'])) {
            $notes = $row['notes'];
        } elseif (!empty($row['name'])) {
            $notes = $row['name'];
        }
        return substr(strip_tags((string) $notes), 0, 190);
    }

    private function build_mapping_notes($table, $id, $label)
    {
        return $table . ':' . (int) $id . ':' . (string) $label;
    }

    private function generate_unique_coa_code($prefix, $source_id, $label)
    {
        $base = strtoupper($prefix) . '-' . str_pad((string) $source_id, 5, '0', STR_PAD_LEFT);
        $slug = strtoupper(preg_replace('/[^A-Za-z0-9]+/', '', (string) $label));
        if (!empty($slug)) {
            $base .= '-' . substr($slug, 0, 10);
        }
        $code = $base;
        $suffix = 1;
        while ($this->db->where('code', $code)->get('tbl_chart_of_accounts')->num_rows() > 0) {
            $code = $base . '-' . $suffix;
            $suffix++;
        }
        return $code;
    }

    private function map_posting_status(array $row)
    {
        if (!empty($row['status'])) {
            return $row['status'];
        }
        return 'posted';
    }

    private function current_user_id()
    {
        $CI = &get_instance();
        if (!empty($CI) && isset($CI->session) && is_object($CI->session)) {
            $user_id = $CI->session->userdata('user_id');
            if (!empty($user_id)) {
                return (int) $user_id;
            }
        }
        return 0;
    }

    public function finance_index_maintenance_summary()
    {
        $definitions = $this->finance_index_definitions();
        $pending = array();
        foreach ($definitions as $definition) {
            $definition['exists'] = $this->finance_index_exists($definition['table'], $definition['name']);
            $definition['status'] = $definition['exists'] ? 'done' : 'pending';
            if (!$definition['exists']) {
                $pending[] = $definition;
            }
        }

        return array(
            'total_count' => count($definitions),
            'pending_count' => count($pending),
            'items' => $definitions,
        );
    }

    public function build_pending_finance_indexes($progress_callback = null)
    {
        $definitions = $this->finance_index_definitions();
        $total = count($definitions);
        $done = 0;
        $applied = 0;

        foreach ($definitions as $definition) {
            $done++;
            $percent = $total > 0 ? (int) floor((($done - 1) / $total) * 100) : 0;
            if (is_callable($progress_callback)) {
                call_user_func($progress_callback, array(
                    'phase' => 'running',
                    'message' => 'Checking ' . $definition['name'],
                    'progress' => $percent,
                    'current' => $done,
                    'total' => $total,
                    'definition' => $definition,
                ));
            }

            if ($this->finance_index_exists($definition['table'], $definition['name'])) {
                continue;
            }

            $this->db->query($definition['sql']);
            $applied++;

            if (is_callable($progress_callback)) {
                call_user_func($progress_callback, array(
                    'phase' => 'running',
                    'message' => 'Created ' . $definition['name'],
                    'progress' => $total > 0 ? (int) floor(($done / $total) * 100) : 100,
                    'current' => $done,
                    'total' => $total,
                    'definition' => $definition,
                ));
            }
        }

        $this->set_finance_index_pending_flag(false);

        return array(
            'total' => $total,
            'applied' => $applied,
            'done' => $done,
            'pending' => max(0, $total - $applied),
        );
    }

    private function finance_index_definitions()
    {
        return array(
            array('table' => 'tbl_journals', 'name' => 'idx_tbl_journals_reversal_of_journal_id', 'sql' => "ALTER TABLE `tbl_journals` ADD INDEX `idx_tbl_journals_reversal_of_journal_id` (`reversal_of_journal_id`)"),
            array('table' => 'tbl_journals', 'name' => 'idx_tbl_journals_reconciled_status', 'sql' => "ALTER TABLE `tbl_journals` ADD INDEX `idx_tbl_journals_reconciled_status` (`reconciled_status`)"),
            array('table' => 'tbl_bank_reconciliations', 'name' => 'idx_tbl_bank_reconciliations_account_journal', 'sql' => "ALTER TABLE `tbl_bank_reconciliations` ADD INDEX `idx_tbl_bank_reconciliations_account_journal` (`account_id`, `journal_id`)"),
            array('table' => 'tbl_bank_reconciliations', 'name' => 'idx_tbl_bank_reconciliations_status', 'sql' => "ALTER TABLE `tbl_bank_reconciliations` ADD INDEX `idx_tbl_bank_reconciliations_status` (`status`)"),
        );
    }

    private function finance_index_exists($table, $index_name)
    {
        if (!$this->db->table_exists($table)) {
            return false;
        }

        $result = $this->db->query("SHOW INDEX FROM `{$table}` WHERE Key_name = " . $this->db->escape($index_name));
        return $result && $result->num_rows() > 0;
    }

    private function set_finance_index_pending_flag($pending = true)
    {
        if (!$this->db->table_exists('tbl_config')) {
            return;
        }

        $value = $pending ? '1' : '0';
        $existing = $this->db->where('config_key', 'finance_indexes_pending')->get('tbl_config')->row_array();
        if (!empty($existing)) {
            $this->db->where('config_key', 'finance_indexes_pending')->update('tbl_config', array('value' => $value));
            return;
        }

        $this->db->insert('tbl_config', array('config_key' => 'finance_indexes_pending', 'value' => $value));
    }
}
