import 'package:intl/intl.dart';

import '../models/invoice_models.dart';
import '../models/receivable_models.dart';
import 'database_helper.dart';

class ReceivableRepository {
  ReceivableRepository();

  final DatabaseHelper _dbHelper = DatabaseHelper();
  final DateFormat _invoiceNumberDateFormat = DateFormat('yyyyMMdd');

  Future<List<ReceivableInvoiceSummary>> fetchSummaries({bool includeSettled = false}) async {
    final db = await _dbHelper.database;
    final rows = await db.rawQuery('''
      SELECT i.id, i.customer_formal_name, i.date, i.total_amount, i.document_type, i.terminal_id,
             COALESCE(SUM(p.amount), 0) AS paid_amount
      FROM invoices i
      LEFT JOIN receivable_payments p ON p.invoice_id = i.id
      WHERE i.document_type = ? AND COALESCE(i.is_draft, 0) = 0
      GROUP BY i.id
      HAVING (? = 1) OR (i.total_amount - COALESCE(SUM(p.amount), 0)) > 0
      ORDER BY i.date DESC
    ''', [DocumentType.invoice.name, includeSettled ? 1 : 0]);
    return rows.map(_mapToSummary).toList();
  }

  Future<ReceivableInvoiceSummary?> findSummaryById(String invoiceId) async {
    final db = await _dbHelper.database;
    final rows = await db.rawQuery('''
      SELECT i.id, i.customer_formal_name, i.date, i.total_amount, i.document_type, i.terminal_id,
             COALESCE(SUM(p.amount), 0) AS paid_amount
      FROM invoices i
      LEFT JOIN receivable_payments p ON p.invoice_id = i.id
      WHERE i.id = ?
      GROUP BY i.id
      LIMIT 1
    ''', [invoiceId]);
    if (rows.isEmpty) return null;
    return _mapToSummary(rows.first);
  }

  Future<List<ReceivablePayment>> fetchPayments(String invoiceId) async {
    final db = await _dbHelper.database;
    final rows = await db.query(
      'receivable_payments',
      where: 'invoice_id = ?',
      whereArgs: [invoiceId],
      orderBy: 'payment_date DESC, created_at DESC',
    );
    return rows.map(ReceivablePayment.fromMap).toList();
  }

  Future<ReceivablePayment?> findPaymentById(String paymentId) async {
    final db = await _dbHelper.database;
    final rows = await db.query(
      'receivable_payments',
      where: 'id = ?',
      whereArgs: [paymentId],
      limit: 1,
    );
    if (rows.isEmpty) return null;
    return ReceivablePayment.fromMap(rows.first);
  }

  Future<void> insertPayment(ReceivablePayment payment) async {
    final db = await _dbHelper.database;
    await db.insert('receivable_payments', payment.toMap());
  }

  Future<void> deletePayment(String paymentId) async {
    final db = await _dbHelper.database;
    await db.delete('receivable_payments', where: 'id = ?', whereArgs: [paymentId]);
  }

  ReceivableInvoiceSummary _mapToSummary(Map<String, Object?> row) {
    final invoiceDate = DateTime.parse(row['date'] as String);
    final dueDate = invoiceDate.add(const Duration(days: 30));
    final totalAmount = row['total_amount'] as int? ?? 0;
    final paidAmount = row['paid_amount'] as int? ?? 0;
    final documentType = DocumentType.values.firstWhere(
      (type) => type.name == row['document_type'],
      orElse: () => DocumentType.invoice,
    );
    final invoiceNumber = _buildInvoiceNumber(
      prefix: _documentPrefix(documentType),
      terminalId: row['terminal_id'] as String? ?? 'T1',
      invoiceDate: invoiceDate,
      id: row['id'] as String,
    );

    return ReceivableInvoiceSummary(
      invoiceId: row['id'] as String,
      invoiceNumber: invoiceNumber,
      customerName: row['customer_formal_name'] as String? ?? '-',
      invoiceDate: invoiceDate,
      dueDate: dueDate,
      totalAmount: totalAmount,
      paidAmount: paidAmount,
    );
  }

  String _buildInvoiceNumber({
    required String prefix,
    required String terminalId,
    required DateTime invoiceDate,
    required String id,
  }) {
    final suffix = id.length >= 4 ? id.substring(id.length - 4) : id;
    final datePart = _invoiceNumberDateFormat.format(invoiceDate);
    return '$prefix-$terminalId-$datePart-$suffix';
  }

  String _documentPrefix(DocumentType type) {
    switch (type) {
      case DocumentType.estimation:
        return 'EST';
      case DocumentType.delivery:
        return 'DEL';
      case DocumentType.invoice:
        return 'INV';
      case DocumentType.receipt:
        return 'REC';
    }
  }
}
