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

interface CreateContractData {
  dealId: string;
  title: string;
  type: string;
  clientInfo: any;
  companyInfo: any;
  startDate: Date;
  endDate?: Date;
  value: number;
  paymentTerms: any;
  deliveryTerms: any;
  terms: string;
}

class ContractsService {
  async create(data: CreateContractData, userId: string) {
    const contractNumber = await this.generateContractNumber();
    const contract = await prisma.contract.create({
      data: {
        contractNumber,
        dealId: data.dealId,
        title: data.title,
        type: data.type,
        clientInfo: data.clientInfo || {},
        companyInfo: data.companyInfo || {},
        startDate: new Date(data.startDate),
        endDate: data.endDate ? new Date(data.endDate) : null,
        value: data.value,
        paymentTerms: data.paymentTerms || {},
        deliveryTerms: data.deliveryTerms || {},
        terms: data.terms,
        status: 'DRAFT',
      },
      include: {
        deal: { include: { contact: true, owner: true } },
      },
    });

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

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

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

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

  async markSigned(id: string, userId: string) {
    const contract = await prisma.contract.update({
      where: { id },
      data: { status: 'ACTIVE', signedAt: new Date() },
      include: { deal: true },
    });
    await AuditLogger.log({
      entityType: 'CONTRACT',
      entityId: id,
      action: 'SIGN',
      userId,
    });
    return contract;
  }

  async update(id: string, data: Partial<CreateContractData>, userId: string) {
    const updateData: Record<string, any> = { ...data };
    if (updateData.startDate) updateData.startDate = new Date(updateData.startDate);
    if (updateData.endDate !== undefined) updateData.endDate = updateData.endDate ? new Date(updateData.endDate) : null;
    const contract = await prisma.contract.update({
      where: { id },
      data: updateData,
      include: { deal: { include: { contact: true, owner: true } } },
    });
    await AuditLogger.log({
      entityType: 'CONTRACT',
      entityId: id,
      action: 'UPDATE',
      userId,
    });
    return contract;
  }

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

export const contractsService = new ContractsService();
