import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:logging/logging.dart';
import 'package:moneymgr_mobile/services/storage/expenses.dart';
import 'package:moneymgr_mobile/utils/extensions.dart';
import 'package:moneymgr_mobile/widgets/expense_editor.dart';
import 'package:moneymgr_mobile/widgets/full_screen_error.dart';
import 'package:moneymgr_mobile/widgets/loading_scaffold.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'scan_details.g.dart';

@riverpod
Future<(Expense, Uint8List)?> _getExpense(Ref ref, {required int id}) async {
  final expProvider = ref.watch(expensesProvider).requireValue;
  final expense = await expProvider.getById(id);
  if (expense == null) return null;
  final file = await expProvider.loadFile(expense);

  return (expense, file);
}

class ScanDetailScreen extends HookConsumerWidget {
  final int id;

  const ScanDetailScreen({super.key, required this.id});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final expenses = ref.watch(expensesProvider).requireValue;
    final expense = ref.watch(_getExpenseProvider(id: id));

    handleUpdate(BaseExpenseInfo newInfo) async {
      try {
        await expenses.updateExpense(expense.requireValue!.$1, newInfo);
        if (context.mounted) {
          context.pop();
        }

        ref.invalidate(expensesProvider);
      } catch (e, s) {
        Logger.root.warning("Failed to update expense! $e$s");
        if (context.mounted) {
          context.showTextSnackBar("Failed to update expense! $e");
        }
      }
    }

    handleDelete() async {
      try {
        await expenses.deleteExpense(expense.requireValue!.$1);
        if (context.mounted) {
          context.pop();
        }

        ref.invalidate(expensesProvider);
      } catch (e, s) {
        Logger.root.warning("Failed to delete expense! $e$s");
        if (context.mounted) {
          context.showTextSnackBar("Failed to delete expense! $e");
        }
      }
    }

    return switch (expense) {
      AsyncData(:final value) when value == null => FullScreenError(
        message: "Expense does not exists!",
        error: 'NONE',
      ),
      AsyncData(:final value) => ExpenseEditor(
        file: value!.$2,
        initialData: value.$1.baseExpense,
        onFinished: handleUpdate,
        onDelete: handleDelete,
      ),
      AsyncError(:final error) => FullScreenError(
        message: "Failed to load expense information!",
        error: error.toString(),
      ),
      _ => LoadingScaffold(title: "Expense $id"),
    };
  }
}
