from datetime import date
import logging
from odoo import models, fields, _
from odoo.exceptions import UserError
from odoo.tools import SQL
from odoo.osv import expression

_logger = logging.getLogger(__name__)


class BankReconciliationReportCustomHandler(models.AbstractModel):
    _name = 'account.bank.reconciliation.report.handler'
    _inherit = 'account.report.custom.handler'
    _description = 'Bank Reconciliation Report Custom Handler'

    ######################
    # Options
    ######################
    def _custom_options_initializer(self, report, options, previous_options):
        super()._custom_options_initializer(report, options, previous_options=previous_options)

        # Options is needed otherwise some elements added in the post processor go on the total line
        options['ignore_totals_below_sections'] = True
        options['no_xlsx_currency_code_columns'] = True
        if 'active_id' in self._context and self._context.get('active_model') == 'account.journal':
            options['bank_reconciliation_report_journal_id'] = self._context['active_id']
        elif 'bank_reconciliation_report_journal_id' in previous_options:
            options['bank_reconciliation_report_journal_id'] = previous_options['bank_reconciliation_report_journal_id']
        else:
            # This should never happen except in some test cases
            options['bank_reconciliation_report_journal_id'] = self.env['account.journal'].search([('type', '=', 'bank')], limit=1).id

        # Remove multi-currency columns if needed
        is_multi_currency = self.env.user.has_group('base.group_multi_currency') and self.env.user.has_group('base.group_no_one')
        if not is_multi_currency:
            options['columns'] = [
                column for column in options['columns']
                if column['expression_label'] not in ('amount_currency', 'currency')
            ]

    ######################
    # Getter
    ######################
    def _get_bank_journal_and_currencies(self, options):
        journal = self.env['account.journal'].browse(options.get('bank_reconciliation_report_journal_id'))
        company_currency = journal.company_id.currency_id
        journal_currency = journal.currency_id or company_currency
        return journal, journal_currency, company_currency

    ######################
    # Return function
    ######################
    def _build_custom_engine_result(self, date=None, label=None, amount_currency=None, amount_currency_currency_id=None, currency=None, amount=0, amount_currency_id=None, has_sublines=False):
        return {
            'date': date,
            'label': label,
            'amount_currency': amount_currency,
            'amount_currency_currency_id': amount_currency_currency_id,
            'currency': currency,
            'amount': amount,
            'amount_currency_id': amount_currency_id,
            'has_sublines': has_sublines,
        }

    ######################
    # Engine
    ######################
    def _report_custom_engine_forced_currency_amount(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        _journal, journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        return self._build_custom_engine_result(amount_currency_id=journal_currency.id)

    def _report_custom_engine_unreconciled_last_statement_receipts(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_common(options, 'receipts', current_groupby, True)

    def _report_custom_engine_unreconciled_last_statement_payments(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_common(options, 'payments', current_groupby, True)

    def _report_custom_engine_unreconciled_receipts(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_common(options, 'receipts', current_groupby, False)

    def _report_custom_engine_unreconciled_payments(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_common(options, 'payments', current_groupby, False)

    def _report_custom_engine_outstanding_receipts(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_outstanding_common(options, 'receipts', current_groupby)

    def _report_custom_engine_outstanding_payments(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_outstanding_common(options, 'payments', current_groupby)

    def _report_custom_engine_misc_operations(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        report = self.env['account.report'].browse(options['report_id'])
        report._check_groupby_fields([current_groupby] if current_groupby else [])

        journal, journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        exchange_journal = journal.company_id.currency_exchange_journal_id

        bank_miscellaneous_domain = self._get_bank_miscellaneous_move_lines_domain(options, journal)
        bank_miscellaneous_domain = expression.AND([
            bank_miscellaneous_domain,
            [('journal_id', '!=', exchange_journal.id)]
        ])

        base_query = report._get_report_query(options, 'strict_range', domain=bank_miscellaneous_domain or [])

        groupby_field_sql = self.env['account.move.line']._field_to_sql("account_move_line", current_groupby, base_query) if current_groupby else None
        query_sql = SQL(
            """
            SELECT
                %(select_from_groupby)s,
                COALESCE(SUM(COALESCE(NULLIF(account_move_line.amount_currency, 0), account_move_line.balance)), 0)
            FROM %(table_references)s
            WHERE %(search_condition)s
            %(groupby_sql)s
            """,
            select_from_groupby=groupby_field_sql,
            table_references=base_query.from_clause,
            search_condition=base_query.where_clause,
            groupby_sql=SQL("GROUP BY %s", groupby_field_sql) if groupby_field_sql else SQL(),
        )

        self._cr.execute(query_sql)
        query_res_lines = self._cr.fetchall()

        if not current_groupby:
            return self._build_custom_engine_result(amount=query_res_lines[-1][1], amount_currency_id=journal_currency.id)
        else:
            return [
                (grouping_key, self._build_custom_engine_result(amount=amount, amount_currency_id=journal_currency.id))
                for grouping_key, amount in query_res_lines
            ]

    def _report_custom_engine_last_statement_balance_amount(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        if current_groupby:
            raise UserError(_("Custom engine _report_custom_engine_last_statement_balance_amount does not support groupby"))

        journal, journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        last_statement = self._get_last_bank_statement(journal, options)

        return self._build_custom_engine_result(amount=last_statement.balance_end_real, amount_currency_id=journal_currency.id)

    def _report_custom_engine_transaction_without_statement_amount(self, expressions, options, date_scope, current_groupby, next_groupby, offset=0, limit=None, warnings=None):
        return self._bank_reconciliation_report_custom_engine_common(options, 'all', current_groupby, False, unreconciled=False)

    def _bank_reconciliation_report_custom_engine_common(self, options, internal_type, current_groupby, from_last_statement, unreconciled=True):
        """
            Retrieve entries for bank reconciliation based on specified parameters.
            Parameters:
            - options (dict): A dictionary containing options of the report.
            - internal_type (str): The internal type used for classification (e.g., receipt, payment). For the receipt
                                   we will query the entries with a positive amounts and for the payment
                                   the negative amounts.
                                   If the internal type is another thing that receipt or payment it will get all the
                                   entries position or negative
            - current_groupby (str): The current grouping criteria.
            - last_statement (bool, optional): If True, query entries from the last bank statement.
                                               Otherwise, query entries that are not part of the last bank
                                               statement.
            - unreconciled (bool, optional): If True, query the unreconciled entries only

        """
        journal, journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        if not journal:
            return self._build_custom_engine_result()

        report = self.env['account.report'].browse(options['report_id'])
        report._check_groupby_fields([current_groupby] if current_groupby else [])

        def build_result_dict(query_res_lines):
            # The query should find exactly one account move line per bank statement line
            if current_groupby == 'id':
                res = query_res_lines[0]
                foreign_currency = self.env['res.currency'].browse(res['foreign_currency_id'])
                rate = 1  # journal_currency / foreign_currency
                if foreign_currency:
                    rate = (res['amount'] / res['amount_currency']) if res['amount_currency'] else 0

                return self._build_custom_engine_result(
                    date=res['date'] if res['date'] else None,
                    label=res['payment_ref'] or res['ref'] or '/',
                    amount_currency=-res['amount_residual'] if res['foreign_currency_id'] else None,
                    amount_currency_currency_id=foreign_currency.id if res['foreign_currency_id'] else None,
                    currency=foreign_currency.display_name if res['foreign_currency_id'] else None,
                    amount=-res['amount_residual'] * rate if res['amount_residual'] else None,
                    amount_currency_id=journal_currency.id,
                )
            else:
                amount = 0
                for res in query_res_lines:
                    rate = 1  # journal_currency / foreign_currency
                    if res['foreign_currency_id']:
                        rate = (res['amount'] / res['amount_currency']) if res['amount_currency'] else 0
                    amount += -res.get('amount_residual', 0) * rate if unreconciled else res.get('amount', 0)

                return self._build_custom_engine_result(
                    amount=amount,
                    amount_currency_id=journal_currency.id,
                    has_sublines=bool(len(query_res_lines)),
                )

        query = report._get_report_query(options, 'strict_range', domain=[
            ('journal_id', '=', journal.id),
            ('account_id', '=', journal.default_account_id.id),  # There should be only 1 line per move with that account
        ])

        if from_last_statement:
            last_statement_id = self._get_last_bank_statement(journal, options).id
            if last_statement_id:
                last_statement_id_condition = SQL("st_line.statement_id = %s", last_statement_id)
            else:
                # If there is no last statement, the last statement section must be empty and the other must have all
                # transaction
                return self._compute_result([], current_groupby, build_result_dict)
        else:
            last_statement_id_condition = SQL("st_line.statement_id IS NULL")

        if internal_type == 'receipts':
            st_line_amount_condition = SQL("AND st_line.amount > 0")
        elif internal_type == 'payments':
            st_line_amount_condition = SQL("AND st_line.amount < 0")
        else:
            # For the Transaction without statement, the internal type is 'all'
            st_line_amount_condition = SQL("")

        groupby_field_sql = self.env['account.move.line']._field_to_sql("account_move_line", current_groupby, query) if current_groupby else SQL('NULL')
        # Build query
        query = SQL(
            """
           SELECT %(select_from_groupby)s,
                  st_line.id,
                  move.name,
                  move.ref,
                  move.date,
                  st_line.payment_ref,
                  st_line.amount,
                  st_line.amount_residual,
                  st_line.amount_currency,
                  st_line.foreign_currency_id
             FROM %(table_references)s
             JOIN account_bank_statement_line st_line ON st_line.move_id = account_move_line.move_id
             JOIN account_move move ON move.id = st_line.move_id
            WHERE %(search_condition)s
                  %(is_unreconciled)s
                  %(st_line_amount_condition)s
              AND %(last_statement_id_condition)s
         GROUP BY %(group_by)s,
                  st_line.id,
                  move.id
            """,
            select_from_groupby=SQL("%s AS grouping_key", groupby_field_sql),
            table_references=query.from_clause,
            search_condition=query.where_clause,
            is_receipt=SQL("st_line.amount > 0") if internal_type == "receipts" else SQL("st_line.amount < 0"),
            is_unreconciled=SQL("AND NOT st_line.is_reconciled") if unreconciled else SQL(""),
            st_line_amount_condition=st_line_amount_condition,
            last_statement_id_condition=last_statement_id_condition,
            group_by=groupby_field_sql if current_groupby else SQL('st_line.id'),  # Same key in the groupby because we can't put a null key in a group by
        )

        self._cr.execute(query)
        query_res_lines = self._cr.dictfetchall()

        return self._compute_result(query_res_lines, current_groupby, build_result_dict)

    def _bank_reconciliation_report_custom_engine_outstanding_common(self, options, internal_type, current_groupby):
        """
            This engine retrieves the data of all recorded payments/receipts that have not been matched with a bank
            statement yet
        """
        journal, journal_currency, company_currency = self._get_bank_journal_and_currencies(options)
        if not journal:
            return self._build_custom_engine_result()

        report = self.env['account.report'].browse(options['report_id'])
        report._check_groupby_fields([current_groupby] if current_groupby else [])

        def build_result_dict(query_res_lines):
            if current_groupby == 'id':
                res = query_res_lines[0]
                convert = not (journal_currency and res['currency_id'] == journal_currency.id)
                amount_currency = res['amount_residual_currency'] if res['is_account_reconcile'] else res['amount_currency']
                balance = res['amount_residual'] if res['is_account_reconcile'] else res['balance']
                foreign_currency = self.env['res.currency'].browse(res['currency_id'])

                return self._build_custom_engine_result(
                    date=res['date'] if res['date'] else None,
                    label=res['ref'] if res['ref'] else None,
                    amount_currency=amount_currency if convert else None,
                    amount_currency_currency_id=foreign_currency.id if convert else None,
                    currency=foreign_currency.display_name if convert else None,
                    amount=company_currency._convert(balance, journal_currency, journal.company_id, options['date']['date_to']) if convert else amount_currency,
                    amount_currency_id=journal_currency.id,
                )
            else:
                amount = 0
                for res in query_res_lines:
                    convert = not (journal_currency and res['currency_id'] == journal_currency.id)
                    if convert:
                        balance = res['amount_residual'] if res['is_account_reconcile'] else res['balance']
                        amount += company_currency._convert(balance, journal_currency, journal.company_id, options['date']['date_to'])
                    else:
                        amount += res['amount_residual_currency'] if res['is_account_reconcile'] else res['amount_currency']

                return self._build_custom_engine_result(
                    amount=amount,
                    amount_currency_id=journal_currency.id,
                    has_sublines=bool(len(query_res_lines)),
                )

        accounts = journal._get_journal_inbound_outstanding_payment_accounts() + journal._get_journal_outbound_outstanding_payment_accounts()

        query = report._get_report_query(options, 'from_beginning', domain=[
            ('journal_id', '=', journal.id),
            ('account_id', 'in', accounts.ids),
            ('full_reconcile_id', '=', False),
            ('amount_residual_currency', '!=', 0.0)
        ])

        # Build query
        groupby_field_sql = self.env['account.move.line']._field_to_sql("account_move_line", current_groupby, query) if current_groupby else SQL('NULL')
        query = SQL(
            """
           SELECT %(select_from_groupby)s,
                  account_move_line.account_id,
                  account_move_line.payment_id,
                  account_move_line.move_id,
                  account_move_line.currency_id,
                  account_move_line.move_name AS name,
                  account_move_line.ref,
                  account_move_line.date,
                  account.reconcile AS is_account_reconcile,
                  SUM(account_move_line.amount_residual) AS amount_residual,
                  SUM(account_move_line.balance) AS balance,
                  SUM(account_move_line.amount_residual_currency) AS amount_residual_currency,
                  SUM(account_move_line.amount_currency) AS amount_currency
             FROM %(table_references)s
             JOIN account_account account ON account.id = account_move_line.account_id
            WHERE %(search_condition)s
              AND %(is_receipt)s
         GROUP BY %(group_by)s,
                  account_move_line.account_id,
                  account_move_line.payment_id,
                  account_move_line.move_id,
                  account_move_line.currency_id,
                  account_move_line.move_name,
                  account_move_line.ref,
                  account_move_line.date,
                  account.reconcile
           """,
            select_from_groupby=SQL("%s AS grouping_key", groupby_field_sql),
            table_references=query.from_clause,
            search_condition=query.where_clause,
            is_receipt=SQL("account_move_line.balance > 0") if internal_type == "receipts" else SQL("account_move_line.balance < 0"),
            group_by=groupby_field_sql if current_groupby else SQL('account_move_line.account_id'),  # Same key in the groupby because we can't put a null key in a group by
        )
        self._cr.execute(query)
        query_res_lines = self._cr.dictfetchall()

        return self._compute_result(query_res_lines, current_groupby, build_result_dict)

    def _compute_result(self, query_res_lines, current_groupby, build_result_dict):
        if not current_groupby:
            return build_result_dict(query_res_lines)
        else:
            rslt = []

            all_res_per_grouping_key = {}
            for query_res in query_res_lines:
                grouping_key = query_res['grouping_key']
                all_res_per_grouping_key.setdefault(grouping_key, []).append(query_res)

            for grouping_key, query_res_lines in all_res_per_grouping_key.items():
                rslt.append((grouping_key, build_result_dict(query_res_lines)))

            return rslt

    def _custom_line_postprocessor(self, report, options, lines):
        lines = super()._custom_line_postprocessor(report, options, lines)
        journal, _journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        if not journal:
            return lines

        last_statement = self._get_last_bank_statement(journal, options)

        for line in lines:
            line_id = report._get_res_id_from_line_id(line['id'], 'account.report.line')
            code = self.env['account.report.line'].browse(line_id).code

            if code == "balance_bank":
                line['name'] = _("Balance of '%s'", journal.default_account_id.display_name)

            if code == "last_statement_balance":
                line['class'] = 'o_bold_tr'
                if last_statement:
                    line['columns'][1].update({
                        'name': last_statement.display_name,
                        'auditable': True,
                    })

            if code == "transaction_without_statement":
                line['class'] = 'o_bold_tr'

            if code == "misc_operations":
                line['class'] = 'o_bold_tr'

            # Check if it's a leaf node
            model, _model_id = report._get_model_info_from_id(line['id'])
            if model == "account.move.line":
                line_name = line['name'].split()
                line['name'] = line_name[0]  # This will give just the name without the ref or label

        return lines

    def _customize_warnings(self, report, options, all_column_groups_expression_totals, warnings):
        journal, journal_currency, _company_currency = self._get_bank_journal_and_currencies(options)
        inconsistent_statement = self._get_inconsistent_statements(options, journal).ids
        bank_miscellaneous_domain = self._get_bank_miscellaneous_move_lines_domain(options, journal)
        has_bank_miscellaneous_move_lines = bank_miscellaneous_domain and bool(self.env['account.move.line'].search_count(bank_miscellaneous_domain, limit=1))
        last_statement, balance_gl, balance_end, unexplained_difference, general_ledger_not_matching = self._compute_journal_balances(report, options, journal, journal_currency)

        if warnings is not None:
            if last_statement and general_ledger_not_matching:
                warnings['odex30_account_reports.journal_balance'] = {
                    'alert_type': 'warning',
                    'general_ledger_amount': balance_gl,
                    'last_bank_statement_amount': balance_end,
                    'unexplained_difference': unexplained_difference,
                }
            if inconsistent_statement:
                warnings['odex30_account_reports.inconsistent_statement_warning'] = {'alert_type': 'warning', 'args': inconsistent_statement}
            if has_bank_miscellaneous_move_lines:
                warnings['odex30_account_reports.has_bank_miscellaneous_move_lines'] = {'alert_type': 'warning', 'args': journal.default_account_id.display_name}

    def _compute_journal_balances(self, report, options, journal, journal_currency):
        """
            This function compute all necessary information for the warning 'odex30_account_reports.journal_balance'
            :param report:          The bank reconciliation report.
            :param options:         The report options.
            :param journal:         The journal used.
        """
        # Get domain and balances
        domain = report._get_options_domain(options, 'from_beginning')
        balance_gl = journal._get_journal_bank_account_balance(domain=domain)[0]
        last_statement, balance_end, difference, general_ledger_not_matching = self._compute_balances(options, journal, balance_gl, journal_currency)

        # Format values
        balance_gl = report.format_value(options, balance_gl, format_params={'currency_id': journal_currency.id}, figure_type='monetary')
        balance_end = report.format_value(options, balance_end, format_params={'currency_id': journal_currency.id}, figure_type='monetary')
        difference = report.format_value(options, difference, format_params={'currency_id': journal_currency.id}, figure_type='monetary')

        return last_statement, balance_gl, balance_end, difference, general_ledger_not_matching

    def _compute_balances(self, options, journal, balance_gl, report_currency):
        """
            This function will compute the balance of the last statement and the unexplained difference.
            :param options:         The report options.
            :param journal:         The journal used.
            :param balance_gl:      The balance of the general ledger.
            :param report_currency: The currency of the report.
        """
        report_date = fields.Date.from_string(options['date']['date_to'])
        last_statement = self._get_last_bank_statement(journal, options)
        balance_end = 0
        difference = 0
        general_ledger_not_matching = False

        if last_statement:
            lines_before_date_to = last_statement.line_ids.filtered(lambda line: line.date <= report_date)
            balance_end = last_statement.balance_start + sum(lines_before_date_to.mapped('amount'))
            difference = balance_gl - balance_end
            general_ledger_not_matching = not report_currency.is_zero(difference)

        return last_statement, balance_end, difference, general_ledger_not_matching

    def _get_last_bank_statement(self, journal, options):
        """
            Retrieve the last bank statement created using this journal.
            :param journal: The journal used.
            :param domain:  An additional domain to be applied on the account.bank.statement model.
            :return:        An account.bank.statement record or an empty recordset.
        """
        report_date = fields.Date.from_string(options['date']['date_to'])
        last_statement_domain = [('journal_id', '=', journal.id), ('statement_id', '!=', False), ('date', '<=', report_date)]
        last_st_line = self.env['account.bank.statement.line'].search(last_statement_domain, order='date desc, id desc', limit=1)
        return last_st_line.statement_id

    def _get_inconsistent_statements(self, options, journal):
        """
            Retrieve the account.bank.statements records on the range of the options date having different starting
            balance regarding its previous statement.
            :param options: The report options.
            :param journal: The account.journal from which this report has been opened.
            :return:        An account.bank.statements recordset.
        """
        return self.env['account.bank.statement'].search([
            ('journal_id', '=', journal.id),
            ('date', '<=', options['date']['date_to']),
            ('is_valid', '=', False),
        ])

    def _get_bank_miscellaneous_move_lines_domain(self, options, journal):
        """
            Get the domain to be used to retrieve the journal items affecting the bank accounts but not linked to
            a statement line. (Limited in a year)
            :param options: The report options.
            :param journal: The account.journal from which this report has been opened.
            :return:        A domain to search on the account.move.line model.

        """
        if not journal.default_account_id:
            return None

        report = self.env['account.report'].browse(options['report_id'])
        domain = [
            ('account_id', '=', journal.default_account_id.id),
            ('statement_line_id', '=', False),
            *report._get_options_domain(options, 'from_beginning'),
        ]

        fiscal_lock_date = journal.company_id._get_user_fiscal_lock_date(journal)
        if fiscal_lock_date != date.min:
            domain.append(('date', '>', fiscal_lock_date))

        if journal.company_id.account_opening_move_id:
            domain.append(('move_id', '!=', journal.company_id.account_opening_move_id.id))

        return domain

    ################
    # Audit
    ################
    def action_audit_cell(self, options, params):
        report_line = self.env['account.report.line'].browse(params['report_line_id'])
        if report_line.code == "balance_bank":
            return self.action_redirect_to_general_ledger(options)
        elif report_line.code == "misc_operations":
            return self.open_bank_miscellaneous_move_lines(options)
        elif report_line.code == "last_statement_balance":
            return self.action_redirect_to_bank_statement_widget(options)
        else:
            return report_line.report_id.action_audit_cell(options, params)

    ################
    # ACTIONS
    ################
    def action_redirect_to_general_ledger(self, options):
        """
            Action to redirect to the general ledger
            :param options:     The report options.
            :return:            Actions to the report
        """
        general_ledger_action = self.env['ir.actions.actions']._for_xml_id('odex30_account_reports.action_account_report_general_ledger')
        general_ledger_action['params'] = {
            'options': options,
            'ignore_session': True,
        }

        return general_ledger_action

    def action_redirect_to_bank_statement_widget(self, options):
        """
            Redirect the user to the requested bank statement, if empty displays all bank transactions of the journal.
            :param options:     The report options.
            :param params:      The action params containing at least 'statement_id', can be false.
            :return:            A dictionary representing an ir.actions.act_window.
        """
        journal = self.env['account.journal'].browse(options.get('bank_reconciliation_report_journal_id'))
        last_statement = self._get_last_bank_statement(journal, options)
        return self.env['account.bank.statement.line']._action_open_bank_reconciliation_widget(
            default_context={'create': False, 'search_default_statement_id': last_statement.id},
            name=last_statement.display_name,
        )

    def open_bank_miscellaneous_move_lines(self, options):
        """
            An action opening the account.move.line list view affecting the bank account balance but not linked to
            a bank statement line.
            :param options: The report options.
            :param params:  -Not used-.
            :return:        An action redirecting to the list view of journal items.
        """
        journal = self.env['account.journal'].browse(options['bank_reconciliation_report_journal_id'])

        return {
            'name': _('Journal Items'),
            'type': 'ir.actions.act_window',
            'res_model': 'account.move.line',
            'view_type': 'list',
            'view_mode': 'list',
            'target': 'current',
            'views': [(self.env.ref('account.view_move_line_tree').id, 'list')],
            'domain': self.env['account.bank.reconciliation.report.handler']._get_bank_miscellaneous_move_lines_domain(options, journal),
        }

    def bank_reconciliation_report_open_inconsistent_statements(self, options, params=None):
        """
            An action opening the account.bank.statement view (form or list) depending the 'inconsistent_statement_ids'
            key set on the options.
            :param options: The report options.
            :param params:  -Not used-.
            :return:        An action redirecting to a view of statements.
        """
        inconsistent_statement_ids = params['args']
        action = {
            'name': _("Inconsistent Statements"),
            'type': 'ir.actions.act_window',
            'res_model': 'account.bank.statement',
        }
        if len(inconsistent_statement_ids) == 1:
            action.update({
                'view_mode': 'form',
                'res_id': inconsistent_statement_ids[0],
                'views': [(False, 'form')],
            })
        else:
            action.update({
                'view_mode': 'list',
                'domain': [('id', 'in', inconsistent_statement_ids)],
                'views': [(False, 'list')],
            })
        return action
