export interface VisibilityWhere {
  clause: string;
  params: unknown[];
}

export function buildVisibilityWhere(user: Express.User, tableAlias: string): VisibilityWhere {
  if (user.role === 'admin') {
    return { clause: '1=1', params: [] };
  }
  const orgPlaceholders = user.orgIds.length > 0
    ? user.orgIds.map(() => '?').join(',')
    : 'NULL';
  return {
    clause: `(
      ${tableAlias}.owner_id = ?
      OR ${tableAlias}.visibility = 'public'
      OR (${tableAlias}.visibility = 'org' AND ${tableAlias}.visibility_scope_org_id IN (${orgPlaceholders}))
    )`.replace(/\s+/g, ' ').trim(),
    params: [user.id, ...user.orgIds],
  };
}

export function canEditEntity(user: Express.User, entity: { ownerId: string | null }): boolean {
  return user.role === 'admin' || entity.ownerId === user.id;
}

/**
 * 指定 user が指定タスクを閲覧できるか判定する。SQL ではなくロード済みオブジェクト
 * に対して使う。`buildVisibilityWhere` と同じセマンティクスをコード上で再現する。
 *
 * - admin: 常に true
 * - owner: 常に true
 * - public: 常に true
 * - org: user.orgIds に visibilityScopeOrgId が含まれているかで判定
 * - private: owner 以外は false
 */
export function canUserSeeTask(
  user: Express.User,
  task: { ownerId: string | null; visibility: 'private' | 'org' | 'public'; visibilityScopeOrgId: string | null },
): boolean {
  if (user.role === 'admin') return true;
  if (task.ownerId !== null && task.ownerId === user.id) return true;
  if (task.visibility === 'public') return true;
  if (task.visibility === 'org' && task.visibilityScopeOrgId !== null) {
    return user.orgIds.includes(task.visibilityScopeOrgId);
  }
  return false;
}
