"""
Unit tests for Phase 1 Daily Helper database models
"""

import pytest
from datetime import datetime, date
from app.models.models import (
    UserProfile, DailyRoutine, RoutineExecution, Notification,
    DailyChecklist, HabitTracker
)


class TestUserProfile:
    """Tests for UserProfile model"""

    def test_user_profile_creation(self):
        """Test creating a user profile"""
        profile = UserProfile(
            email="test@example.com",
            username="testuser",
            timezone="EST",
            preferred_trading_start="09:00",
            preferred_trading_end="17:00",
            risk_tolerance="moderate",
            trading_style="day_trader",
            daily_target=1000.0,
            max_loss=500.0,
        )

        assert profile.email == "test@example.com"
        assert profile.username == "testuser"
        assert profile.timezone == "EST"
        assert profile.risk_tolerance == "moderate"
        assert profile.trading_style == "day_trader"
        assert profile.notifications_enabled == True
        assert profile.email_reports == True
        assert profile.sms_enabled == False

    def test_user_profile_defaults(self):
        """Test UserProfile default values"""
        profile = UserProfile()

        assert profile.timezone == "UTC"
        assert profile.preferred_trading_start == "09:00"
        assert profile.preferred_trading_end == "17:00"
        assert profile.risk_tolerance == "moderate"
        assert profile.trading_style == "day_trader"
        assert profile.notifications_enabled == True
        assert profile.push_notifications == True


class TestDailyRoutine:
    """Tests for DailyRoutine model"""

    def test_daily_routine_creation(self):
        """Test creating a daily routine"""
        routine = DailyRoutine(
            user_id="user123",
            routine_type="morning",
            scheduled_time="08:30",
            tasks=["market_brief", "checklist", "review_plan"],
            enabled=True,
        )

        assert routine.routine_type == "morning"
        assert routine.scheduled_time == "08:30"
        assert len(routine.tasks) == 3
        assert "market_brief" in routine.tasks
        assert routine.enabled == True

    def test_daily_routine_empty_tasks(self):
        """Test routine with empty tasks list"""
        routine = DailyRoutine(
            routine_type="evening",
            scheduled_time="17:00",
            enabled=True,
        )

        assert routine.tasks == []

    def test_daily_routine_types(self):
        """Test different routine types"""
        types = ["morning", "active_trading", "evening"]

        for routine_type in types:
            routine = DailyRoutine(routine_type=routine_type)
            assert routine.routine_type == routine_type


class TestRoutineExecution:
    """Tests for RoutineExecution model"""

    def test_routine_execution_creation(self):
        """Test creating a routine execution record"""
        execution = RoutineExecution(
            routine_id=1,
            completion_status="completed",
            tasks_completed=["market_brief", "checklist"],
            execution_notes="All tasks completed successfully",
        )

        assert execution.routine_id == 1
        assert execution.completion_status == "completed"
        assert len(execution.tasks_completed) == 2
        assert execution.execution_notes is not None

    def test_execution_status_values(self):
        """Test different execution status values"""
        statuses = ["completed", "failed", "partial"]

        for status in statuses:
            execution = RoutineExecution(routine_id=1, completion_status=status)
            assert execution.completion_status == status


class TestNotification:
    """Tests for Notification model"""

    def test_notification_creation(self):
        """Test creating a notification"""
        notification = Notification(
            notification_type="price_alert",
            title="Price Alert",
            message="Gold price exceeded $2000",
            priority="high",
            delivery_method="push",
            read=False,
        )

        assert notification.notification_type == "price_alert"
        assert notification.title == "Price Alert"
        assert notification.priority == "high"
        assert notification.delivery_method == "push"
        assert notification.read == False

    def test_notification_read_status(self):
        """Test notification read/unread status"""
        notification = Notification(
            notification_type="news",
            title="Breaking News",
            message="Fed announces rate decision",
            read=False,
        )

        assert notification.read == False

        # Simulate marking as read
        notification.read = True
        notification.read_at = datetime.utcnow()

        assert notification.read == True
        assert notification.read_at is not None

    def test_notification_with_data(self):
        """Test notification with additional data"""
        data = {
            "price": 2010.50,
            "threshold": 2000.00,
            "direction": "above"
        }

        notification = Notification(
            notification_type="price_alert",
            title="Price Alert",
            message="Gold moved above threshold",
            data=data,
        )

        assert notification.data == data


