import unittest
from datetime import datetime, timedelta
from unittest.mock import patch, MagicMock
from pygeai.cli.commands.analytics import (
    resolve_date_range,
    get_agents_created_and_modified,
    get_total_cost
)
from pygeai.cli.commands import Option


class TestAnalyticsPeriodHelpers(unittest.TestCase):

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_last_week(self, mock_stdout):
        opts = {"last_week": ""}
        start_date, end_date = resolve_date_range(opts)
        expected_start = (datetime.now() - timedelta(weeks=1)).strftime("%Y-%m-%d")
        expected_end = datetime.now().strftime("%Y-%m-%d")
        self.assertEqual(start_date, expected_start)
        self.assertEqual(end_date, expected_end)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_last_day(self, mock_stdout):
        opts = {"last_day": ""}
        start_date, end_date = resolve_date_range(opts)
        yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
        self.assertEqual(start_date, yesterday)
        self.assertEqual(end_date, yesterday)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_last_month(self, mock_stdout):
        opts = {"last_month": ""}
        start_date, end_date = resolve_date_range(opts)
        today = datetime.now()
        if today.month == 1:
            last_month = 12
            year = today.year - 1
        else:
            last_month = today.month - 1
            year = today.year
        
        from calendar import monthrange
        first_day = datetime(year, last_month, 1)
        last_day_num = monthrange(year, last_month)[1]
        last_day = datetime(year, last_month, last_day_num)
        
        expected_start = first_day.strftime("%Y-%m-%d")
        expected_end = last_day.strftime("%Y-%m-%d")
        
        self.assertEqual(start_date, expected_start)
        self.assertEqual(end_date, expected_end)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_last_semester(self, mock_stdout):
        opts = {"last_semester": ""}
        start_date, end_date = resolve_date_range(opts)
        expected_start = (datetime.now() - timedelta(days=180)).strftime("%Y-%m-%d")
        expected_end = datetime.now().strftime("%Y-%m-%d")
        self.assertEqual(start_date, expected_start)
        self.assertEqual(end_date, expected_end)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_last_year(self, mock_stdout):
        opts = {"last_year": ""}
        start_date, end_date = resolve_date_range(opts)
        expected_start = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d")
        expected_end = datetime.now().strftime("%Y-%m-%d")
        self.assertEqual(start_date, expected_start)
        self.assertEqual(end_date, expected_end)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_manual_dates(self, mock_stdout):
        opts = {"start_date": "2024-01-01", "end_date": "2024-01-31"}
        start_date, end_date = resolve_date_range(opts)
        self.assertEqual(start_date, "2024-01-01")
        self.assertEqual(end_date, "2024-01-31")

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_period_overrides_manual(self, mock_stdout):
        opts = {
            "last_day": "",
            "start_date": "2024-01-01",
            "end_date": "2024-01-31"
        }
        start_date, end_date = resolve_date_range(opts)
        yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
        self.assertEqual(start_date, yesterday)
        self.assertEqual(end_date, yesterday)

    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_resolve_defaults(self, mock_stdout):
        opts = {}
        start_date, end_date = resolve_date_range(opts)
        today = datetime.now()
        if today.month == 1:
            last_month = 12
            year = today.year - 1
        else:
            last_month = today.month - 1
            year = today.year
        
        from calendar import monthrange
        first_day = datetime(year, last_month, 1)
        last_day_num = monthrange(year, last_month)[1]
        last_day = datetime(year, last_month, last_day_num)
        
        expected_start = first_day.strftime("%Y-%m-%d")
        expected_end = last_day.strftime("%Y-%m-%d")
        
        self.assertEqual(start_date, expected_start)
        self.assertEqual(end_date, expected_end)


class TestAnalyticsCommandsWithPeriods(unittest.TestCase):

    @patch('pygeai.cli.commands.analytics.AnalyticsManager')
    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_agents_created_with_period_shortcut(self, mock_stdout, mock_manager_class):
        mock_manager = MagicMock()
        mock_manager_class.return_value = mock_manager
        mock_response = MagicMock()
        mock_response.createdAgents = 15
        mock_response.modifiedAgents = 8
        mock_manager.get_agents_created_and_modified.return_value = mock_response
        
        option_list = [
            (Option("last_week", ["--last-week"], "", False), "")
        ]
        
        get_agents_created_and_modified(option_list)
        
        self.assertTrue(mock_manager.get_agents_created_and_modified.called)
        calls = [call[0][0] for call in mock_stdout.call_args_list]
        self.assertTrue(any("Using period: last-week" in call for call in calls))

    @patch('pygeai.cli.commands.analytics.AnalyticsManager')
    @patch('pygeai.cli.commands.analytics.Console.write_stdout')
    def test_total_cost_with_manual_dates(self, mock_stdout, mock_manager_class):
        mock_manager = MagicMock()
        mock_manager_class.return_value = mock_manager
        mock_response = MagicMock()
        mock_response.totalCost = 125.50
        mock_manager.get_total_cost.return_value = mock_response
        
        option_list = [
            (Option("start_date", ["--start-date"], "", True), "2024-01-01"),
            (Option("end_date", ["--end-date"], "", True), "2024-01-31")
        ]
        
        get_total_cost(option_list)
        
        mock_manager.get_total_cost.assert_called_once_with("2024-01-01", "2024-01-31")
        calls = [call[0][0] for call in mock_stdout.call_args_list]
        self.assertTrue(any("Using date range: 2024-01-01 to 2024-01-31" in call for call in calls))


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