#
# 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 asyncio
import logging
import time
import unittest
from queue import Queue
from threading import Event, Thread

from skywalking.agent import (
    _abandon_async_queue,
    _abandon_sync_queue,
    _await_shutdown_or_background_failure,
    _cancel_pending_tasks,
    _join_sync_queue,
    _shutdown_async_queue,
    _shutdown_sync_queue,
)


class TestShutdownQueueHelpers(unittest.TestCase):

    def test_abandon_sync_queue_unblocks_join(self):
        q = Queue()
        q.put('a')
        q.put('b')
        self.assertEqual(q.unfinished_tasks, 2)

        hung = Event()

        def _join():
            q.join()
            hung.set()

        Thread(target=_join, daemon=True).start()
        time.sleep(0.05)
        self.assertFalse(hung.is_set())

        abandoned = _abandon_sync_queue(q)
        self.assertEqual(abandoned, 2)
        self.assertTrue(hung.wait(1.0))
        self.assertTrue(_join_sync_queue(q, 0.5))

    def test_shutdown_sync_skips_flush_when_not_ready(self):
        q = Queue()
        q.put('x')
        called = []

        def report():
            called.append(1)
            raise AssertionError('must not flush when may_send is False')

        _shutdown_sync_queue(report, q, 'test', may_send=False)
        self.assertEqual(called, [])
        self.assertTrue(q.empty())
        self.assertEqual(q.unfinished_tasks, 0)

    def test_shutdown_sync_flush_timeout_then_abandon(self):
        q = Queue()
        q.put('x')
        started = Event()

        def report():
            started.set()
            time.sleep(10)  # longer than flush budget

        # Temporarily shrink budget via monkeypatch on module constant
        import skywalking.agent as agent_mod

        previous = agent_mod._SHUTDOWN_FLUSH_TIMEOUT_SEC
        try:
            agent_mod._SHUTDOWN_FLUSH_TIMEOUT_SEC = 0.2
            t0 = time.monotonic()
            _shutdown_sync_queue(report, q, 'test', may_send=True)
            elapsed = time.monotonic() - t0
        finally:
            agent_mod._SHUTDOWN_FLUSH_TIMEOUT_SEC = previous

        self.assertTrue(started.wait(1.0))
        self.assertLess(elapsed, 2.0)
        self.assertTrue(q.empty())
        self.assertEqual(q.unfinished_tasks, 0)

    def test_abandon_async_queue_unblocks_join(self):
        async def _run():
            q = asyncio.Queue()
            await q.put('a')
            await q.put('b')
            join_task = asyncio.create_task(q.join())
            await asyncio.sleep(0.05)
            self.assertFalse(join_task.done())
            abandoned = await _abandon_async_queue(q)
            self.assertEqual(abandoned, 2)
            await asyncio.wait_for(join_task, timeout=1.0)

        asyncio.run(_run())

    def test_cancel_pending_tasks_excludes_caller(self):
        """Regression: gathering the caller's own task made shutdown hang until the outer budget."""
        loop = asyncio.new_event_loop()
        thread = Thread(target=loop.run_forever, daemon=True)
        thread.start()

        async def _forever():
            while True:
                await asyncio.sleep(0.05)

        try:
            async def _spawn():
                return [asyncio.create_task(_forever()) for _ in range(2)]

            reporter_tasks = asyncio.run_coroutine_threadsafe(_spawn(), loop).result(timeout=2.0)
            time.sleep(0.1)

            t0 = time.monotonic()
            future = asyncio.run_coroutine_threadsafe(_cancel_pending_tasks(reporter_tasks), loop)
            future.result(timeout=2.0)
            self.assertLess(time.monotonic() - t0, 2.0)
            for task in reporter_tasks:
                self.assertTrue(task.cancelled() or task.done())
        finally:
            loop.call_soon_threadsafe(loop.stop)
            thread.join(timeout=2.0)
            loop.close()

    def test_async_shutdown_cleanup_runs_inside_asyncio_run_root(self):
        """
        Production topology: root waits on _finished, then cancels reporters and
        awaits a yielding protocol aclose() before asyncio.run returns.
        """
        holder = {}
        aclose_entered = Event()
        aclose_done = Event()
        loop_ready = Event()

        async def yielding_aclose():
            aclose_entered.set()
            await asyncio.sleep(0.05)
            aclose_done.set()

        async def root():
            finished = asyncio.Event()
            holder['finished'] = finished
            holder['loop'] = asyncio.get_running_loop()

            async def reporter():
                while not finished.is_set():
                    await asyncio.sleep(0.02)

            tasks = {asyncio.create_task(reporter()) for _ in range(2)}
            loop_ready.set()
            await finished.wait()
            await _cancel_pending_tasks(tasks)
            await yielding_aclose()
            holder['root_finished'] = True

        thread = Thread(target=lambda: asyncio.run(root()), daemon=True)
        thread.start()
        self.assertTrue(loop_ready.wait(3.0))
        holder['loop'].call_soon_threadsafe(holder['finished'].set)
        thread.join(timeout=5.0)
        self.assertTrue(aclose_entered.wait(2.0))
        self.assertTrue(aclose_done.wait(2.0))
        self.assertTrue(holder.get('root_finished', False))

    def test_background_task_failure_is_logged_not_silenced(self):
        """Regression: failing background tasks must be observed and logged exactly once."""
        holder = {'errors': []}
        error_logged = Event()
        aclose_done = Event()

        class _Handler(logging.Handler):
            def emit(self, record):
                msg = record.getMessage()
                if 'Error in Python agent asyncio event loop' in msg:
                    holder['errors'].append(msg)
                    error_logged.set()

        agent_logger = logging.getLogger('skywalking')
        handler = _Handler()
        agent_logger.addHandler(handler)
        previous_level = agent_logger.level
        agent_logger.setLevel(logging.ERROR)

        async def failing_background():
            await asyncio.sleep(0.02)
            raise ValueError('command dispatch failed')

        async def yielding_aclose():
            await asyncio.sleep(0.02)
            aclose_done.set()

        async def root():
            finished = asyncio.Event()
            holder['finished'] = finished
            failing_task = asyncio.create_task(failing_background())

            async def reporter():
                while not finished.is_set():
                    await asyncio.sleep(0.05)

            reporter_task = asyncio.create_task(reporter())
            tasks = {failing_task, reporter_task}
            await _await_shutdown_or_background_failure(finished, tasks)
            await _cancel_pending_tasks(tasks)
            await yielding_aclose()
            holder['after_wait'] = True
            holder['failing_task'] = failing_task

        try:
            asyncio.run(root())
            self.assertTrue(holder.get('after_wait'))
            self.assertTrue(error_logged.wait(2.0))
            self.assertTrue(aclose_done.wait(2.0))
            self.assertEqual(len(holder['errors']), 1)
            self.assertIn('command dispatch failed', holder['errors'][0])
            self.assertTrue(holder['finished'].is_set())
            self.assertTrue(holder['failing_task'].done())
            self.assertIsInstance(holder['failing_task'].exception(), ValueError)
        finally:
            agent_logger.removeHandler(handler)
            agent_logger.setLevel(previous_level)

    def test_clean_shutdown_does_not_log_normal_background_completion(self):
        """Clean shutdown: reporters finish after _finished; cleanup must stay silent."""
        holder = {'errors': []}

        class _Handler(logging.Handler):
            def emit(self, record):
                if 'Error in Python agent asyncio event loop' in record.getMessage():
                    holder['errors'].append(record.getMessage())

        agent_logger = logging.getLogger('skywalking')
        handler = _Handler()
        agent_logger.addHandler(handler)
        previous_level = agent_logger.level
        agent_logger.setLevel(logging.ERROR)

        async def root():
            finished = asyncio.Event()

            async def reporter():
                while not finished.is_set():
                    await asyncio.sleep(0.01)

            tasks = {asyncio.create_task(reporter()) for _ in range(2)}
            finished.set()
            await _await_shutdown_or_background_failure(finished, tasks)
            # Give reporters a turn to observe _finished and return normally.
            await asyncio.sleep(0.05)
            await _cancel_pending_tasks(tasks)
            holder['all_done'] = all(task.done() for task in tasks)

        try:
            asyncio.run(root())
            self.assertTrue(holder.get('all_done'))
            self.assertEqual(holder['errors'], [])
        finally:
            agent_logger.removeHandler(handler)
            agent_logger.setLevel(previous_level)

    def test_unexpected_pre_shutdown_cancellation_is_logged(self):
        """Cancellation before shutdown must be logged and trigger orderly cleanup."""
        holder = {'errors': []}
        error_logged = Event()
        aclose_done = Event()

        class _Handler(logging.Handler):
            def emit(self, record):
                msg = record.getMessage()
                if 'Error in Python agent asyncio event loop' in msg:
                    holder['errors'].append(msg)
                    error_logged.set()

        agent_logger = logging.getLogger('skywalking')
        handler = _Handler()
        agent_logger.addHandler(handler)
        previous_level = agent_logger.level
        agent_logger.setLevel(logging.ERROR)

        async def cancelled_background():
            asyncio.current_task().cancel()
            await asyncio.sleep(0)

        async def yielding_aclose():
            await asyncio.sleep(0.02)
            aclose_done.set()

        async def root():
            finished = asyncio.Event()
            holder['finished'] = finished

            async def reporter():
                while not finished.is_set():
                    await asyncio.sleep(0.05)

            cancelled_task = asyncio.create_task(cancelled_background())
            reporter_task = asyncio.create_task(reporter())
            tasks = {cancelled_task, reporter_task}
            await _await_shutdown_or_background_failure(finished, tasks)
            await _cancel_pending_tasks(tasks)
            await yielding_aclose()
            holder['after_wait'] = True

        try:
            asyncio.run(root())
            self.assertTrue(holder.get('after_wait'))
            self.assertTrue(error_logged.wait(2.0))
            self.assertTrue(aclose_done.wait(2.0))
            self.assertEqual(len(holder['errors']), 1)
            self.assertIn('cancelled unexpectedly', holder['errors'][0])
            self.assertTrue(holder['finished'].is_set())
        finally:
            agent_logger.removeHandler(handler)
            agent_logger.setLevel(previous_level)

    def test_intentional_cleanup_cancellation_is_silent(self):
        """Tasks cancelled by _cancel_pending_tasks during cleanup must not ERROR."""
        holder = {'errors': []}

        class _Handler(logging.Handler):
            def emit(self, record):
                if 'Error in Python agent asyncio event loop' in record.getMessage():
                    holder['errors'].append(record.getMessage())

        agent_logger = logging.getLogger('skywalking')
        handler = _Handler()
        agent_logger.addHandler(handler)
        previous_level = agent_logger.level
        agent_logger.setLevel(logging.ERROR)

        async def forever():
            while True:
                await asyncio.sleep(0.05)

        async def root():
            tasks = {asyncio.create_task(forever()) for _ in range(2)}
            await _cancel_pending_tasks(tasks)
            holder['all_done'] = all(task.done() for task in tasks)

        try:
            asyncio.run(root())
            self.assertTrue(holder.get('all_done'))
            self.assertEqual(holder['errors'], [])
        finally:
            agent_logger.removeHandler(handler)
            agent_logger.setLevel(previous_level)

    def test_shutdown_async_queue_bounded(self):
        async def _run():
            q = asyncio.Queue()
            await q.put('a')
            t0 = time.monotonic()
            await _shutdown_async_queue(q, 'test')
            self.assertLess(time.monotonic() - t0, 2.0)
            self.assertTrue(q.empty())

        asyncio.run(_run())


if __name__ == '__main__':
    unittest.main()
