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/router/routes_list.dart';
import 'package:moneymgr_mobile/services/storage/expenses.dart';
import 'package:moneymgr_mobile/services/storage/prefs.dart';
import 'package:moneymgr_mobile/utils/ocr_utils.dart';
import 'package:moneymgr_mobile/utils/pdf_utils.dart';
import 'package:moneymgr_mobile/widgets/expense_editor.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'scan_screen.g.dart';

/// Scan a document & return generated PDF as byte file
@riverpod
Future<(Uint8List?, BaseExpenseInfo?)> _scanDocument(Ref ref) async {
  final prefs = ref.watch(prefsProvider).requireValue;

  final pdf = await scanDocAsPDF();
  final img = await renderPdf(pdfBytes: pdf);
  final amount = await extractInfoFromBill(
    imgBuff: img,
    extractDates: !prefs.disableExtractDates(),
  );
  return (pdf, amount);
}

class ScanScreen extends HookConsumerWidget {
  const ScanScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final scanDocProvider = ref.watch(_scanDocumentProvider);
    final expenses = ref.watch(expensesProvider).requireValue;

    restartScan() async {
      try {
        ref.invalidate(_scanDocumentProvider);
        Logger.root.info("Load again startup");
      } catch (e, s) {
        Logger.root.shout("Failed to try again startup loading! $e $s");
      }
    }

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: switch (scanDocProvider) {
        AsyncData(:final value) when value.$1 != null => ExpenseEditor(
          file: value.$1!,
          initialData: value.$2,
          onFinished: (expense) async {
            await expenses.add(
              info: expense,
              fileContent: value.$1!,
              fileMimeType: "application/pdf",
            );
            if (context.mounted) {
              context.pushReplacement(scansPage);
            }
          },
          onRescan: restartScan,
        ),

        // No data
        AsyncData(:final value) when value.$1 == null => ScanErrorScreen(
          message: "No document scanned!",
          onTryAgain: restartScan,
        ),

        // Error
        AsyncError(:final error) => ScanErrorScreen(
          message: error.toString(),
          onTryAgain: restartScan,
        ),
        _ => const Center(child: CircularProgressIndicator()),
      },
    );
  }
}

class ScanErrorScreen extends StatelessWidget {
  final String message;
  final Function() onTryAgain;

  const ScanErrorScreen({
    super.key,
    required this.message,
    required this.onTryAgain,
  });

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Spacer(flex: 5),
          Text("An error occurred while scanning"),
          Spacer(flex: 1),
          Text(message, textAlign: TextAlign.center),
          Spacer(flex: 1),
          MaterialButton(
            onPressed: onTryAgain,
            child: Text("Try again".toUpperCase()),
          ),
          Spacer(flex: 5),
        ],
      ),
    );
  }
}
