/// Providers: Invoices
///
/// Riverpod providers for managing invoices state.
library;

import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:worker/core/database/models/enums.dart';
import 'package:worker/features/orders/data/datasources/invoices_local_datasource.dart';
import 'package:worker/features/orders/data/models/invoice_model.dart';

part 'invoices_provider.g.dart';

/// Invoices Local Data Source Provider
@riverpod
InvoicesLocalDataSource invoicesLocalDataSource(Ref ref) {
  return InvoicesLocalDataSource();
}

/// Invoices Provider
///
/// Provides list of all invoices from local data source.
@riverpod
class Invoices extends _$Invoices {
  @override
  Future<List<InvoiceModel>> build() async {
    return await ref.read(invoicesLocalDataSourceProvider).getAllInvoices();
  }

  /// Refresh invoices
  Future<void> refresh() async {
    state = const AsyncValue.loading();
    state = await AsyncValue.guard(() async {
      return await ref.read(invoicesLocalDataSourceProvider).getAllInvoices();
    });
  }
}

/// Selected Invoice Status Filter Provider
///
/// Tracks the currently selected invoice status filter for tabs.
/// null means "All" invoices.
@riverpod
class SelectedInvoiceStatusFilter extends _$SelectedInvoiceStatusFilter {
  @override
  String? build() {
    return null; // Default: show all invoices
  }

  /// Select a status filter
  void selectStatus(String? status) {
    state = status;
  }

  /// Clear selection (show all)
  void clearSelection() {
    state = null;
  }
}

/// Filtered Invoices Provider
///
/// Filters invoices by selected status tab.
@riverpod
Future<List<InvoiceModel>> filteredInvoices(Ref ref) async {
  final invoicesAsync = ref.watch(invoicesProvider);
  final selectedStatus = ref.watch(selectedInvoiceStatusFilterProvider);

  return invoicesAsync.when(
    data: (invoices) {
      var filtered = invoices;

      // Filter by status tab
      if (selectedStatus != null) {
        if (selectedStatus == 'unpaid') {
          // Unpaid tab: issued status only
          filtered = filtered
              .where(
                (invoice) =>
                    invoice.status == InvoiceStatus.issued && !invoice.isPaid,
              )
              .toList();
        } else if (selectedStatus == 'overdue') {
          // Overdue tab: overdue status
          filtered = filtered
              .where(
                (invoice) =>
                    invoice.status == InvoiceStatus.overdue ||
                    invoice.isOverdue,
              )
              .toList();
        } else if (selectedStatus == 'paid') {
          // Paid tab: paid status
          filtered = filtered
              .where(
                (invoice) =>
                    invoice.status == InvoiceStatus.paid || invoice.isPaid,
              )
              .toList();
        }
      }

      // Sort by issue date (newest first)
      filtered.sort((a, b) => b.issueDate.compareTo(a.issueDate));

      return filtered;
    },
    loading: () => [],
    error: (error, stack) => [],
  );
}

/// Invoices Count by Status Provider
///
/// Returns count of invoices for each status tab.
@riverpod
Future<Map<String, int>> invoicesCountByStatus(Ref ref) async {
  final invoicesAsync = ref.watch(invoicesProvider);

  return invoicesAsync.when(
    data: (invoices) {
      final counts = <String, int>{};

      // All tab
      counts['all'] = invoices.length;

      // Unpaid tab (issued status)
      counts['unpaid'] = invoices
          .where(
            (invoice) =>
                invoice.status == InvoiceStatus.issued && !invoice.isPaid,
          )
          .length;

      // Overdue tab
      counts['overdue'] = invoices
          .where(
            (invoice) =>
                invoice.status == InvoiceStatus.overdue || invoice.isOverdue,
          )
          .length;

      // Paid tab
      counts['paid'] = invoices
          .where(
            (invoice) => invoice.status == InvoiceStatus.paid || invoice.isPaid,
          )
          .length;

      return counts;
    },
    loading: () => {},
    error: (error, stack) => {},
  );
}

/// Total Invoices Amount Provider
///
/// Returns total amount of all invoices.
@riverpod
Future<double> totalInvoicesAmount(Ref ref) async {
  final invoicesAsync = ref.watch(invoicesProvider);

  return invoicesAsync.when(
    data: (invoices) {
      return invoices.fold<double>(
        0.0,
        (sum, invoice) => sum + invoice.totalAmount,
      );
    },
    loading: () => 0.0,
    error: (error, stack) => 0.0,
  );
}

/// Total Unpaid Amount Provider
///
/// Returns total amount remaining across all unpaid invoices.
@riverpod
Future<double> totalUnpaidAmount(Ref ref) async {
  final invoicesAsync = ref.watch(invoicesProvider);

  return invoicesAsync.when(
    data: (invoices) {
      return invoices.fold<double>(
        0.0,
        (sum, invoice) => sum + invoice.amountRemaining,
      );
    },
    loading: () => 0.0,
    error: (error, stack) => 0.0,
  );
}
