import prisma from '../../config/database';
import { AppError } from '../../shared/middleware/errorHandler';
import { AuditLogger } from '../../shared/utils/auditLogger';

interface CreateInvoiceData {
  dealId?: string;
  items: any[];
  subtotal: number;
  taxAmount: number;
  total: number;
  dueDate: Date;
}

class InvoicesService {
  async create(data: CreateInvoiceData, userId: string) {
    const invoiceNumber = await this.generateInvoiceNumber();
    const invoice = await prisma.invoice.create({
      data: {
        invoiceNumber,
        dealId: data.dealId || null,
        items: data.items,
        subtotal: data.subtotal,
        taxAmount: data.taxAmount,
        total: data.total,
        dueDate: new Date(data.dueDate),
        status: 'DRAFT',
      },
      include: {
        deal: { include: { contact: true, owner: true } },
      },
    });

    await AuditLogger.log({
      entityType: 'INVOICE',
      entityId: invoice.id,
      action: 'CREATE',
      userId,
    });
    return invoice;
  }

  async findById(id: string) {
    const invoice = await prisma.invoice.findUnique({
      where: { id },
      include: {
        deal: { include: { contact: true, owner: true } },
      },
    });
    if (!invoice) throw new AppError(404, 'الفاتورة غير موجودة - Invoice not found');
    return invoice;
  }

  async findByDeal(dealId: string) {
    return prisma.invoice.findMany({
      where: { dealId },
      orderBy: { createdAt: 'desc' },
    });
  }

  async updateStatus(id: string, status: string, userId: string) {
    const invoice = await prisma.invoice.update({
      where: { id },
      data: { status },
      include: { deal: true },
    });
    await AuditLogger.log({
      entityType: 'INVOICE',
      entityId: id,
      action: 'STATUS_CHANGE',
      userId,
      changes: { status },
    });
    return invoice;
  }

  async recordPayment(id: string, paidAmount: number, paidDate: Date, userId: string) {
    const invoice = await prisma.invoice.update({
      where: { id },
      data: {
        status: 'PAID',
        paidAmount,
        paidDate: new Date(paidDate),
      },
      include: { deal: true },
    });
    await AuditLogger.log({
      entityType: 'INVOICE',
      entityId: id,
      action: 'PAYMENT_RECORDED',
      userId,
      changes: { paidAmount, paidDate },
    });
    return invoice;
  }

  async update(id: string, data: Partial<CreateInvoiceData>, userId: string) {
    const updateData: Record<string, any> = { ...data };
    if (updateData.dueDate) updateData.dueDate = new Date(updateData.dueDate);
    const invoice = await prisma.invoice.update({
      where: { id },
      data: updateData,
      include: { deal: { include: { contact: true, owner: true } } },
    });
    await AuditLogger.log({
      entityType: 'INVOICE',
      entityId: id,
      action: 'UPDATE',
      userId,
    });
    return invoice;
  }

  private async generateInvoiceNumber(): Promise<string> {
    const year = new Date().getFullYear();
    const prefix = `INV-${year}-`;
    const last = await prisma.invoice.findFirst({
      where: { invoiceNumber: { startsWith: prefix } },
      orderBy: { createdAt: 'desc' },
      select: { invoiceNumber: true },
    });
    let next = 1;
    if (last) {
      const parts = last.invoiceNumber.split('-');
      next = parseInt(parts[2] || '0') + 1;
    }
    return `${prefix}${next.toString().padStart(6, '0')}`;
  }
}

export const invoicesService = new InvoicesService();
