import 'dart:typed_data';

import 'package:confirm_dialog/confirm_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:moneymgr_mobile/services/storage/expenses.dart';
import 'package:moneymgr_mobile/services/storage/prefs.dart';
import 'package:moneymgr_mobile/utils/extensions.dart';
import 'package:moneymgr_mobile/utils/time_utils.dart';
import 'package:moneymgr_mobile/widgets/pdf_viewer.dart';

import '../utils/hooks.dart';

class ExpenseEditor extends HookConsumerWidget {
  final Uint8List file;
  final Future<void> Function(BaseExpenseInfo) onFinished;
  final Function()? onRescan;
  final Function()? onDelete;
  final BaseExpenseInfo? initialData;

  const ExpenseEditor({
    super.key,
    required this.file,
    required this.onFinished,
    this.onRescan,
    this.onDelete,
    this.initialData,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final serverConfig = ref.watch(prefsProvider).requireValue.serverConfig()!;

    final labelController = useTextEditingController(text: initialData?.label);
    final costController = useTextEditingController(
      text: initialData?.cost.toString(),
    );
    final timeController = useState(initialData?.time ?? DateTime.now());

    final (:pending, :snapshot, :hasError) = useAsyncTask();

    // Force refresh of field if required
    final previousData = useState<BaseExpenseInfo?>(null);
    if (initialData != previousData.value) {
      previousData.value = initialData;
      labelController.text = initialData?.label ?? "";
      costController.text = initialData?.cost.toString() ?? "";
      timeController.value = initialData?.time ?? DateTime.now();
    }

    // Clear cost value
    handleClearCost() {
      costController.text = "";
    }

    // Pick a new date
    handlePickDate() async {
      final date = await showDatePicker(
        context: context,
        firstDate: DateTime(2000),
        lastDate: DateTime(2099),
        initialDate: timeController.value,
      );
      if (date != null) timeController.value = date;
    }

    // Save expense
    handleSubmit() async {
      if (costController.text.isEmpty) {
        context.showTextSnackBar("Please specify expense cost!");
        return;
      }

      pending.value = onFinished(
        BaseExpenseInfo(
          label: labelController.text.isEmpty ? null : labelController.text,
          cost: double.tryParse(costController.text) ?? 0,
          time: timeController.value,
        ),
      );

      // Reset screen after a scan
      await pending.value;
      labelController.text = "";
      costController.text = "";
    }

    // Cancel operation
    handleRescan() async {
      if (await confirm(
            context,
            content: Text("Do you really want to discard this expense?"),
          ) &&
          onRescan != null) {
        onRescan!();
      }
    }

    // Delete expense
    handleDelete() async {
      if (await confirm(
            context,
            content: Text("Do you really want to delete this expense?"),
          ) &&
          onDelete != null) {
        onDelete!();
      }
    }

    // Open invoice in full screen
    handleFullScreenInvoice() {
      showDialog(
        context: context,
        builder: (c) => Scaffold(
          appBar: AppBar(title: Text("Expense")),
          body: SingleChildScrollView(
            child: PDFViewer(pdfBytes: file, fit: BoxFit.fitWidth),
          ),
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: Text("Expense info"),
        actions: [
          // Rescan expense
          onRescan == null
              ? Container()
              : IconButton(
                  onPressed: handleRescan,
                  icon: Icon(Icons.restart_alt),
                ),

          // Delete expense
          onDelete == null
              ? Container()
              : IconButton(onPressed: handleDelete, icon: Icon(Icons.delete)),

          // Submit
          snapshot.connectionState == ConnectionState.waiting
              ? CircularProgressIndicator()
              : IconButton(
                  onPressed: handleSubmit,
                  icon: Icon(Icons.save),
                  color: hasError ? Colors.red : null,
                ),
        ],
      ),
      body: Column(
        children: [
          // Expense preview
          Expanded(
            child: GestureDetector(
              onTap: handleFullScreenInvoice,
              child: PDFViewer(pdfBytes: file, fit: BoxFit.contain),
            ),
          ),

          SizedBox(height: 10),

          // Cost
          TextField(
            controller: costController,
            keyboardType: TextInputType.numberWithOptions(
              decimal: true,
              signed: false,
            ),
            decoration: InputDecoration(
              labelText: 'Cost',
              suffixIcon: IconButton(
                onPressed: handleClearCost,
                icon: const Icon(Icons.clear),
              ),
            ),
            textInputAction: TextInputAction.done,
          ),

          SizedBox(height: 10),

          // Date
          TextField(
            enabled: true,
            readOnly: true,
            controller: TextEditingController(
              text: timeController.value.simpleDate,
            ),
            keyboardType: TextInputType.datetime,
            decoration: InputDecoration(
              labelText: 'Date',
              suffixIcon: IconButton(
                onPressed: handlePickDate,
                icon: const Icon(Icons.date_range),
              ),
            ),
          ),

          SizedBox(height: 10),

          // Label
          TextField(
            controller: labelController,
            keyboardType: TextInputType.text,
            decoration: const InputDecoration(labelText: 'Label'),
            textInputAction: TextInputAction.done,
            maxLength: serverConfig.constraints.inbox_entry_label.max,
          ),
        ],
      ),
    );
  }
}
