/**
 * Organization Data Utilities
 *
 * Provides helpers for organization-aware data queries.
 * When a user is a member of an organization (STAFF/ADMIN),
 * they should see all of the organization's data (appointments,
 * customers, conversations, etc.) instead of their own empty data.
 *
 * All data access goes through Convex. No Prisma fallback.
 */

import { convexQuery } from '@/lib/convex-client';
import { logger } from '@/lib/logger';

/**
 * Result from getEffectiveDataOwnerId
 */
export interface EffectiveOwnerResult {
  /** The user ID to use for data queries (either original user or org owner) */
  effectiveUserId: string;
  /** Whether this user is part of an organization */
  isOrganizationMember: boolean;
  /** Organization ID if user is a member */
  organizationId?: string;
  /** Organization name if user is a member */
  organizationName?: string;
  /** User's role in the organization */
  role?: 'OWNER' | 'ADMIN' | 'STAFF';
}

/**
 * Get the effective owner user ID for data queries.
 *
 * For organization members (STAFF/ADMIN), returns the organization owner's ID
 * so they can see all organization data (appointments, customers, conversations).
 * For organization owners or solo users, returns their own ID.
 *
 * @param userId - The authenticated user's ID
 * @returns The effective user ID to use for data queries, with metadata
 */
export async function getEffectiveDataOwnerId(
  userId: string
): Promise<EffectiveOwnerResult> {
  try {
    const orgState = await convexQuery<Record<string, unknown>>(
      "organizations/queries:getOrganizationStateByUserId",
      { userId }
    );

    if (!orgState) {
      return {
        effectiveUserId: userId,
        isOrganizationMember: false,
      };
    }

    const userRole = orgState.userRole as string | undefined;
    const organization = orgState.organization as Record<string, unknown> | undefined;

    if (!organization || !userRole) {
      return {
        effectiveUserId: userId,
        isOrganizationMember: false,
      };
    }

    const orgId = (organization._id as string) || (organization.id as string);
    const orgName = (organization.name as string) || '';
    const role = userRole as 'OWNER' | 'ADMIN' | 'STAFF';

    // For OWNER role, they already own the data - use their own ID
    if (role === 'OWNER') {
      return {
        effectiveUserId: userId,
        isOrganizationMember: true,
        organizationId: orgId,
        organizationName: orgName,
        role,
      };
    }

    // For ADMIN/STAFF, use the organization owner's ID to see all org data
    const ownerId = organization.ownerId as string | undefined;

    logger.debug('[getEffectiveDataOwnerId] Org member accessing owner data', {
      userId,
      ownerId,
      role,
      organizationId: orgId,
    });

    return {
      effectiveUserId: ownerId || userId,
      isOrganizationMember: true,
      organizationId: orgId,
      organizationName: orgName,
      role,
    };
  } catch (error) {
    logger.error('[getEffectiveDataOwnerId] Error checking org membership', {
      userId,
      error: error instanceof Error ? error.message : String(error),
    });

    return {
      effectiveUserId: userId,
      isOrganizationMember: false,
    };
  }
}

/**
 * Simplified helper that just returns the effective user ID string.
 * Use this when you only need the ID and don't need org metadata.
 *
 * @param userId - The authenticated user's ID
 * @returns The effective user ID to use for data queries
 */
export async function getEffectiveOwnerId(userId: string): Promise<string> {
  const result = await getEffectiveDataOwnerId(userId);
  return result.effectiveUserId;
}

/**
 * Get all user IDs in an organization for queries that need to include
 * all members' data (e.g., for analytics or reporting).
 *
 * @param userId - Any user ID in the organization
 * @returns Array of all user IDs in the organization, or just the userId if not in org
 */
export async function getOrganizationUserIds(userId: string): Promise<string[]> {
  try {
    const orgState = await convexQuery<Record<string, unknown>>(
      "organizations/queries:getOrganizationStateByUserId",
      { userId }
    );

    if (!orgState) {
      return [userId];
    }

    const organization = orgState.organization as Record<string, unknown> | undefined;
    if (!organization) {
      return [userId];
    }

    // Try to get all members from Convex
    const orgId = (organization._id as string) || (organization.id as string);
    const members = await convexQuery<Array<{ userId: string }>>(
      "organizations/queries:getOrganizationMembers",
      { organizationId: orgId }
    );

    if (members && Array.isArray(members)) {
      return members.map((m) => m.userId);
    }

    return [userId];
  } catch (error) {
    logger.error('[getOrganizationUserIds] Error', {
      userId,
      error: error instanceof Error ? error.message : String(error),
    });
    return [userId];
  }
}
