import { auditAction } from '@/features/foundation/audit-log/service';
import { hasCrmPermission, hasBranchScopeAccess, hasProductScopeAccess } from '@/lib/auth/crm-access';
import { PERMISSIONS } from '@/lib/auth/rbac';

export interface CrmSecurityContext {
  organizationId: string;
  userId: string;
  membershipRole: string;
  businessRole: string;
  businessRoles?: string[];
  permissions: string[];
  branchScopeIds: string[];
  productTypeScopeIds: string[];
  ownershipScope: string;
  branchScopeMode: string;
  productScopeMode: string;
  approvalAuthority?: string | null;
}

export function buildCrmSecurityContext(input: {
  organizationId: string;
  userId: string;
  membership: {
    role: string;
    businessRole: string;
    businessRoles?: string[];
    permissions?: string[] | null;
    branchScopeIds?: string[] | null;
    productTypeScopeIds?: string[] | null;
    ownershipScope?: string | null;
    branchScopeMode?: string | null;
    productScopeMode?: string | null;
    approvalAuthority?: string | null;
  };
}): CrmSecurityContext {
  return {
    organizationId: input.organizationId,
    userId: input.userId,
    membershipRole: input.membership.role,
    businessRole: input.membership.businessRole,
    businessRoles: input.membership.businessRoles ?? [input.membership.businessRole],
    permissions: input.membership.permissions ?? [],
    branchScopeIds: input.membership.branchScopeIds ?? [],
    productTypeScopeIds: input.membership.productTypeScopeIds ?? [],
    ownershipScope: input.membership.ownershipScope ?? 'organization',
    branchScopeMode: input.membership.branchScopeMode ?? 'all',
    productScopeMode: input.membership.productScopeMode ?? 'all',
    approvalAuthority: input.membership.approvalAuthority ?? null
  };
}

export function canViewQuotationPricing(context: Pick<CrmSecurityContext, 'permissions'>) {
  return hasCrmPermission(context, PERMISSIONS.crmQuotationPricingRead);
}

export function canAccessScopedCrmRecord(
  context: Pick<
    CrmSecurityContext,
    | 'membershipRole'
    | 'userId'
    | 'ownershipScope'
    | 'branchScopeMode'
    | 'branchScopeIds'
    | 'productScopeMode'
    | 'productTypeScopeIds'
  >,
  row: {
    branchId?: string | null;
    productType?: string | null;
    createdBy?: string | null;
    ownerUserId?: string | null;
  }
) {
  if (!hasBranchScopeAccess(context, row.branchId)) {
    return false;
  }

  if (!hasProductScopeAccess(context, row.productType)) {
    return false;
  }

  if (context.membershipRole === 'admin' || context.ownershipScope !== 'own') {
    return true;
  }

  return row.createdBy === context.userId || row.ownerUserId === context.userId;
}

export function canAccessCustomer(
  context: Pick<
    CrmSecurityContext,
    | 'membershipRole'
    | 'userId'
    | 'ownershipScope'
    | 'branchScopeMode'
    | 'branchScopeIds'
    | 'productScopeMode'
    | 'productTypeScopeIds'
  >,
  row: {
    branchId?: string | null;
    createdBy?: string | null;
    ownerUserId?: string | null;
  }
) {
  return canAccessScopedCrmRecord(context, {
    branchId: row.branchId,
    createdBy: row.createdBy,
    ownerUserId: row.ownerUserId
  });
}

export function canAccessContact(
  context: Pick<
    CrmSecurityContext,
    | 'membershipRole'
    | 'userId'
    | 'ownershipScope'
    | 'branchScopeMode'
    | 'branchScopeIds'
    | 'productScopeMode'
    | 'productTypeScopeIds'
  >,
  row: {
    branchId?: string | null;
    createdBy?: string | null;
    ownerUserId?: string | null;
    sharedToUserIds?: string[] | null;
  }
) {
  if (!hasBranchScopeAccess(context, row.branchId)) {
    return false;
  }

  if (context.membershipRole === 'admin' || context.ownershipScope === 'organization' || context.ownershipScope === 'team') {
    return true;
  }

  return (
    row.createdBy === context.userId ||
    row.ownerUserId === context.userId ||
    (row.sharedToUserIds ?? []).includes(context.userId)
  );
}

export async function auditCrmSecurityEvent(input: {
  organizationId: string;
  userId: string;
  action:
    | 'access_denied'
    | 'scope_violation'
    | 'permission_violation'
    | 'pricing_hidden'
    | 'customer_scope_violation'
    | 'contact_scope_violation'
    | 'approval_scope_violation';
  entityType: string;
  entityId: string;
  reason: string;
  metadata?: Record<string, unknown>;
}) {
  await auditAction({
    organizationId: input.organizationId,
    userId: input.userId,
    entityType: 'crm_security_access',
    entityId: `${input.entityType}:${input.entityId}`,
    action: input.action,
    afterData: {
      targetEntityType: input.entityType,
      targetEntityId: input.entityId,
      reason: input.reason,
      ...input.metadata
    }
  });
}
