import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uuid/uuid.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Plant care API')),
        body: CheckList(),
      ),
    );
  }
}

class CheckList extends ConsumerStatefulWidget {
  const CheckList({super.key});

  @override
  ConsumerState<CheckList> createState() => _CheckListState();
}

class _CheckListState extends ConsumerState<CheckList> {
  @override
  Widget build(BuildContext context) {
    final todoList = ref.watch(todoListProvider);
    final completedPercentage = ref.watch(completedPercentageProvider);

    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
              'Completed todos: ${completedPercentage.toStringAsFixed(2)}%'),
        ),
        Expanded(
          child: ListView.builder(
            itemCount: todoList.length,
            itemBuilder: (context, index) {
              final todo = todoList[index];
              return ListTile(
                title: Text(todo.description),
                trailing: Checkbox(
                  value: todo.completed,
                  onChanged: (value) {
                    ref.read(todoListProvider.notifier).toggle(todo.id);
                  },
                ),
              );
            },
          ),
        ),
      ],
    );
  }
}

final todoListProvider =
    NotifierProvider<TodoList, List<Todo>>(() => TodoList());

final completedPercentageProvider =
    StateNotifierProvider<CompletedPercentageNotifier, double>(
  (ref) => CompletedPercentageNotifier(ref.watch(todoListProvider)),
);

class Todo {
  Todo({
    required this.description,
    required this.id,
    this.completed = false,
  });

  final String id;
  final String description;
  bool completed;
}

class TodoList extends Notifier<List<Todo>> {
  @override
  List<Todo> build() {
    final initialTodos = [
      Todo(
        id: _uuid.v4(),
        description: 'Water all the plants in your garden.',
      ),
    ];
    ref.read(completedPercentageProvider.notifier).update(initialTodos);
    return initialTodos;
  }

  void add(String description) {
    state = [
      ...state,
      Todo(id: _uuid.v4(), description: description),
    ];
    _updateCompletedPercentage();
  }

  void toggle(String id) {
    state = [
      for (final todo in state)
        if (todo.id == id)
          Todo(
            id: todo.id,
            completed: !todo.completed,
            description: todo.description,
          )
        else
          todo,
    ];
    _updateCompletedPercentage();
  }

  void edit({required String id, required String description}) {
    state = [
      for (final todo in state)
        if (todo.id == id)
          Todo(
            id: todo.id,
            completed: todo.completed,
            description: description,
          )
        else
          todo,
    ];
    _updateCompletedPercentage();
  }

  void remove(Todo target) {
    state = state.where((todo) => todo.id != target.id).toList();
    _updateCompletedPercentage();
  }

  int get length => state.length;

  Todo operator [](int index) => state[index];

  void _updateCompletedPercentage() {
    final completedPercentageNotifier =
        ref.read(completedPercentageProvider.notifier);
    completedPercentageNotifier.update(state);
  }
}

class CompletedPercentageNotifier extends StateNotifier<double> {
  CompletedPercentageNotifier(List<Todo> initialTodos)
      : super(_calculateCompletedPercentage(initialTodos));

  static double _calculateCompletedPercentage(List<Todo> todos) {
    if (todos.isEmpty) return 0;
    final completedCount = todos.where((todo) => todo.completed).length;
    return (completedCount / todos.length) * 100;
  }

  void update(List<Todo> todos) {
    state = _calculateCompletedPercentage(todos);
  }
}

const _uuid = Uuid();
circular dependency error