import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:okane/database/sqlite.dart';
import 'package:okane/screen.dart';
import 'package:okane/ui/state/core.dart';

Future<T?> showDialogOrModal<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  bool showDragHandle = true,
  bool horizontalPaddingOnMobile = true,
}) {
  final screenSize = getScreenSize(context);
  final width = MediaQuery.sizeOf(context).shortestSide;

  return switch (screenSize) {
    ScreenSize.small => showModalBottomSheet<T>(
      context: context,
      showDragHandle: showDragHandle,
      isScrollControlled: true,
      builder:
          (context) => Padding(
            padding: EdgeInsets.only(
              bottom: 32 + MediaQuery.of(context).viewInsets.bottom,
              left: horizontalPaddingOnMobile ? 16 : 0,
              right: horizontalPaddingOnMobile ? 16 : 0,
            ),
            child: builder(context),
          ),
    ),
    ScreenSize.normal => showDialog<T>(
      context: context,
      builder:
          (context) => Dialog(
            child: Padding(
              padding: EdgeInsets.only(top: 16),
              child: Container(
                constraints: BoxConstraints(maxWidth: width * 0.7),
                child: Padding(
                  padding: EdgeInsets.only(bottom: 32),
                  child: builder(context),
                ),
              ),
            ),
          ),
    ),
  };
}

Future<TransactionTemplateDto?> selectTransactionTemplate(
  BuildContext context,
) {
  return showDialogOrModal<TransactionTemplateDto>(
    context: context,
    builder: (context) {
      return BlocBuilder<CoreCubit, CoreState>(
        builder: (context, state) {
          if (state.transactionTemplates.isEmpty) {
            return Padding(
              padding: EdgeInsets.symmetric(horizontal: 16),
              child: Text("No templates defined"),
            );
          }

          return ListView.builder(
            itemCount: state.transactionTemplates.length,
            itemBuilder:
                (context, index) => ListTile(
                  title: Text(state.transactionTemplates[index].template.name),
                  onTap: () {
                    Navigator.of(
                      context,
                    ).pop(state.transactionTemplates[index]);
                  },
                ),
          );
        },
      );
    },
  );
}

DateTime toMidnight(DateTime t) {
  return DateTime(t.year, t.month, t.day);
}

String zeroPad(int i) {
  if (i <= 9) {
    return "0$i";
  }

  return i.toString();
}

String formatDateTime(DateTime dt, {bool formatYear = true}) {
  if (!formatYear) {
    return "${zeroPad(dt.day)}.${zeroPad(dt.month)}";
  }
  return "${zeroPad(dt.day)}.${zeroPad(dt.month)}.${zeroPad(dt.year)}";
}

Color colorHash(String text) {
  final hue =
      text.characters
          .map((c) => c.codeUnitAt(0).toDouble())
          .reduce((acc, c) => c + ((acc.toInt() << 5) - acc)) %
      360;
  return HSVColor.fromAHSV(1, hue, 0.5, 0.5).toColor();
}

String formatCurrency(double amount, {bool precise = true}) {
  if (!precise) {
    return "${amount.toInt()}€";
  }
  return "${amount.toStringAsFixed(2)}€";
}

DateTime monthEnding(DateTime now) {
  return DateTime(now.year, now.month, 32, 23, 59, 59);
}

Future<bool> confirm(BuildContext context, String title, String body) async {
  final result = await showDialog<bool>(
    context: context,
    builder:
        (context) => AlertDialog(
          title: Text(title),
          content: Text(body),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(true);
              },
              child: Text("Delete", style: TextStyle(color: Colors.red)),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(false);
              },
              child: Text("Cancel"),
            ),
          ],
        ),
  );
  return result ?? false;
}

bool isTransactionDue(RecurringTransaction r, DateTime now) {
  if (r.lastExecution == null) {
    return true;
  }

  final expectedNextExecution = r.lastExecution!.add(Duration(days: r.days));
  if (now.isAfter(expectedNextExecution)) {
    return true;
  }

  return now.difference(expectedNextExecution).inDays.abs() <=
      (r.days * 0.5).toInt();
}