import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:rluv/global/utils.dart';

import '../../../global/api.dart';
import '../../../global/store.dart';
import '../../../global/styles.dart';
import '../../../global/widgets/ui_button.dart';
import '../../../models/budget_category_model.dart';
import '../../../models/transaction_model.dart';
import '../../../models/user.dart';

class TransactionDialog extends ConsumerStatefulWidget {
  const TransactionDialog({super.key, this.transaction});

  final Transaction? transaction;

  @override
  ConsumerState<TransactionDialog> createState() => _AddTransactionDialogState();
}

class _AddTransactionDialogState extends ConsumerState<TransactionDialog> {
  late DateTime selectedDate;
  late final TextEditingController amountController;
  late final TextEditingController memoController;
  User? user;

  final amountFocusNode = FocusNode();
  final memoFocusNode = FocusNode();

  TransactionType transactionType = TransactionType.expense;
  late BudgetCategory selectedBudgetCategory;

  @override
  void initState() {
    if (widget.transaction != null) {
      amountController = TextEditingController(text: widget.transaction!.amount.toString());
      memoController = TextEditingController(text: widget.transaction!.memo);
      transactionType = widget.transaction!.type;
      selectedDate = widget.transaction!.date;
    } else {
      amountController = TextEditingController();
      memoController = TextEditingController();
      selectedDate = DateTime.now();
    }
    final categories = ref.read(budgetCategoriesProvider);
    if (categories.isNotEmpty) {
      selectedBudgetCategory = categories.first;
    }
    final u = ref.read(userProvider);
    if (u == null) {
      WidgetsBinding.instance.addPostFrameCallback((_) => ref.read(jwtProvider.notifier).revokeToken());
    } else {
      user = u;
    }

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    if (user == null) return Container();
    final List<BudgetCategory> budgetCategories = ref.read(budgetCategoriesProvider);
    return SizedBox(
        width: MediaQuery.of(context).size.width * Styles.dialogScreenWidthFactor,
        child: budgetCategories.isEmpty
            ? const Padding(
                padding: EdgeInsets.all(8.0),
                child: Text(
                  'Add budget categories to sort your transactions',
                  textAlign: TextAlign.center,
                ),
              )
            : Padding(
                padding: const EdgeInsets.all(18.0),
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    if (widget.transaction == null)
                      Padding(
                        padding: const EdgeInsets.only(bottom: 8.0, left: 8.0),
                        child: Row(children: [
                          if (budgetCategories.isNotEmpty)
                            InkWell(
                              onTap: transactionType == TransactionType.expense
                                  ? null
                                  : () {
                                      setState(() => transactionType = TransactionType.expense);
                                    },
                              child: AnimatedContainer(
                                height: 38,
                                width: 80,
                                decoration: BoxDecoration(
                                    borderRadius: const BorderRadius.only(
                                        topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0)),
                                    color: transactionType == TransactionType.expense
                                        ? Styles.lavender
                                        : Styles.washedStone),
                                duration: const Duration(milliseconds: 300),
                                child: const Padding(
                                  padding: EdgeInsets.all(8.0),
                                  child: Text('Expense', style: TextStyle(fontSize: 16)),
                                ),
                              ),
                            ),
                          InkWell(
                            onTap: transactionType == TransactionType.income
                                ? null
                                : () {
                                    setState(() => transactionType = TransactionType.income);
                                  },
                            child: AnimatedContainer(
                              height: 38,
                              width: 80,
                              decoration: BoxDecoration(
                                  borderRadius: const BorderRadius.only(
                                      topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0)),
                                  color:
                                      transactionType == TransactionType.income ? Styles.lavender : Styles.washedStone),
                              duration: const Duration(milliseconds: 300),
                              child: const Padding(
                                padding: EdgeInsets.all(8.0),
                                child: Text('Income', style: TextStyle(fontSize: 16)),
                              ),
                            ),
                          ),
                        ]),
                      ),
                    Row(
                      children: [
                        const Padding(
                          padding: EdgeInsets.all(8.0),
                          child: Text(
                            'Amount:',
                            style: TextStyle(fontSize: 18.0),
                          ),
                        ),
                        Container(
                          width: 120,
                          height: 40,
                          decoration: Styles.boxLavenderBubble,
                          child: TextFormField(
                            keyboardType: TextInputType.number,
                            textAlign: TextAlign.center,
                            style: const TextStyle(fontSize: 18.0),
                            cursorColor: Styles.blushingPink,
                            decoration: Styles.inputLavenderBubble(),
                            focusNode: amountFocusNode,
                            controller: amountController,
                            onFieldSubmitted: (_) {
                              memoFocusNode.requestFocus();
                            },
                          ),
                        ),
                      ],
                    ),
                    if (budgetCategories.isEmpty)
                      const Padding(
                        padding: EdgeInsets.all(18.0),
                        child: Text(
                          'Add budget categories to sort your transactions',
                          textAlign: TextAlign.center,
                        ),
                      ),
                    if (budgetCategories.isNotEmpty)
                      AnimatedSwitcher(
                        duration: const Duration(milliseconds: 300),
                        child: transactionType == TransactionType.income
                            ? const SizedBox(height: 12.5)
                            : Padding(
                                padding: const EdgeInsets.only(left: 8.0),
                                child: Row(
                                  children: [
                                    const Padding(
                                      padding: EdgeInsets.only(right: 28.0),
                                      child: Text(
                                        'Category:',
                                        style: TextStyle(fontSize: 18.0),
                                      ),
                                    ),
                                    DropdownButton<BudgetCategory>(
                                      dropdownColor: Styles.lavender,
                                      value: selectedBudgetCategory,
                                      items: budgetCategories
                                          .map(
                                            (e) => DropdownMenuItem(
                                              value: e,
                                              child: Row(
                                                mainAxisSize: MainAxisSize.min,
                                                children: [
                                                  Container(
                                                    height: 18,
                                                    width: 18,
                                                    decoration: BoxDecoration(
                                                      shape: BoxShape.circle,
                                                      border: Border.all(color: Colors.black, width: 1.5),
                                                      color: e.color,
                                                    ),
                                                  ),
                                                  const SizedBox(width: 12),
                                                  Text(e.name),
                                                ],
                                              ),
                                            ),
                                          )
                                          .toList(),
                                      onChanged: (BudgetCategory? value) {
                                        if (value != null) {
                                          if (kDebugMode) {
                                            print('${value.name} selected');
                                          }
                                          setState(() => selectedBudgetCategory = value);
                                        }
                                      },
                                    ),
                                  ],
                                ),
                              ),
                      ),
                    const Padding(
                      padding: EdgeInsets.all(8.0),
                      child: Row(
                        children: [
                          Text(
                            'Memo',
                            style: TextStyle(fontSize: 18.0),
                          ),
                        ],
                      ),
                    ),
                    Container(
                      width: MediaQuery.of(context).size.width * 0.65,
                      height: 100,
                      decoration: Styles.boxLavenderBubble,
                      child: TextFormField(
                        style: const TextStyle(fontSize: 18.0),
                        maxLines: 4,
                        focusNode: memoFocusNode,
                        textAlign: TextAlign.left,
                        cursorColor: Styles.blushingPink,
                        controller: memoController,
                        decoration: Styles.inputLavenderBubble(),
                        onFieldSubmitted: (_) {},
                      ),
                    ),
                    UiButton(
                      showLoading: true,
                      text: 'ADD',
                      color: Styles.lavender,
                      onPressed: () => submitTransaction().then((_) {
                        if (mounted) {
                          Navigator.pop(context);
                        }
                        showSnack(
                          ref: ref,
                          text: widget.transaction != null ? 'Transaction updated!' : 'Transaction added!',
                          type: SnackType.success,
                        );
                      }),
                    ),
                  ],
                ),
              ));
  }

  Future submitTransaction() async {
    Map<String, dynamic>? data;
    if (widget.transaction != null) {
      data = await ref.read(apiProvider.notifier).put(
          path: 'transaction',
          data: Transaction.copyWith(widget.transaction!, {
            'memo': memoController.text.isNotEmpty ? memoController.text : null,
            'amount': double.parse(amountController.text),
            'budget_category_id': transactionType == TransactionType.income ? null : selectedBudgetCategory.id,
          }).toJson());
    } else {
      data = await ref.read(apiProvider.notifier).post(
          path: 'transaction',
          data: Transaction(
                  amount: double.parse(amountController.text),
                  createdByUserId: user!.id!,
                  budgetCategoryId: transactionType == TransactionType.income ? null : selectedBudgetCategory.id,
                  budgetId: user!.budgetId,
                  date: DateTime.now(),
                  type: transactionType,
                  memo: memoController.text.isNotEmpty ? memoController.text : null)
              .toJson());
    }
    final success = data != null ? data['success'] as bool : false;
    if (success) {
      if (widget.transaction != null) {
        ref.read(dashboardProvider.notifier).update({'transactions': data});
      } else {
        ref.read(dashboardProvider.notifier).add({'transactions': data});
      }
    } else {
      showSnack(
          ref: ref,
          text: widget.transaction != null ? 'Failed to edit transaction' : 'Failed to add transaction',
          type: SnackType.error);
    }
  }
}