#
# 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.

import typing
import unittest
import warnings

import pandas as pd

import apache_beam as beam
from apache_beam import coders
from apache_beam import metrics
from apache_beam.dataframe import convert
from apache_beam.dataframe import expressions
from apache_beam.dataframe import frame_base
from apache_beam.dataframe import transforms
from apache_beam.runners.portability.fn_api_runner import fn_runner
from apache_beam.testing.util import assert_that
from apache_beam.testing.util import equal_to


def check_correct(expected, actual):
  if actual is None:
    raise AssertionError('Empty frame but expected: \n\n%s' % (expected))
  if isinstance(expected, pd.core.generic.NDFrame):
    expected = expected.sort_index()
    actual = actual.sort_index()

    if isinstance(expected, pd.Series):
      pd.testing.assert_series_equal(expected, actual)
    elif isinstance(expected, pd.DataFrame):
      pd.testing.assert_frame_equal(expected, actual)
    else:
      raise ValueError(
          f"Expected value is a {type(expected)},"
          "not a Series or DataFrame.")
  else:
    if actual != expected:
      raise AssertionError('Scalars not equal: %s != %s' % (actual, expected))


def concat(parts):
  if len(parts) > 1:
    return pd.concat(parts)
  elif len(parts) == 1:
    return parts[0]
  else:
    return None


def df_equal_to(expected):
  return lambda actual: check_correct(expected, concat(actual))


AnimalSpeed = typing.NamedTuple(
    'AnimalSpeed', [('Animal', str), ('Speed', int)])
coders.registry.register_coder(AnimalSpeed, coders.RowCoder)
Nested = typing.NamedTuple(
    'Nested', [('id', int), ('animal_speed', AnimalSpeed)])
coders.registry.register_coder(Nested, coders.RowCoder)


