import { and, eq, isNull } from 'drizzle-orm';
import { crmOpportunities, crmQuotations } from '@/db/schema';
import { auditAction } from '@/features/foundation/audit-log/service';
import { db } from '@/lib/db';
import { AuthError } from '@/lib/auth/session';

export async function assertOpportunityLinkIntegrity(args: {
  organizationId: string;
  opportunityId: string | null | undefined;
  customerId: string;
  productType?: string | null;
}) {
  if (!args.opportunityId) {
    return null;
  }

  const [opportunity] = await db
    .select()
    .from(crmOpportunities)
    .where(
      and(
        eq(crmOpportunities.id, args.opportunityId),
        eq(crmOpportunities.organizationId, args.organizationId),
        isNull(crmOpportunities.deletedAt)
      )
    )
    .limit(1);

  if (!opportunity) {
    throw new AuthError('Opportunity not found', 404);
  }

  if ((opportunity.outcomeStatus ?? 'open') !== 'open') {
    throw new AuthError('Closed opportunity cannot create quotation', 400);
  }

  if (opportunity.customerId !== args.customerId) {
    throw new AuthError('Quotation customer must match linked opportunity customer', 400);
  }

  if (args.productType && opportunity.productType !== args.productType) {
    throw new AuthError('Quotation product type must match linked opportunity product type', 400);
  }

  return opportunity;
}

export async function assertRevisionOpportunityLinkIntegrity(args: {
  organizationId: string;
  quotationId: string;
}) {
  const [quotation] = await db
    .select()
    .from(crmQuotations)
    .where(
      and(
        eq(crmQuotations.id, args.quotationId),
        eq(crmQuotations.organizationId, args.organizationId),
        isNull(crmQuotations.deletedAt)
      )
    )
    .limit(1);

  if (!quotation) {
    throw new AuthError('Quotation not found', 404);
  }

  return quotation.opportunityId ?? null;
}

export async function auditQuotationOpportunityLink(args: {
  organizationId: string;
  userId: string;
  quotationId: string;
  opportunityId: string | null;
  previousOpportunityId?: string | null;
  reason: string;
}) {
  if (!args.opportunityId && !args.previousOpportunityId) {
    return;
  }

  await auditAction({
    organizationId: args.organizationId,
    userId: args.userId,
    entityType: 'crm_quotation',
    entityId: args.quotationId,
    action: 'sync_quotation_opportunity_link',
    afterData: {
      quotationId: args.quotationId,
      opportunityId: args.opportunityId,
      previousOpportunityId: args.previousOpportunityId ?? null,
      reason: args.reason,
      actedBy: args.userId
    }
  });
}
