import 'package:flutter/material.dart';
import 'package:agenda_tasks/l10n/app_localizations.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';

import '../../../../core/di/injection_container.dart';
import '../../domain/entities/task_entity.dart';
import '../../domain/enums/priority.dart';
import '../../domain/repositories/task_repository.dart';

class CalendarPage extends StatefulWidget {
  const CalendarPage({super.key});

  @override
  State<CalendarPage> createState() => _CalendarPageState();
}

class _CalendarPageState extends State<CalendarPage> {
  late DateTime _focusedMonth;
  DateTime? _selectedDate;
  Map<String, List<TaskEntity>> _tasksByDate = {};
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    _focusedMonth = DateTime.now();
    _loadTasksForMonth();
  }

  Future<void> _loadTasksForMonth() async {
    setState(() => _isLoading = true);

    final repository = getIt<TaskRepository>();
    final Map<String, List<TaskEntity>> tasks = {};

    final lastDay = DateTime(_focusedMonth.year, _focusedMonth.month + 1, 0);

    // Create all date requests
    final dates = List.generate(
      lastDay.day,
      (index) => DateTime(_focusedMonth.year, _focusedMonth.month, index + 1),
    );

    // Execute all API calls in parallel
    final results = await Future.wait(
      dates.map((date) => repository.getTasksByDate(date)),
    );

    // Process results
    for (int i = 0; i < dates.length; i++) {
      final dateStr = DateFormat('yyyy-MM-dd').format(dates[i]);
      results[i].when(
        success: (data) {
          if (data.isNotEmpty) {
            tasks[dateStr] = data;
          }
        },
        error: (_) {},
      );
    }

    if (mounted) {
      setState(() {
        _tasksByDate = tasks;
        _isLoading = false;
      });
    }
  }

  List<Priority> _getUniquePriorities(List<TaskEntity>? tasks) {
    if (tasks == null || tasks.isEmpty) return [];

    final incompleteTasks = tasks.where((t) => !t.isDone).toList();
    if (incompleteTasks.isEmpty) return [];

    // Get unique priorities, sorted by importance (high first)
    final priorities = <Priority>[];
    if (incompleteTasks.any((t) => t.priority == Priority.high)) {
      priorities.add(Priority.high);
    }
    if (incompleteTasks.any((t) => t.priority == Priority.medium)) {
      priorities.add(Priority.medium);
    }
    if (incompleteTasks.any((t) => t.priority == Priority.low)) {
      priorities.add(Priority.low);
    }
    return priorities;
  }

  @override
  Widget build(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    final locale = Localizations.localeOf(context).languageCode;

    return Scaffold(
      appBar: AppBar(
        title: Text(l10n.calendar),
        leading: IconButton(
          icon: const Icon(Icons.close),
          onPressed: () => context.pop(),
        ),
      ),
      body: Column(
        children: [
          _MonthNavigation(
            month: _focusedMonth,
            locale: locale,
            onPrevious: () {
              setState(() {
                _focusedMonth = DateTime(_focusedMonth.year, _focusedMonth.month - 1);
              });
              _loadTasksForMonth();
            },
            onNext: () {
              setState(() {
                _focusedMonth = DateTime(_focusedMonth.year, _focusedMonth.month + 1);
              });
              _loadTasksForMonth();
            },
          ),
          _WeekdayHeaders(locale: locale),
          Expanded(
            child: _isLoading
                ? const Center(child: CircularProgressIndicator())
                : _CalendarGrid(
                    focusedMonth: _focusedMonth,
                    selectedDate: _selectedDate,
                    tasksByDate: _tasksByDate,
                    getUniquePriorities: _getUniquePriorities,
                    onDateSelected: (date) {
                      setState(() => _selectedDate = date);
                    },
                  ),
          ),
        ],
      ),
      bottomNavigationBar: _selectedDate != null
          ? SafeArea(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: SizedBox(
                  height: 56,
                  child: ElevatedButton(
                    onPressed: () {
                      final dateStr = DateFormat('yyyy-MM-dd').format(_selectedDate!);
                      context.go('/?date=$dateStr');
                    },
                    child: Text(l10n.goToDay),
                  ),
                ),
              ),
            )
          : null,
    );
  }
}

class _MonthNavigation extends StatelessWidget {
  final DateTime month;
  final String locale;
  final VoidCallback onPrevious;
  final VoidCallback onNext;

  const _MonthNavigation({
    required this.month,
    required this.locale,
    required this.onPrevious,
    required this.onNext,
  });

  @override
  Widget build(BuildContext context) {
    final monthFormat = DateFormat.yMMMM(locale);

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 12),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          SizedBox(
            width: 48,
            height: 48,
            child: IconButton(
              icon: const Icon(Icons.chevron_left, size: 28),
              onPressed: onPrevious,
            ),
          ),
          Text(
            monthFormat.format(month),
            style: Theme.of(context).textTheme.titleLarge,
          ),
          SizedBox(
            width: 48,
            height: 48,
            child: IconButton(
              icon: const Icon(Icons.chevron_right, size: 28),
              onPressed: onNext,
            ),
          ),
        ],
      ),
    );
  }
}