class TransformTest(unittest.TestCase):
  def run_scenario(self, input, func):
    expected = func(input)

    empty = input.iloc[0:0]
    input_placeholder = expressions.PlaceholderExpression(empty)
    input_deferred = frame_base.DeferredFrame.wrap(input_placeholder)
    actual_deferred = func(input_deferred)._expr.evaluate_at(
        expressions.Session({input_placeholder: input}))

    check_correct(expected, actual_deferred)

    with beam.Pipeline() as p:
      input_pcoll = p | beam.Create([input.iloc[::2], input.iloc[1::2]])
      input_df = convert.to_dataframe(input_pcoll, proxy=empty)
      output_df = func(input_df)

      output_proxy = output_df._expr.proxy()
      if isinstance(output_proxy, pd.core.generic.NDFrame):
        self.assertTrue(
            output_proxy.iloc[:0].equals(expected.iloc[:0]),
            (
                'Output proxy is incorrect:\n'
                f'Expected:\n{expected.iloc[:0]}\n\n'
                f'Actual:\n{output_proxy.iloc[:0]}'))
      else:
        self.assertEqual(type(output_proxy), type(expected))

      output_pcoll = convert.to_pcollection(output_df, yield_elements='pandas')

      assert_that(
          output_pcoll, lambda actual: check_correct(expected, concat(actual)))

  def test_identity(self):
    df = pd.DataFrame({
        'Animal': ['Falcon', 'Falcon', 'Parrot', 'Parrot'],
        'Speed': [380., 370., 24., 26.]
    })
    self.run_scenario(df, lambda x: x)

  def test_groupby_sum_mean(self):
    df = pd.DataFrame({
        'Animal': ['Falcon', 'Falcon', 'Parrot', 'Parrot'],
        'Speed': [380., 370., 24., 26.]
    })
    self.run_scenario(df, lambda df: df.groupby('Animal').sum())
    with expressions.allow_non_parallel_operations():
      self.run_scenario(df, lambda df: df.groupby('Animal').mean())
    self.run_scenario(
        df, lambda df: df.loc[df.Speed > 25].groupby('Animal').sum())

  def test_groupby_apply(self):
    df = pd.DataFrame({
        'group': ['a' if i % 5 == 0 or i % 3 == 0 else 'b' for i in range(100)],
        'foo': [None if i % 11 == 0 else i for i in range(100)],
        'bar': [None if i % 7 == 0 else 99 - i for i in range(100)],
        'baz': [None if i % 13 == 0 else i * 2 for i in range(100)],
    })

    def median_sum_fn(x):
      with warnings.catch_warnings():
        warnings.filterwarnings("ignore", message="Mean of empty slice")
        return (x.foo + x.bar).median()

    describe = lambda df: df.describe()

    self.run_scenario(df, lambda df: df.groupby('group').foo.apply(describe))
    self.run_scenario(
        df, lambda df: df.groupby('group')[['foo', 'bar']].apply(describe))
    self.run_scenario(df, lambda df: df.groupby('group').apply(median_sum_fn))
    self.run_scenario(
        df,
        lambda df: df.set_index('group').foo.groupby(level=0).apply(describe))
    self.run_scenario(df, lambda df: df.groupby(level=0).apply(median_sum_fn))
    self.run_scenario(
        df, lambda df: df.groupby(lambda x: x % 3).apply(describe))

  def test_filter(self):
    df = pd.DataFrame({
        'Animal': ['Aardvark', 'Ant', 'Elephant', 'Zebra'],
        'Speed': [5, 2, 35, 40]
    })
    self.run_scenario(df, lambda df: df.filter(items=['Animal']))
    self.run_scenario(df, lambda df: df.filter(regex='Anim.*'))
    self.run_scenario(
        df, lambda df: df.set_index('Animal').filter(regex='F.*', axis='index'))

    with expressions.allow_non_parallel_operations():
      a = pd.DataFrame({'col': [1, 2, 3]})
      self.run_scenario(a, lambda a: a.agg(sum))
      self.run_scenario(a, lambda a: a.agg(['mean', 'min', 'max']))

  def test_scalar(self):
    with expressions.allow_non_parallel_operations():
      a = pd.Series([1, 2, 6])
      self.run_scenario(a, lambda a: a.agg(sum))
      self.run_scenario(a, lambda a: a / a.agg(sum))
      self.run_scenario(a, lambda a: a / (a.max() - a.min()))
      self.run_scenario(a, lambda a: a / (a.sum() - 1))

      # Tests scalar being used as an input to a downstream stage.
      df = pd.DataFrame({'key': ['a', 'a', 'b'], 'val': [1, 2, 6]})
      self.run_scenario(
          df, lambda df: df.groupby('key').sum().val / df.val.agg(sum))

  def test_getitem_projection(self):
    df = pd.DataFrame({
        'Animal': ['Aardvark', 'Ant', 'Elephant', 'Zebra'],
        'Speed': [5, 2, 35, 40],
        'Size': ['Small', 'Extra Small', 'Large', 'Medium']
    })
    self.run_scenario(df, lambda df: df[['Speed', 'Size']])

  def test_offset_elementwise(self):
    s = pd.Series(range(10)).astype(float)
    df = pd.DataFrame({'value': s, 'square': s * s, 'cube': s * s * s})
    # Only those values that are both squares and cubes will intersect.
    self.run_scenario(
        df,
        lambda df: df.set_index('square').value + df.set_index('cube').value)

  def test_batching_named_tuple_input(self):
    with beam.Pipeline() as p:
      result = (
          p | beam.Create([
              AnimalSpeed('Aardvark', 5),
              AnimalSpeed('Ant', 2),
              AnimalSpeed('Elephant', 35),
              AnimalSpeed('Zebra', 40)
          ]).with_output_types(AnimalSpeed)
          | transforms.DataframeTransform(lambda df: df.filter(regex='Anim.*')))

      assert_that(
          result,
          equal_to([('Aardvark', ), ('Ant', ), ('Elephant', ), ('Zebra', )]))

  def test_batching_beam_row_input(self):
    with beam.Pipeline() as p:
      result = (
          p
          | beam.Create([('Falcon', 380.), ('Falcon', 370.), ('Parrot', 24.),
                         ('Parrot', 26.)])
          | beam.Map(lambda tpl: beam.Row(Animal=tpl[0], Speed=tpl[1]))
          | transforms.DataframeTransform(
              lambda df: df.groupby('Animal').mean(), include_indexes=True))

      assert_that(result, equal_to([('Falcon', 375.), ('Parrot', 25.)]))

  def test_batching_beam_row_to_dataframe(self):
    with beam.Pipeline() as p:
      df = convert.to_dataframe(
          p
          | beam.Create([('Falcon', 380.), ('Falcon', 370.), ('Parrot', 24.), (
              'Parrot', 26.)])
          | beam.Map(lambda tpl: beam.Row(Animal=tpl[0], Speed=tpl[1])))

      result = convert.to_pcollection(
          df.groupby('Animal').mean(), include_indexes=True)

      assert_that(result, equal_to([('Falcon', 375.), ('Parrot', 25.)]))

  def test_batching_passthrough_nested_schema(self):
    with beam.Pipeline() as p:
      nested_schema_pc = (
          p | beam.Create([Nested(1, AnimalSpeed('Aardvark', 5))
                           ]).with_output_types(Nested))
      result = nested_schema_pc | transforms.DataframeTransform(  # pylint: disable=expression-not-assigned
          lambda df: df.filter(items=['animal_speed']))

      assert_that(result, equal_to([(('Aardvark', 5), )]))

  def test_batching_passthrough_nested_array(self):
    Array = typing.NamedTuple(
        'Array', [('id', int), ('business_numbers', typing.Sequence[int])])
    coders.registry.register_coder(Array, coders.RowCoder)

    with beam.Pipeline() as p:
      array_schema_pc = (p | beam.Create([Array(1, [7, 8, 9])]))
      result = array_schema_pc | transforms.DataframeTransform(  # pylint: disable=expression-not-assigned
            lambda df: df.filter(items=['business_numbers']))

      assert_that(result, equal_to([([7, 8, 9], )]))

  def test_unbatching_series(self):
    with beam.Pipeline() as p:
      result = (
          p
          | beam.Create([('Falcon', 380.), ('Falcon', 370.), ('Parrot', 24.),
                         ('Parrot', 26.)])
          | beam.Map(lambda tpl: beam.Row(Animal=tpl[0], Speed=tpl[1]))
          | transforms.DataframeTransform(lambda df: df.Animal))

      assert_that(result, equal_to(['Falcon', 'Falcon', 'Parrot', 'Parrot']))

  def test_input_output_polymorphism(self):
    one_series = pd.Series([1])
    two_series = pd.Series([2])
    three_series = pd.Series([3])
    proxy = one_series[:0]

    def equal_to_series(expected):
      def check(actual):
        actual = pd.concat(actual)
        if not expected.equals(actual):
          raise AssertionError(
              'Series not equal: \n%s\n%s\n' % (expected, actual))

      return check

    with beam.Pipeline() as p:
      one = p | 'One' >> beam.Create([one_series])
      two = p | 'Two' >> beam.Create([two_series])

      assert_that(
          one | 'PcollInPcollOut' >> transforms.DataframeTransform(
              lambda x: 3 * x, proxy=proxy, yield_elements='pandas'),
          equal_to_series(three_series),
          label='CheckPcollInPcollOut')

      assert_that(
          (one, two)
          | 'TupleIn' >> transforms.DataframeTransform(
              lambda x, y: (x + y), (proxy, proxy), yield_elements='pandas'),
          equal_to_series(three_series),
          label='CheckTupleIn')

      assert_that(
          dict(x=one, y=two)
          | 'DictIn' >> transforms.DataframeTransform(
              lambda x, y: (x + y),
              proxy=dict(x=proxy, y=proxy),
              yield_elements='pandas'),
          equal_to_series(three_series),
          label='CheckDictIn')

      double, triple = one | 'TupleOut' >> transforms.DataframeTransform(
              lambda x: (2*x, 3*x), proxy, yield_elements='pandas')
      assert_that(double, equal_to_series(two_series), 'CheckTupleOut0')
      assert_that(triple, equal_to_series(three_series), 'CheckTupleOut1')

      res = one | 'DictOut' >> transforms.DataframeTransform(
          lambda x: {'res': 3 * x}, proxy, yield_elements='pandas')
      assert_that(res['res'], equal_to_series(three_series), 'CheckDictOut')

  def test_multiple_dataframes_transforms(self):
    expected_output = ["Bryan", "DKER2"]

    def transform_func(a, b):
      b["name"] = "DKER2"
      return a, b

    with beam.Pipeline() as p:
      pcol1 = p | "Create1" >> beam.Create([beam.Row(name="Bryan")])
      pcol2 = p | "Create2" >> beam.Create([beam.Row(name="common")])

      result = ({
          "a": pcol1, "b": pcol2
      }
                |
                "TransformDF" >> transforms.DataframeTransform(transform_func)
                | "Flatten" >> beam.Flatten()
                | transforms.DataframeTransform(lambda df: df.name))
      assert_that(result, equal_to(expected_output))

  def test_cat(self):
    # verify that cat works with a List[Series] since this is
    # missing from doctests
    df = pd.DataFrame({
        'one': ['A', 'B', 'C'],
        'two': ['BB', 'CC', 'A'],
        'three': ['CCC', 'AA', 'B'],
    })
    self.run_scenario(df, lambda df: df.two.str.cat([df.three], join='outer'))
    self.run_scenario(
        df, lambda df: df.one.str.cat([df.two, df.three], join='outer'))

  def test_repeat(self):
    # verify that repeat works with a Series since this is
    # missing from doctests
    df = pd.DataFrame({
        'strings': ['A', 'B', 'C', 'D', 'E'],
        'repeats': [3, 1, 4, 5, 2],
    })
    self.run_scenario(df, lambda df: df.strings.str.repeat(df.repeats))

  def test_rename(self):
    df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
    self.run_scenario(
        df, lambda df: df.rename(columns={'B': 'C'}, index={
            0: 2, 2: 0
        }))

    with expressions.allow_non_parallel_operations():
      self.run_scenario(
          df, lambda df: df.rename(
              columns={'B': 'C'}, index={
                  0: 2, 2: 0
              }, errors='raise'))


