import 'dart:async';

import 'package:uuid/uuid.dart';

import '../models/hash_chain_models.dart';
import '../models/receivable_models.dart';
import 'business_calendar_mapper.dart';
import 'invoice_repository.dart';
import 'receivable_repository.dart';

class ReceivableService {
  ReceivableService({ReceivableRepository? repository, BusinessCalendarMapper? calendarMapper})
      : _repository = repository ?? ReceivableRepository(),
        _calendarMapper = calendarMapper ?? BusinessCalendarMapper();

  final ReceivableRepository _repository;
  final InvoiceRepository _invoiceRepository = InvoiceRepository();
  final BusinessCalendarMapper _calendarMapper;
  final Uuid _uuid = const Uuid();

  Future<List<ReceivableInvoiceSummary>> fetchSummaries({bool includeSettled = false}) async {
    final summaries = await _repository.fetchSummaries(includeSettled: includeSettled);
    unawaited(_calendarMapper.syncReceivables(summaries));
    return summaries;
  }

  Future<ReceivableInvoiceSummary?> findSummary(String invoiceId) async {
    final summary = await _repository.findSummaryById(invoiceId);
    if (summary != null) {
      unawaited(_calendarMapper.syncReceivable(summary));
    }
    return summary;
  }

  Future<List<ReceivablePayment>> fetchPayments(String invoiceId) {
    return _repository.fetchPayments(invoiceId);
  }

  Future<void> addPayment({
    required String invoiceId,
    required int amount,
    required DateTime paymentDate,
    required PaymentMethod method,
    String? notes,
  }) async {
    if (amount <= 0) {
      throw ArgumentError('amount must be greater than 0');
    }
    final payment = ReceivablePayment(
      id: _uuid.v4(),
      invoiceId: invoiceId,
      amount: amount,
      paymentDate: paymentDate,
      method: method,
      notes: notes,
      createdAt: DateTime.now(),
    );
    await _repository.insertPayment(payment);
    final summary = await _repository.findSummaryById(invoiceId);
    if (summary != null) {
      unawaited(_calendarMapper.syncReceivable(summary));
    }
  }

  Future<void> deletePayment(String paymentId) async {
    final payment = await _repository.findPaymentById(paymentId);
    await _repository.deletePayment(paymentId);
    if (payment != null) {
      final summary = await _repository.findSummaryById(payment.invoiceId);
      if (summary != null) {
        unawaited(_calendarMapper.syncReceivable(summary));
      }
    }
  }

  Future<HashChainVerificationResult> verifyHashChain() {
    return _invoiceRepository.verifyHashChain();
  }
}
