#
# Licensed 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 contextlib
import unittest

import pytest
from mock import Mock, call, patch

from apache.aurora.client.api.job_monitor import JobMonitor
from apache.aurora.client.cli import Context
from apache.aurora.client.cli.client import AuroraCommandLine
from apache.aurora.client.cli.jobs import KillAllJobCommand, KillCommand
from apache.aurora.client.cli.options import TaskInstanceKey, parse_instances

from .util import AuroraClientCommandTest, FakeAuroraCommandContext, mock_verb_options

from gen.apache.aurora.api.constants import ACTIVE_STATES
from gen.apache.aurora.api.ttypes import (
    JobKey,
    ResponseCode,
    Result,
    ScheduleStatus,
    ScheduleStatusResult,
    TaskQuery
)


class TestInstancesParser(unittest.TestCase):
  def test_parse_instances(self):
    instances = '0,1-3,5'
    x = parse_instances(instances)
    assert x == [0, 1, 2, 3, 5]

  def test_parse_none(self):
    assert parse_instances(None) is None
    assert parse_instances("") is None


class TestKillCommand(AuroraClientCommandTest):

  def test_kill_updating_error_nobatch(self):
    """Verify that the no batch code path correctly includes the lock error message."""
    command = KillCommand()
    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [])
    mock_options.no_batching = True

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)
    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    mock_api = fake_context.get_api('test')
    mock_api.kill_job.return_value = AuroraClientCommandTest.create_blank_response(
      ResponseCode.JOB_UPDATING_ERROR, "Error.")

    with pytest.raises(Context.CommandError):
      command.execute(fake_context)

    mock_api.kill_job.assert_called_once_with(
        self.TEST_JOBKEY,
        mock_options.instance_spec.instance,
        config=None,
        message=None)

    self.assert_lock_message(fake_context)

  def test_kill_updating_error_batches(self):
    """Verify that the batch kill path short circuits and includes the lock error message."""
    command = KillCommand()
    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1])
    mock_options.no_batching = False

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)

    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(
      AuroraClientCommandTest.create_query_call_result(
        AuroraClientCommandTest.create_scheduled_task(1, ScheduleStatus.RUNNING)))

    mock_api = fake_context.get_api('test')
    mock_api.kill_job.return_value = AuroraClientCommandTest.create_blank_response(
      ResponseCode.JOB_UPDATING_ERROR, "Error.")

    with pytest.raises(Context.CommandError):
      command.execute(fake_context)

    mock_api.kill_job.assert_called_once_with(
        self.TEST_JOBKEY,
        mock_options.instance_spec.instance,
        config=None,
        message=None)

    self.assert_lock_message(fake_context)

  def test_kill_inactive_instance_spec(self):
    """Verify the instance spec is validated in a batched kill."""
    command = KillCommand()
    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1])
    mock_options.no_batching = False
    mock_options.strict = True

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)

    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(AuroraClientCommandTest.create_empty_task_result())

    with pytest.raises(Context.CommandError) as e:
      command.execute(fake_context)
    assert e.value.message == "Invalid instance parameter: [1]"

  def test_kill_batched_queries_active_instances(self):
    """Verify that the batch kill operates on active instances only."""
    command = KillCommand()
    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1])
    mock_options.no_batching = False

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)

    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(AuroraClientCommandTest.create_empty_task_result())

    command.execute(fake_context)
    message = "No tasks to kill found for job %s" % self.TEST_JOBKEY.to_path()
    assert fake_context.get_err()[0] == message

  def test_kill_opens_url(self):
    """Verify the kill commands opens the job page if requested"""
    command = KillCommand()
    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1])
    mock_options.open_browser = True

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)

    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(AuroraClientCommandTest.create_empty_task_result())

    command.execute(fake_context)

    assert self.mock_webbrowser.mock_calls == [
        call("http://something_or_other/scheduler/bozo/test/hello")
    ]

  def test_kill_nobatch_passes_config(self):
    """Verify that the no batch code path correctly passes job config to the api."""
    command = KillCommand()
    config = self.get_valid_config()

    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [])
    mock_options.no_batching = True
    mock_options.config = config

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)
    fake_context.add_config(config)

    mock_api = fake_context.get_api('test')
    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(AuroraClientCommandTest.create_empty_task_result())
    mock_api.kill_job.return_value = self.create_simple_success_response()

    command.execute(fake_context)

    assert mock_api.kill_job.mock_calls == [
        call(self.TEST_JOBKEY, mock_options.instance_spec.instance, config=config, message=None)
    ]

  def test_kill_batched_passes_config(self):
    """Verify that the batched code path correctly passes job config to the api."""
    command = KillCommand()
    config = self.get_valid_config()

    mock_options = mock_verb_options(command)
    mock_options.instance_spec = TaskInstanceKey(self.TEST_JOBKEY, [1])
    mock_options.no_batching = False
    mock_options.config = config

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)
    fake_context.add_config(config)

    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(
      AuroraClientCommandTest.create_query_call_result(
        AuroraClientCommandTest.create_scheduled_task(1, ScheduleStatus.RUNNING)))

    mock_api = fake_context.get_api('test')
    mock_api.kill_job.return_value = self.create_simple_success_response()
    command.execute(fake_context)

    assert mock_api.kill_job.mock_calls == [
        call(self.TEST_JOBKEY, mock_options.instance_spec.instance, config=config, message=None)
    ]