class _WeekdayHeaders extends StatelessWidget {
  final String locale;

  const _WeekdayHeaders({required this.locale});

  @override
  Widget build(BuildContext context) {
    final weekdays = DateFormat.E(locale);
    final today = DateTime.now();
    final monday = today.subtract(Duration(days: today.weekday - 1));

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8),
      child: Row(
        children: List.generate(7, (index) {
          final day = monday.add(Duration(days: index));
          return Expanded(
            child: Center(
              child: Text(
                weekdays.format(day).substring(0, 2),
                style: Theme.of(context).textTheme.bodySmall?.copyWith(
                      fontWeight: FontWeight.bold,
                    ),
              ),
            ),
          );
        }),
      ),
    );
  }
}

class _CalendarGrid extends StatelessWidget {
  final DateTime focusedMonth;
  final DateTime? selectedDate;
  final Map<String, List<TaskEntity>> tasksByDate;
  final List<Priority> Function(List<TaskEntity>?) getUniquePriorities;
  final ValueChanged<DateTime> onDateSelected;

  const _CalendarGrid({
    required this.focusedMonth,
    required this.selectedDate,
    required this.tasksByDate,
    required this.getUniquePriorities,
    required this.onDateSelected,
  });

  @override
  Widget build(BuildContext context) {
    final firstDayOfMonth = DateTime(focusedMonth.year, focusedMonth.month, 1);
    final lastDayOfMonth = DateTime(focusedMonth.year, focusedMonth.month + 1, 0);
    final startOffset = (firstDayOfMonth.weekday - 1) % 7;
    final totalDays = startOffset + lastDayOfMonth.day;
    final rowCount = (totalDays / 7).ceil();
    final today = DateTime.now();

    return GridView.builder(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 7,
        childAspectRatio: 1,
        mainAxisSpacing: 4,
        crossAxisSpacing: 4,
      ),
      itemCount: rowCount * 7,
      itemBuilder: (context, index) {
        final dayOffset = index - startOffset;
        if (dayOffset < 0 || dayOffset >= lastDayOfMonth.day) {
          return const SizedBox();
        }

        final date = DateTime(focusedMonth.year, focusedMonth.month, dayOffset + 1);
        final dateStr = DateFormat('yyyy-MM-dd').format(date);
        final isToday = date.year == today.year &&
            date.month == today.month &&
            date.day == today.day;
        final isSelected = selectedDate != null &&
            date.year == selectedDate!.year &&
            date.month == selectedDate!.month &&
            date.day == selectedDate!.day;

        final tasks = tasksByDate[dateStr];
        final priorities = getUniquePriorities(tasks);

        return GestureDetector(
          onTap: () => onDateSelected(date),
          child: Container(
            decoration: BoxDecoration(
              color: isSelected
                  ? Theme.of(context).colorScheme.primary
                  : isToday
                      ? Theme.of(context).colorScheme.primaryContainer
                      : null,
              borderRadius: BorderRadius.circular(8),
            ),
            child: Stack(
              alignment: Alignment.center,
              children: [
                Text(
                  '${dayOffset + 1}',
                  style: TextStyle(
                    color: isSelected
                        ? Theme.of(context).colorScheme.onPrimary
                        : isToday
                            ? Theme.of(context).colorScheme.onPrimaryContainer
                            : null,
                    fontWeight: isToday || isSelected ? FontWeight.bold : null,
                  ),
                ),
                if (priorities.isNotEmpty)
                  Positioned(
                    bottom: 6,
                    child: _PriorityDots(priorities: priorities),
                  ),
              ],
            ),
          ),
        );
      },
    );
  }
}

class _PriorityDots extends StatelessWidget {
  final List<Priority> priorities;

  const _PriorityDots({required this.priorities});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: priorities
          .map((priority) => Padding(
                padding: const EdgeInsets.symmetric(horizontal: 2),
                child: _PulsingDot(priority: priority),
              ))
          .toList(),
    );
  }
}

class _PulsingDot extends StatefulWidget {
  final Priority priority;

  const _PulsingDot({required this.priority});

  @override
  State<_PulsingDot> createState() => _PulsingDotState();
}

class _PulsingDotState extends State<_PulsingDot>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    )..repeat(reverse: true);

    _animation = Tween<double>(begin: 0.6, end: 1.0).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Color _getPriorityColor() {
    switch (widget.priority) {
      case Priority.high:
        return Colors.red.shade600;
      case Priority.medium:
        return Colors.orange.shade600;
      case Priority.low:
        return Colors.green.shade600;
    }
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animation,
      builder: (context, child) {
        return Opacity(
          opacity: _animation.value,
          child: Container(
            width: 10,
            height: 10,
            decoration: BoxDecoration(
              color: _getPriorityColor(),
              shape: BoxShape.circle,
              boxShadow: [
                BoxShadow(
                  color: _getPriorityColor().withValues(alpha: 0.5),
                  blurRadius: 3,
                  spreadRadius: 1,
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}
