#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""A module that allows running existing pandas doctests with Beam dataframes.

This module hooks into the doctesting framework by providing a custom
runner and, in particular, an OutputChecker, as well as providing a fake
object for mocking out the pandas module.

The (novel) sequence of events when running a doctest is as follows.

  1. The test invokes `pd.DataFrame(...)` (or similar) and an actual dataframe
     is computed and stashed but a Beam deferred dataframe is returned
     in its place.
  2. Computations are done on these "dataframes," resulting in new objects,
     but as these are actually deferred, only expression trees are built.
     In the background, a mapping of id -> deferred dataframe is stored for
     each newly created dataframe.
  3. When any dataframe is printed out, the repr has been overwritten to
     print `Dataframe[id]`. The aforementened mapping is used to map this back
     to the actual dataframe object, which is then computed via Beam, and its
     the (stringified) result plugged into the actual output for comparison.
  4. The comparison is then done on the sorted lines of the expected and actual
     values.
"""

import collections
import contextlib
import doctest
import re
import sys
import traceback
from io import StringIO
from typing import Any

import numpy as np
import pandas as pd

import apache_beam as beam
from apache_beam.dataframe import expressions
from apache_beam.dataframe import frames  # pylint: disable=unused-import
from apache_beam.dataframe import pandas_top_level_functions
from apache_beam.dataframe import transforms
from apache_beam.dataframe.frame_base import DeferredBase


class FakePandasObject(object):
  """A stand-in for the wrapped pandas objects.
  """
  def __init__(self, pandas_obj, test_env):
    self._pandas_obj = pandas_obj
    self._test_env = test_env

  def __call__(self, *args, **kwargs):
    result = self._pandas_obj(*args, **kwargs)
    if type(result) in DeferredBase._pandas_type_map:
      placeholder = expressions.PlaceholderExpression(result.iloc[0:0])
      self._test_env._inputs[placeholder] = result
      return DeferredBase.wrap(placeholder)
    else:
      return result

  def __getattr__(self, name):
    attr = getattr(self._pandas_obj, name)
    if callable(attr):
      result = FakePandasObject(attr, self._test_env)
    else:
      result = attr
    # Cache this so two lookups return the same object.
    setattr(self, name, result)
    return result

  def __reduce__(self):
    return lambda: pd, ()


class TestEnvironment(object):
  """A class managing the patching (of methods, inputs, and outputs) needed
  to run and validate tests.

  These classes are patched to be able to recognize and retrieve inputs
  and results, stored in `self._inputs` and `self._all_frames` respectively.
  """
  def __init__(self):
    self._inputs = {}
    self._all_frames = {}

  def fake_pandas_module(self):
    return FakePandasObject(pandas_top_level_functions.pd_wrapper, self)

  @contextlib.contextmanager
  def _monkey_patch_type(self, deferred_type):
    """Monkey-patch __init__ to record a pointer to all created frames, and
    __repr__ to be able to recognize them in the doctest output.
    """
    try:
      old_init, old_repr = deferred_type.__init__, deferred_type.__repr__

      def new_init(df, *args, **kwargs):
        old_init(df, *args, **kwargs)
        self._all_frames[id(df)] = df

      deferred_type.__init__ = new_init
      deferred_type.__repr__ = lambda self: 'DeferredBase[%s]' % id(self)
      self._recorded_results = collections.defaultdict(list)
      yield
    finally:
      deferred_type.__init__, deferred_type.__repr__ = old_init, old_repr

  @contextlib.contextmanager
  def context(self):
    """Creates a context within which DeferredBase types are monkey patched
    to record ids."""
    with contextlib.ExitStack() as stack:
      for deferred_type in DeferredBase._pandas_type_map.values():
        stack.enter_context(self._monkey_patch_type(deferred_type))
      yield


class _InMemoryResultRecorder(object):
  """Helper for extracting computed results from a Beam pipeline.

  Used as follows::

  with _InMemoryResultRecorder() as recorder:
    with beam.Pipeline() as p:
      ...
      pcoll | beam.Map(recorder.record_fn(name))

    seen = recorder.get_recorded(name)
  """

  # Class-level value to survive pickling.
  _ALL_RESULTS: dict[str, list[Any]] = {}

  def __init__(self):
    self._id = id(self)

  def __enter__(self):
    self._ALL_RESULTS[self._id] = collections.defaultdict(list)
    return self

  def __exit__(self, *unused_args):
    del self._ALL_RESULTS[self._id]

  def record_fn(self, name):
    def record(value):
      self._ALL_RESULTS[self._id][name].append(value)

    return record

  def get_recorded(self, name):
    return self._ALL_RESULTS[self._id][name]


WONT_IMPLEMENT = 'apache_beam.dataframe.frame_base.WontImplementError'
NOT_IMPLEMENTED = 'NotImplementedError'


class _DeferrredDataframeOutputChecker(doctest.OutputChecker):
  """Validates output by replacing DeferredBase[...] with computed values.
  """
  def __init__(self, env, use_beam):
    self._env = env
    if use_beam:
      self.compute = self.compute_using_beam
    else:
      self.compute = self.compute_using_session
    self.reset()

  def reset(self):
    self._last_error = None

  def compute_using_session(self, to_compute):
    session = expressions.PartitioningSession(self._env._inputs)
    return {
        name: session.evaluate(frame._expr)
        for name, frame in to_compute.items()
    }

  def compute_using_beam(self, to_compute):
    with _InMemoryResultRecorder() as recorder:
      with beam.Pipeline() as p:
        input_pcolls = {
            placeholder: p
            | 'Create%s' % placeholder >> beam.Create([input[::2], input[1::2]])
            for placeholder, input in self._env._inputs.items()
        }
        output_pcolls = (
            input_pcolls | transforms._DataframeExpressionsTransform({
                name: frame._expr
                for name, frame in to_compute.items()
            }))
        for name, output_pcoll in output_pcolls.items():
          _ = output_pcoll | 'Record%s' % name >> beam.FlatMap(
              recorder.record_fn(name))
      # pipeline runs, side effects recorded

      def concat(values):
        if len(values) > 1:
          return pd.concat(values)
        else:
          return values[0]

      return {
          name: concat(recorder.get_recorded(name))
          for name in to_compute.keys()
      }

  def fix(self, want, got):
    if 'DeferredBase' in got:
      # When we have a tuple of Dataframes, pandas prints each from a new line.
      got = re.sub(r'DeferredBase\[(\d+)\],', '\\g<0>\n', got)
      try:
        to_compute = {
            m.group(0): self._env._all_frames[int(m.group(1))]
            for m in re.finditer(r'DeferredBase\[(\d+)\]', got)
        }
        computed = self.compute(to_compute)
        for name, frame in computed.items():
          got = got.replace(name, repr(frame))

        # If a multiindex is used, compensate for it
        if any(isinstance(frame, pd.core.generic.NDFrame) and
               frame.index.nlevels > 1 for frame in computed.values()):

          def fill_multiindex(text):
            """An awful hack to work around the fact that pandas omits repeated
            elements in a multi-index.
            For example:

              Series name  Row ID
              s1           0         a
                           1         b
              s2           0         c
                           1         d
              dtype: object

            The s1 and s2 are implied for the 2nd and 4th rows. However if we
            re-order this Series it might be printed this way:

              Series name  Row ID
              s1           0         a
              s2           1         d
              s2           0         c
              s1           1         b
              dtype: object

            In our model these are equivalent, but when we sort the lines and
            check equality they are not. This method fills in any omitted
            multiindex values, so that we can successfully sort and compare."""
            lines = [list(line) for line in text.split('\n')]
            for prev, line in zip(lines[:-1], lines[1:]):
              if all(l == ' ' for l in line):
                continue

              for i, l in enumerate(line):
                if l != ' ':
                  break
                line[i] = prev[i]

            return '\n'.join(''.join(line) for line in lines)

          got = fill_multiindex(got)
          want = fill_multiindex(want)

        def sort_and_normalize(text):
          return '\n'.join(
              sorted(
                  [line.rstrip() for line in text.split('\n') if line.strip()],
                  key=str.strip)) + '\n'

        got = sort_and_normalize(got)
        want = sort_and_normalize(want)
      except Exception:
        got = traceback.format_exc()

    if 'NumpyExtensionArray' in got:
      # Work around formatting differences (np.int32(1) vs 1).
      got = re.sub('np.(int32|str_)[(]([^()]+)[)]', r'\2', got)
      got = re.sub('np.complex128[(]([^()]+)[)]', r'(\1)', got)

    return want, got

  @property
  def _seen_error(self):
    return self._last_error is not None

  def check_output(self, want, got, optionflags):
    # When an error occurs check_output is called with want=example.exc_msg,
    # and got=exc_msg

    # First check if `want` is a special string indicating wont_implement_ok
    # and/or not_implemented_ok
    allowed_exceptions = want.split('|')
    if all(exc in (WONT_IMPLEMENT, NOT_IMPLEMENTED)
           for exc in allowed_exceptions):
      # If it is, check for WontImplementError and NotImplementedError
      if WONT_IMPLEMENT in allowed_exceptions and got.startswith(
          WONT_IMPLEMENT):
        self._last_error = WONT_IMPLEMENT
        return True

      elif NOT_IMPLEMENTED in allowed_exceptions and got.startswith(
          NOT_IMPLEMENTED):
        self._last_error = NOT_IMPLEMENTED
        return True

      elif got.startswith('NameError') and self._seen_error:
        # This allows us to gracefully skip tests like
        #    >>> res = df.unsupported_operation()
        #    >>> check(res)
        return True

    self.reset()
    want, got = self.fix(want, got)
    return super().check_output(want, got, optionflags)

  def output_difference(self, example, got, optionflags):
    want, got = self.fix(example.want, got)
    if want != example.want:
      example = doctest.Example(
          example.source,
          want,
          example.exc_msg,
          example.lineno,
          example.indent,
          example.options)
    return super().output_difference(example, got, optionflags)


class BeamDataframeDoctestRunner(doctest.DocTestRunner):
  """A Doctest runner suitable for replacing the `pd` module with one backed
  by beam.
  """
  def __init__(
      self,
      env,
      use_beam=True,
      wont_implement_ok=None,
      not_implemented_ok=None,
      skip=None,
      **kwargs):
    self._test_env = env

    def to_callable(cond):
      if cond == '*':
        return lambda example: True
      else:
        return lambda example: example.source.strip() == cond

    self._wont_implement_ok = {
        test: [to_callable(cond) for cond in examples]
        for test, examples in (wont_implement_ok or {}).items()
    }
    self._not_implemented_ok = {
        test: [to_callable(cond) for cond in examples]
        for test, examples in (not_implemented_ok or {}).items()
    }
    self._skip = {
        test: [to_callable(cond) for cond in examples]
        for test, examples in (skip or {}).items()
    }
    super().__init__(
        checker=_DeferrredDataframeOutputChecker(self._test_env, use_beam),
        **kwargs)
    self.success = 0
    self.skipped = 0
    self._reasons = collections.defaultdict(list)
    self._skipped_set = set()

  def _is_wont_implement_ok(self, example, test):
    always_wont_implement = self._wont_implement_ok.get('*', [])
    return any(
        wont_implement(example) for wont_implement in (
            self._wont_implement_ok.get(test.name, []) + always_wont_implement))

  def _is_not_implemented_ok(self, example, test):
    always_not_impl = self._not_implemented_ok.get('*', [])
    return any(
        not_implemented(example) for not_implemented in (
            self._not_implemented_ok.get(test.name, []) + always_not_impl))

  def run(self, test, **kwargs):
    self._checker.reset()
    always_skip = self._skip.get('*', [])
    for example in test.examples:
      if any(should_skip(example)
             for should_skip in self._skip.get(test.name, []) + always_skip):
        self._skipped_set.add(example)
        example.source = 'pass'
        example.want = ''
        self.skipped += 1
      elif example.exc_msg is None:
        allowed_exceptions = []
        if self._is_not_implemented_ok(example, test):
          allowed_exceptions.append(NOT_IMPLEMENTED)
        if self._is_wont_implement_ok(example, test):
          allowed_exceptions.append(WONT_IMPLEMENT)

        if len(allowed_exceptions):
          # Don't fail doctests that raise this error.
          example.exc_msg = '|'.join(allowed_exceptions)
    with self._test_env.context():
      result = super().run(test, **kwargs)
      # Can't add attributes to builtin result.
      result = AugmentedTestResults(result.failed, result.attempted)
      result.summary = self.summary()
      return result

  def report_success(self, out, test, example, got):
    def extract_concise_reason(got, expected_exc):
      m = re.search(r"Implement(?:ed)?Error:\s+(.*)\n$", got)
      if m:
        return m.group(1)
      elif "NameError" in got:
        return "NameError following %s" % expected_exc
      elif re.match(r"DeferredBase\[\d+\]\n", got):
        return "DeferredBase[*]"
      else:
        return got.replace("\n", "\\n")

    if self._checker._last_error is not None:
      self._reasons[self._checker._last_error].append(
          extract_concise_reason(got, self._checker._last_error))

    if self._checker._seen_error:
      m = re.search('^([a-zA-Z0-9_, ]+)=', example.source)
      if m:
        for var in m.group(1).split(','):
          var = var.strip()
          if var in test.globs:
            # More informative to get a NameError than
            # use the wrong previous value.
            del test.globs[var]

    return super().report_success(out, test, example, got)

  def fake_pandas_module(self):
    return self._test_env.fake_pandas_module()

  def summarize(self):
    super().summarize()
    self.summary().summarize()

  def summary(self):
    return Summary(self.failures, self.tries, self.skipped, self._reasons)


class AugmentedTestResults(doctest.TestResults):
  pass


class Summary(object):
  def __init__(self, failures=0, tries=0, skipped=0, error_reasons=None):
    self.failures = failures
    self.tries = tries
    self.skipped = skipped
    self.error_reasons = error_reasons or collections.defaultdict(list)

  def result(self):
    res = AugmentedTestResults(self.failures, self.tries)
    res.summary = self
    return res

  def __add__(self, other):
    merged_reasons = {
        key: self.error_reasons.get(key, []) + other.error_reasons.get(key, [])
        for key in set(self.error_reasons.keys()).union(
            other.error_reasons.keys())
    }
    return Summary(
        self.failures + other.failures,
        self.tries + other.tries,
        self.skipped + other.skipped,
        merged_reasons)

  def summarize(self):
    def print_partition(indent, desc, n, total):
      print("%s%d %s (%.1f%%)" % ("  " * indent, n, desc, n / total * 100))

    print()
    print("%d total test cases:" % self.tries)

    if not self.tries:
      return

    print_partition(1, "skipped", self.skipped, self.tries)
    for error, reasons in self.error_reasons.items():
      print_partition(1, error, len(reasons), self.tries)
      reason_counts = sorted(
          collections.Counter(reasons).items(),
          key=lambda x: x[1],
          reverse=True)
      for desc, count in reason_counts:
        print_partition(2, desc, count, len(reasons))
    print_partition(1, "failed", self.failures, self.tries)
    print_partition(
        1,
        "passed",
        self.tries - self.skipped -
        sum(len(reasons)
            for reasons in self.error_reasons.values()) - self.failures,
        self.tries)
    print()


def parse_rst_ipython_tests(rst, name, extraglobs=None, optionflags=None):
  """Extracts examples from an rst file and produce a test suite by running
  them through pandas to get the expected outputs.
  """

  # Optional dependency.
  import IPython
  from traitlets.config import Config

  def get_indent(line):
    return len(line) - len(line.lstrip())

  def is_example_line(line):
    line = line.strip()
    return line and not line.startswith('#') and not line[0] == line[-1] == ':'

  IMPORT_PANDAS = 'import pandas as pd'

  example_srcs = []
  lines = iter([(lineno, line.rstrip())
                for lineno, line in enumerate(rst.split('\n'))
                if is_example_line(line)] + [(None, 'END')])

  # https://ipython.readthedocs.io/en/stable/sphinxext.html
  lineno, line = next(lines)
  while True:
    if line == 'END':
      break
    if line.startswith('.. ipython::'):
      lineno, line = next(lines)
      indent = get_indent(line)
      example = []
      example_srcs.append((lineno, example))
      while get_indent(line) >= indent:
        if '@verbatim' in line or ':verbatim:' in line or '@savefig' in line:
          example_srcs.pop()
          break
        line = re.sub(r'In \[\d+\]: ', '', line)
        line = re.sub(r'\.\.\.+:', '', line)
        example.append(line[indent:])
        lineno, line = next(lines)
        if get_indent(line) == indent and line[indent] not in ')]}':
          example = []
          example_srcs.append((lineno, example))
    else:
      lineno, line = next(lines)

  # TODO(robertwb): Would it be better to try and detect/compare the actual
  # objects in two parallel sessions than make (stringified) doctests?
  examples = []

  config = Config()
  config.HistoryManager.hist_file = ':memory:'
  config.InteractiveShell.autocall = False
  config.InteractiveShell.autoindent = False
  config.InteractiveShell.colors = 'NoColor'

  set_pandas_options()
  IP = IPython.InteractiveShell.instance(config=config)
  IP.run_cell(IMPORT_PANDAS + '\n')
  IP.run_cell('import numpy as np\n')
  try:
    stdout = sys.stdout
    for lineno, src in example_srcs:
      sys.stdout = cout = StringIO()
      src = '\n'.join(src)
      if src == IMPORT_PANDAS:
        continue
      IP.run_cell(src + '\n')
      output = cout.getvalue()
      if output:
        # Strip the prompt.
        # TODO(robertwb): Figure out how to suppress this.
        output = re.sub(r'^Out\[\d+\]:[ \t]*\n?', '', output)
      examples.append(doctest.Example(src, output, lineno=lineno))

  finally:
    sys.stdout = stdout

  return doctest.DocTest(
      examples, dict(extraglobs or {}, np=np), name, name, None, None)


def test_rst_ipython(
    rst,
    name,
    report=False,
    wont_implement_ok=(),
    not_implemented_ok=(),
    skip=(),
    **kwargs):
  """Extracts examples from an rst file and run them through pandas to get the
  expected output, and then compare them against our dataframe implementation.
  """
  def run_tests(extraglobs, optionflags, **kwargs):
    # The patched one.
    tests = parse_rst_ipython_tests(rst, name, extraglobs, optionflags)
    runner = doctest.DocTestRunner(optionflags=optionflags)
    set_pandas_options()
    result = runner.run(tests, **kwargs)
    if report:
      runner.summarize()
    return result

  result = _run_patched(
      run_tests,
      wont_implement_ok={name: wont_implement_ok},
      not_implemented_ok={name: not_implemented_ok},
      skip={name: skip},
      **kwargs)
  return result


def teststring(text, wont_implement_ok=None, not_implemented_ok=None, **kwargs):
  return teststrings(
      {'<string>': text},
      wont_implement_ok={'<string>': ['*']} if wont_implement_ok else None,
      not_implemented_ok={'<string>': ['*']} if not_implemented_ok else None,
      **kwargs)


def teststrings(texts, report=False, **runner_kwargs):
  optionflags = runner_kwargs.pop('optionflags', 0)
  optionflags |= (
      doctest.NORMALIZE_WHITESPACE | doctest.IGNORE_EXCEPTION_DETAIL)

  parser = doctest.DocTestParser()
  runner = BeamDataframeDoctestRunner(
      TestEnvironment(), optionflags=optionflags, **runner_kwargs)
  globs = {
      'pd': runner.fake_pandas_module(),
      'np': np,
      'option_context': pd.option_context,
  }
  with expressions.allow_non_parallel_operations():
    for name, text in texts.items():
      test = parser.get_doctest(text, globs, name, name, 0)
      runner.run(test)
  if report:
    runner.summarize()
  return runner.summary().result()


def set_pandas_options():
  # See
  # https://github.com/pandas-dev/pandas/blob/a00202d12d399662b8045a8dd3fdac04f18e1e55/doc/source/conf.py#L319
  np.random.seed(123456)
  legacy = None
  if np.version.version.startswith('2'):
    legacy = '1.25'
  np.set_printoptions(precision=4, suppress=True, legacy=legacy)
  pd.options.display.max_rows = 15


def _run_patched(func, *args, **kwargs):
  set_pandas_options()

  # https://github.com/pandas-dev/pandas/blob/1.0.x/setup.cfg#L63
  optionflags = kwargs.pop('optionflags', 0)
  optionflags |= (
      doctest.NORMALIZE_WHITESPACE | doctest.IGNORE_EXCEPTION_DETAIL)

  env = TestEnvironment()
  use_beam = kwargs.pop('use_beam', True)
  skip = kwargs.pop('skip', {})
  wont_implement_ok = kwargs.pop('wont_implement_ok', {})
  not_implemented_ok = kwargs.pop('not_implemented_ok', {})
  extraglobs = dict(kwargs.pop('extraglobs', {}))
  extraglobs['pd'] = env.fake_pandas_module()

  try:
    # Unfortunately the runner is not injectable.
    original_doc_test_runner = doctest.DocTestRunner
    doctest.DocTestRunner = lambda **kwargs: BeamDataframeDoctestRunner(
        env, use_beam=use_beam, wont_implement_ok=wont_implement_ok,
        not_implemented_ok=not_implemented_ok, skip=skip, **kwargs)
    with expressions.allow_non_parallel_operations():
      return func(
          *args, extraglobs=extraglobs, optionflags=optionflags, **kwargs)
  finally:
    doctest.DocTestRunner = original_doc_test_runner


def with_run_patched_docstring(target=None):
  assert target is not None

  def wrapper(fn):
    fn.__doc__ = f"""Run all pandas doctests in the specified {target}.

    Arguments `skip`, `wont_implement_ok`, `not_implemented_ok` are all in the
    format::

      {{
         "module.Class.method": ['*'],
         "module.Class.other_method": [
           'instance.other_method(bad_input)',
           'observe_result_of_bad_input()',
         ],
      }}

    `'*'` indicates all examples should be matched, otherwise the list is a list
    of specific input strings that should be matched.

    All arguments are kwargs.

    Args:
      optionflags (int): Passed through to doctests.
      extraglobs (dict[str,Any]): Passed through to doctests.
      use_beam (bool): If true, run a Beam pipeline with partitioned input to
        verify the examples, else use PartitioningSession to simulate
        distributed execution.
      skip (dict[str,str]): A set of examples to skip entirely.
        If a key is '*', an example will be skipped in all test scenarios.
      wont_implement_ok (dict[str,str]): A set of examples that are allowed to
        raise WontImplementError.
      not_implemented_ok (dict[str,str]): A set of examples that are allowed to
        raise NotImplementedError.

    Returns:
      ~doctest.TestResults: A doctest result describing the passed/failed tests.
    """
    return fn

  return wrapper


@with_run_patched_docstring(target="file")
def testfile(*args, **kwargs):
  return _run_patched(doctest.testfile, *args, **kwargs)


@with_run_patched_docstring(target="module")
def testmod(*args, **kwargs):
  return _run_patched(doctest.testmod, *args, **kwargs)