class TestKillAllCommand(AuroraClientCommandTest):
  def test_killall_nobatch_passes_config(self):
    """Verify that the no batch code path correctly passes job config to the api."""
    command = KillAllJobCommand()
    config = self.get_valid_config()

    mock_options = mock_verb_options(command)
    mock_options.jobspec = self.TEST_JOBKEY
    mock_options.no_batching = True
    mock_options.config = config

    fake_context = FakeAuroraCommandContext()
    fake_context.set_options(mock_options)
    fake_context.add_config(config)

    mock_api = fake_context.get_api('test')
    fake_context.add_expected_query_result(
      self.create_query_call_result(), job_key=self.TEST_JOBKEY)
    fake_context.add_expected_query_result(AuroraClientCommandTest.create_empty_task_result())
    mock_api.kill_job.return_value = self.create_simple_success_response()

    command.execute(fake_context)

    assert mock_api.kill_job.mock_calls == [
        call(self.TEST_JOBKEY, None, config=config, message=None)
    ]


class TestClientKillCommand(AuroraClientCommandTest):
  @classmethod
  def get_expected_task_query(cls, instances=None):
    instance_ids = frozenset(instances) if instances is not None else None
    return TaskQuery(taskIds=None,
                     instanceIds=instance_ids,
                     jobKeys=[JobKey(role=cls.TEST_ROLE,
                                     environment=cls.TEST_ENV,
                                     name=cls.TEST_JOB)])

  @classmethod
  def get_monitor_mock(cls, result=True):
    mock_monitor = Mock(spec=JobMonitor)
    mock_monitor.wait_until.return_value = result
    return mock_monitor

  @classmethod
  def assert_kill_calls(cls, api, instance_range=None, instances=None, message=None):
    if instances:
      kill_calls = [call(cls.TEST_JOBKEY, instances, config=None, message=message)]
    else:
      kill_calls = [
          call(cls.TEST_JOBKEY, [i], config=None, message=message)
          for i in instance_range
      ]
    assert api.kill_job.mock_calls == kill_calls

  @classmethod
  def assert_wait_calls(cls, mock_monitor, terminal, instance_range=None, instances=None):
    if instances:
      wait_calls = [call(terminal, instances=instances, with_timeout=True)]
    else:
      wait_calls = [call(terminal, instances=[i], with_timeout=True) for i in instance_range]
    assert mock_monitor.wait_until.mock_calls == wait_calls

  @classmethod
  def assert_kill_call_no_instances(cls, api):
    assert api.kill_job.mock_calls == [call(cls.TEST_JOBKEY, None, config=None, message=None)]

  @classmethod
  def assert_query(cls, fake_api, times=1):
    calls = [call(TaskQuery(jobKeys=[cls.TEST_JOBKEY.to_thrift()], statuses=ACTIVE_STATES))
      for _ in range(times)]
    assert fake_api.query_no_configs.mock_calls == calls

  def test_killall_job(self):
    """Test killall client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):

      api = mock_context.get_api('west')
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'killall', '--no-batching', self.TEST_JOBSPEC])

      self.assert_kill_call_no_instances(api)
      assert mock_monitor.wait_until.mock_calls == [
          call(m.terminal, instances=None, with_timeout=True)]

  def test_killall_job_batched(self):
    """Test killall command with batching."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):

      api = mock_context.get_api('west')
      api.kill_job.return_value = self.create_simple_success_response()
      mock_context.add_expected_query_result(
          self.create_query_call_result(), job_key=self.TEST_JOBKEY)

      cmd = AuroraCommandLine()
      cmd.execute(['job', 'killall', self.TEST_JOBSPEC])

      self.assert_kill_calls(api, instance_range=range(20), message=None)
      self.assert_wait_calls(mock_monitor, m.terminal, instance_range=range(20))
      self.assert_query(api)

  def test_kill_job_with_instances_nobatching(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--no-batching', self.get_instance_spec('0,2,4-6')])

      instances = [0, 2, 4, 5, 6]
      self.assert_kill_calls(api, instances=instances, message=None)
      self.assert_wait_calls(mock_monitor, m.terminal, instances=instances)
      self.assert_query(api)

  def test_kill_job_with_invalid_instances_strict(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context)):
      api = mock_context.get_api('west')
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--no-batching', '--strict',
           self.get_instance_spec('0,2,4-6,11-20')])

      assert api.kill_job.call_count == 0

  def test_kill_job_with_invalid_instances_nonstrict(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--no-batching', self.get_instance_spec('0,2,4-6,11-13')])
      instances = [0, 2, 4, 5, 6, 11, 12, 13]
      self.assert_kill_calls(api, instances=instances, message=None)
      self.assert_wait_calls(mock_monitor, m.terminal, instances=instances)
      self.assert_query(api)

  def test_kill_job_with_instances_batched(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)

      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', self.get_instance_spec('0-6')])

      self.assert_kill_calls(api, instance_range=range(7))
      self.assert_wait_calls(mock_monitor, m.terminal, instance_range=range(7))
      self.assert_query(api, times=2)

  def test_kill_job_with_instances_batched_maxerrors(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock(result=False)
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)

      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--max-total-failures=1', self.get_instance_spec('0-4')])

      # We should have aborted after the second batch.
      self.assert_kill_calls(api, instance_range=range(2), message=None)
      self.assert_query(api, times=2)

  def test_kill_job_with_empty_instances_batched(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context)):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      # set up an empty instance list in the getTasksWithoutConfigs response
      status_response = self.create_simple_success_response()
      status_response.result = Result(scheduleStatusResult=ScheduleStatusResult(tasks=[]))
      mock_context.add_expected_query_result(status_response)
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', self.get_instance_spec('0,2,4-13')])

      assert api.kill_job.call_count == 0
      self.assert_query(api, times=2)

  def test_killall_job_output(self):
    """Test kill output."""
    mock_context = FakeAuroraCommandContext()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=self.get_monitor_mock())):
      api = mock_context.get_api('west')
      api.kill_job.return_value = self.create_simple_success_response()

      cmd = AuroraCommandLine()
      cmd.execute(['job', 'killall', '--no-batching', self.TEST_JOBSPEC])

      assert mock_context.get_out() == ['Job killall succeeded']
      assert mock_context.get_err() == []

  def test_kill_job_with_instances_batched_output(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=self.get_monitor_mock())):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      mock_context.add_expected_query_result(self.create_query_call_result())
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--batch-size=5', self.get_instance_spec('0,2,4-6')])

    assert mock_context.get_out() == ['Successfully killed instances [0, 2, 4, 5, 6]',
        'Job kill succeeded']
    assert mock_context.get_err() == []
    self.assert_query(api, times=2)

  def test_kill_job_with_instances_batched_maxerrors_output(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock(result=False)
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      mock_context.add_expected_query_result(self.create_query_call_result())
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      cmd.execute(['job', 'kill', '--max-total-failures=1', '--batch-size=5',
          self.get_instance_spec('0,2,4-13')])

      assert mock_context.get_out() == []
      assert mock_context.get_err() == [
         'Instances [0, 2, 4, 5, 6] were not killed in time',
         'Instances [7, 8, 9, 10, 11] were not killed in time',
         'Exceeded maximum number of errors while killing instances']
      self.assert_query(api, times=2)

  def test_kill_job_with_message(self):
    """Test kill client-side API logic."""
    mock_context = FakeAuroraCommandContext()
    mock_monitor = self.get_monitor_mock()
    with contextlib.nested(
        patch('apache.aurora.client.cli.jobs.Job.create_context', return_value=mock_context),
        patch('apache.aurora.client.cli.jobs.JobMonitor', return_value=mock_monitor)) as (_, m):
      api = mock_context.get_api('west')
      mock_context.add_expected_query_result(
        self.create_query_call_result(), job_key=self.TEST_JOBKEY)
      api.kill_job.return_value = self.create_simple_success_response()
      cmd = AuroraCommandLine()
      message = 'Test message'
      cmd.execute(['job', 'kill', '--no-batch', '--message', message, self.get_instance_spec('0')])

      instances = [0]
      self.assert_kill_calls(api, instances=instances, message=message)
      self.assert_query(api)