class FusionTest(unittest.TestCase):
  @staticmethod
  def fused_stages(p):
    return p.result.monitoring_metrics().query(
        metrics.MetricsFilter().with_name(
            fn_runner.FnApiRunner.NUM_FUSED_STAGES_COUNTER)
    )['counters'][0].result

  @staticmethod
  def create_animal_speed_input(p):
    return p | beam.Create([
        AnimalSpeed('Aardvark', 5),
        AnimalSpeed('Ant', 2),
        AnimalSpeed('Elephant', 35),
        AnimalSpeed('Zebra', 40)
    ],
                           reshuffle=False)

  def test_loc_filter(self):
    # TODO(https://github.com/apache/beam/issues/34549): This test relies on
    # monitoring_metrics property of the FnApiRunner which does not exist on
    # other runners like Prism.
    # https://github.com/apache/beam/blob/5f9cd73b7c9a2f37f83971ace3a399d633201dd1/sdks/python/apache_beam/runners/portability/fn_api_runner/fn_runner.py#L1590
    with beam.Pipeline('FnApiRunner') as p:
      _ = (
          self.create_animal_speed_input(p)
          | transforms.DataframeTransform(lambda df: df[df.Speed > 10]))
    self.assertEqual(self.fused_stages(p), 1)

  def test_column_manipulation(self):
    def set_column(df, name, s):
      df[name] = s
      return df

    # TODO(https://github.com/apache/beam/issues/34549): This test relies on
    # monitoring_metrics property of the FnApiRunner which does not exist on
    # other runners like Prism.
    # https://github.com/apache/beam/blob/5f9cd73b7c9a2f37f83971ace3a399d633201dd1/sdks/python/apache_beam/runners/portability/fn_api_runner/fn_runner.py#L1590
    with beam.Pipeline('FnApiRunner') as p:
      _ = (
          self.create_animal_speed_input(p)
          | transforms.DataframeTransform(
              lambda df: set_column(df, 'x', df.Speed + df.Animal.str.len())))
    self.assertEqual(self.fused_stages(p), 1)