class TestDailyChecklist:
    """Tests for DailyChecklist model"""

    def test_daily_checklist_creation(self):
        """Test creating a daily checklist"""
        items = [
            {"id": "1", "title": "Check Economic Calendar", "completed": False},
            {"id": "2", "title": "Create Trading Plan", "completed": False},
        ]

        checklist = DailyChecklist(
            checklist_date=date.today(),
            checklist_type="morning",
            items=items,
            completion_percentage=0.0,
        )

        assert checklist.checklist_date == date.today()
        assert checklist.checklist_type == "morning"
        assert len(checklist.items) == 2
        assert checklist.completion_percentage == 0.0

    def test_checklist_completion_percentage(self):
        """Test checklist completion percentage calculation"""
        items = [
            {"id": "1", "title": "Item 1", "completed": True},
            {"id": "2", "title": "Item 2", "completed": True},
            {"id": "3", "title": "Item 3", "completed": False},
        ]

        completion = sum(1 for item in items if item["completed"]) / len(items) * 100

        checklist = DailyChecklist(
            checklist_type="morning",
            items=items,
            completion_percentage=completion,
        )

        assert checklist.completion_percentage == pytest.approx(66.67, rel=0.1)

    def test_checklist_types(self):
        """Test different checklist types"""
        types = ["morning", "active_trading", "evening", "all"]

        for checklist_type in types:
            checklist = DailyChecklist(checklist_type=checklist_type)
            assert checklist.checklist_type == checklist_type


class TestHabitTracker:
    """Tests for HabitTracker model"""

    def test_habit_tracker_creation(self):
        """Test creating a habit tracker"""
        habit = HabitTracker(
            habit_name="Daily Planning",
            frequency="daily",
            current_streak=5,
            longest_streak=10,
            total_completions=25,
        )

        assert habit.habit_name == "Daily Planning"
        assert habit.frequency == "daily"
        assert habit.current_streak == 5
        assert habit.longest_streak == 10
        assert habit.total_completions == 25

    def test_habit_defaults(self):
        """Test habit tracker default values"""
        habit = HabitTracker(habit_name="Test Habit")

        assert habit.frequency == "daily"
        assert habit.current_streak == 0
        assert habit.longest_streak == 0
        assert habit.total_completions == 0
        assert habit.completion_dates == []

    def test_habit_completion_dates(self):
        """Test habit completion dates tracking"""
        dates = ["2024-11-10", "2024-11-11", "2024-11-12"]

        habit = HabitTracker(
            habit_name="Trading Journal",
            frequency="daily",
            completion_dates=dates,
            total_completions=len(dates),
        )

        assert len(habit.completion_dates) == 3
        assert habit.total_completions == 3

    def test_habit_frequencies(self):
        """Test different habit frequencies"""
        frequencies = ["daily", "weekly"]

        for frequency in frequencies:
            habit = HabitTracker(
                habit_name="Test",
                frequency=frequency
            )
            assert habit.frequency == frequency

    def test_habit_streak_calculation(self):
        """Test streak calculation logic"""
        # Simulate consecutive completions
        completion_dates = [
            "2024-11-10",
            "2024-11-11",
            "2024-11-12",
            "2024-11-13",
            "2024-11-14",
        ]

        habit = HabitTracker(
            habit_name="Test",
            completion_dates=completion_dates,
            current_streak=5,
        )

        assert habit.current_streak == 5


class TestModelRelationships:
    """Tests for model relationships"""

    def test_routine_has_executions(self):
        """Test that routine has executions"""
        routine = DailyRoutine(
            routine_type="morning",
            scheduled_time="08:30",
        )

        execution1 = RoutineExecution(routine_id=1)
        execution2 = RoutineExecution(routine_id=1)

        assert execution1.routine_id == execution2.routine_id == 1

    def test_notification_structure(self):
        """Test notification structure"""
        types = ["price_alert", "routine", "report", "news", "reminder"]

        for notif_type in types:
            notification = Notification(
                notification_type=notif_type,
                title="Test",
                message="Test message",
            )
            assert notification.notification_type == notif_type


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
