import { NotFoundError } from '../../lib/errors.js';
import { getCollection } from '../../lib/datastore.js';
import type {
  ScimConnectorDoc,
  ScimGroupSyncDoc,
  ScimProvisioningEventDoc,
  ScimUserSyncDoc,
} from './types.js';

function connectorCollection() {
  return getCollection<ScimConnectorDoc>('scim_connectors', '/orgId');
}

function userSyncCollection() {
  return getCollection<ScimUserSyncDoc>('scim_user_sync', '/connectorId');
}

function groupSyncCollection() {
  return getCollection<ScimGroupSyncDoc>('scim_group_sync', '/connectorId');
}

function eventCollection() {
  return getCollection<ScimProvisioningEventDoc>('scim_events', '/connectorId');
}

export async function createConnector(doc: ScimConnectorDoc): Promise<ScimConnectorDoc> {
  return connectorCollection().create(doc);
}

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

export async function getConnector(id: string, orgId: string): Promise<ScimConnectorDoc> {
  const connector = await connectorCollection().findById(id, orgId);
  if (!connector) throw new NotFoundError(`SCIM connector '${id}' not found`);
  return connector;
}

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

export async function upsertUserSync(doc: ScimUserSyncDoc): Promise<ScimUserSyncDoc> {
  return userSyncCollection().upsert(doc);
}

export async function listUserSync(connectorId: string): Promise<ScimUserSyncDoc[]> {
  return userSyncCollection().findMany({
    filter: { connectorId },
    sort: { lastSyncedAt: -1 },
    limit: 500,
  });
}

export async function upsertGroupSync(doc: ScimGroupSyncDoc): Promise<ScimGroupSyncDoc> {
  return groupSyncCollection().upsert(doc);
}

export async function listGroupSync(connectorId: string): Promise<ScimGroupSyncDoc[]> {
  return groupSyncCollection().findMany({
    filter: { connectorId },
    sort: { lastSyncedAt: -1 },
    limit: 500,
  });
}

export async function createEvent(
  doc: ScimProvisioningEventDoc
): Promise<ScimProvisioningEventDoc> {
  return eventCollection().create(doc);
}

export async function listEvents(connectorId: string): Promise<ScimProvisioningEventDoc[]> {
  return eventCollection().findMany({
    filter: { connectorId },
    sort: { createdAt: -1 },
    limit: 500,
  });
}

export interface ScimConnectorStats {
  connectorId: string;
  userCount: number;
  groupCount: number;
  eventCount: number;
  provisionedUsers: number;
  failedUsers: number;
  provisionedGroups: number;
  failedGroups: number;
  lastEventAt: string | null;
}

export async function getConnectorStats(connectorId: string): Promise<ScimConnectorStats> {
  const [users, groups, events] = await Promise.all([
    listUserSync(connectorId),
    listGroupSync(connectorId),
    listEvents(connectorId),
  ]);

  return {
    connectorId,
    userCount: users.length,
    groupCount: groups.length,
    eventCount: events.length,
    provisionedUsers: users.filter(u => u.status === 'provisioned').length,
    failedUsers: users.filter(u => u.status === 'failed').length,
    provisionedGroups: groups.filter(g => g.status === 'provisioned').length,
    failedGroups: groups.filter(g => g.status === 'failed').length,
    lastEventAt: events[0]?.createdAt ?? null,
  };
}

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