import { NotFoundError } from '../../lib/errors.js';
import { getCollection } from '../../lib/datastore.js';
import type {
  ListMembershipsQuery,
  ListOrganizationsQuery,
  MembershipDoc,
  OrganizationDoc,
  WorkspaceDoc,
} from './types.js';

function orgCollection() {
  return getCollection<OrganizationDoc>('organizations', '/productId');
}

function workspaceCollection() {
  return getCollection<WorkspaceDoc>('workspaces', '/orgId');
}

function membershipCollection() {
  return getCollection<MembershipDoc>('org_memberships', '/orgId');
}

export async function createOrganization(doc: OrganizationDoc): Promise<OrganizationDoc> {
  return orgCollection().create(doc);
}

export async function listOrganizations(
  productId: string,
  query: ListOrganizationsQuery
): Promise<OrganizationDoc[]> {
  return orgCollection().findMany({
    filter: {
      productId,
      ...(query.status ? { status: query.status } : {}),
    },
    sort: { createdAt: -1 },
    limit: query.limit,
  });
}

export async function getOrganization(id: string, productId: string): Promise<OrganizationDoc> {
  const org = await orgCollection().findById(id, productId);
  if (!org) throw new NotFoundError(`Organization '${id}' not found`);
  return org;
}

export async function updateOrganization(
  id: string,
  productId: string,
  updates: Partial<OrganizationDoc>
): Promise<OrganizationDoc> {
  const updated = await orgCollection().update(id, productId, {
    ...updates,
    updatedAt: new Date().toISOString(),
  });
  if (!updated) throw new NotFoundError(`Organization '${id}' not found`);
  return updated;
}

export async function createWorkspace(doc: WorkspaceDoc): Promise<WorkspaceDoc> {
  return workspaceCollection().create(doc);
}

export async function listWorkspaces(orgId: string): Promise<WorkspaceDoc[]> {
  return workspaceCollection().findMany({
    filter: { orgId },
    sort: { createdAt: -1 },
    limit: 100,
  });
}

export async function getWorkspace(id: string, orgId: string): Promise<WorkspaceDoc> {
  const workspace = await workspaceCollection().findById(id, orgId);
  if (!workspace) throw new NotFoundError(`Workspace '${id}' not found`);
  return workspace;
}

export async function updateWorkspace(
  id: string,
  orgId: string,
  updates: Partial<WorkspaceDoc>
): Promise<WorkspaceDoc> {
  const updated = await workspaceCollection().update(id, orgId, {
    ...updates,
    updatedAt: new Date().toISOString(),
  });
  if (!updated) throw new NotFoundError(`Workspace '${id}' not found`);
  return updated;
}

export async function createMembership(doc: MembershipDoc): Promise<MembershipDoc> {
  return membershipCollection().create(doc);
}

export async function listMemberships(
  orgId: string,
  query: ListMembershipsQuery
): Promise<MembershipDoc[]> {
  const memberships = await membershipCollection().findMany({
    filter: {
      orgId,
      ...(query.scope ? { scope: query.scope } : {}),
      ...(query.workspaceId ? { workspaceId: query.workspaceId } : {}),
    },
    sort: { createdAt: -1 },
    limit: query.limit,
  });
  return memberships;
}

export async function getMembership(id: string, orgId: string): Promise<MembershipDoc> {
  const membership = await membershipCollection().findById(id, orgId);
  if (!membership) throw new NotFoundError(`Membership '${id}' not found`);
  return membership;
}

export async function updateMembership(
  id: string,
  orgId: string,
  updates: Partial<MembershipDoc>
): Promise<MembershipDoc> {
  const updated = await membershipCollection().update(id, orgId, {
    ...updates,
    updatedAt: new Date().toISOString(),
  });
  if (!updated) throw new NotFoundError(`Membership '${id}' not found`);
  return updated;
}

export async function deleteMembership(id: string, orgId: string): Promise<void> {
  await membershipCollection().delete(id, orgId);
}

export async function getUserMembership(
  orgId: string,
  userId: string
): Promise<MembershipDoc | null> {
  const results = await membershipCollection().findMany({
    filter: { orgId, userId, scope: 'org' },
    limit: 1,
  });
  return results[0] ?? null;
}

export async function deleteOrganization(id: string, productId: string): Promise<void> {
  await orgCollection().delete(id, productId);
}

export async function deleteWorkspace(id: string, orgId: string): Promise<void> {
  await workspaceCollection().delete(id, orgId);
}