class TransformPartsTest(unittest.TestCase):
  def test_rebatch(self):
    with beam.Pipeline() as p:
      sA = pd.Series(range(1000))
      sB = sA * sA
      pcA = p | 'CreatePCollA' >> beam.Create([('k0', sA[::3]),
                                               ('k1', sA[1::3]),
                                               ('k2', sA[2::3])])
      pcB = p | 'CreatePCollB' >> beam.Create([('k0', sB[::3]),
                                               ('k1', sB[1::3]),
                                               ('k2', sB[2::3])])
      input = {'A': pcA, 'B': pcB} | beam.CoGroupByKey()
      output = input | beam.ParDo(
          transforms._ReBatch(target_size=sA.memory_usage()))

      # There should be exactly two elements, as the target size will be
      # hit when 2/3 of pcA and 2/3 of pcB is seen, but not before.
      assert_that(output | beam.combiners.Count.Globally(), equal_to([2]))

      # Sanity check that we got all the right values.
      assert_that(
          output | beam.Map(lambda x: x['A'].sum())
          | 'SumA' >> beam.CombineGlobally(sum),
          equal_to([sA.sum()]),
          label='CheckValuesA')
      assert_that(
          output | beam.Map(lambda x: x['B'].sum())
          | 'SumB' >> beam.CombineGlobally(sum),
          equal_to([sB.sum()]),
          label='CheckValuesB')


if __name__ == '__main__':
  unittest.main()
