/**
 * KB settings repository — settings-kb (wave-14).
 *
 * Reads and writes the KB-specific columns of the shared `tenant_settings`
 * singleton row.  Functions are tenant-scoped and safe to call from route
 * handlers (imported via @zync/db/queries, NOT directly from the schema).
 */
import { eq, and } from 'drizzle-orm'
import type { Db } from '../client'
import { tenantSettings, kbSpaces } from '../schema'
import type { TenantKbSettings } from '../schema'

// ── Defaults (used when no tenant_settings row exists) ────────────────────────

const DEFAULTS: Omit<TenantKbSettings, 'tenant_id'> = {
  kb_require_review: false,
  kb_versioning_enabled: true,
  kb_default_space_id: null,
}

// ── Typed error ───────────────────────────────────────────────────────────────

export class KbDefaultSpaceCrossTenantError extends Error {
  constructor() {
    super('kb_default_space_id does not belong to this tenant')
    this.name = 'KbDefaultSpaceCrossTenantError'
  }
}

// ── Queries ───────────────────────────────────────────────────────────────────

/**
 * Return the tenant's KB settings.
 * If no `tenant_settings` row exists yet, returns canonical defaults WITHOUT
 * inserting a row.
 */
export async function getKbSettings(db: Db, tenantId: string): Promise<TenantKbSettings> {
  const [row] = await db
    .select({
      tenantId: tenantSettings.tenantId,
      kbRequireReview: tenantSettings.kbRequireReview,
      kbVersioningEnabled: tenantSettings.kbVersioningEnabled,
      kbDefaultSpaceId: tenantSettings.kbDefaultSpaceId,
    })
    .from(tenantSettings)
    .where(eq(tenantSettings.tenantId, tenantId))
    .limit(1)

  if (!row) {
    return { tenant_id: tenantId, ...DEFAULTS }
  }

  return {
    tenant_id: row.tenantId,
    kb_require_review: row.kbRequireReview,
    kb_versioning_enabled: row.kbVersioningEnabled,
    kb_default_space_id: row.kbDefaultSpaceId ?? null,
  }
}

/**
 * Upsert the tenant's KB settings (partial patch).
 *
 * Validates that `kb_default_space_id` (when non-null) belongs to the same
 * tenant before writing; throws `KbDefaultSpaceCrossTenantError` otherwise.
 */
export async function upsertKbSettings(
  db: Db,
  tenantId: string,
  patch: Partial<Pick<TenantKbSettings, 'kb_require_review' | 'kb_versioning_enabled' | 'kb_default_space_id'>>,
): Promise<TenantKbSettings> {
  // Validate kb_default_space_id tenant ownership when being set to a non-null value
  if (patch.kb_default_space_id != null) {
    const [space] = await db
      .select({ id: kbSpaces.id })
      .from(kbSpaces)
      .where(and(eq(kbSpaces.id, patch.kb_default_space_id), eq(kbSpaces.tenantId, tenantId)))
      .limit(1)
    if (!space) {
      throw new KbDefaultSpaceCrossTenantError()
    }
  }

  const updateSet: Record<string, unknown> = {
    updatedAt: new Date(),
  }
  if (patch.kb_require_review !== undefined) updateSet.kbRequireReview = patch.kb_require_review
  if (patch.kb_versioning_enabled !== undefined) updateSet.kbVersioningEnabled = patch.kb_versioning_enabled
  if ('kb_default_space_id' in patch) updateSet.kbDefaultSpaceId = patch.kb_default_space_id

  const rows = await db
    .insert(tenantSettings)
    .values({
      tenantId,
      kbRequireReview: patch.kb_require_review ?? DEFAULTS.kb_require_review,
      kbVersioningEnabled: patch.kb_versioning_enabled ?? DEFAULTS.kb_versioning_enabled,
      kbDefaultSpaceId: patch.kb_default_space_id ?? null,
    })
    .onConflictDoUpdate({
      target: tenantSettings.tenantId,
      set: updateSet,
    })
    .returning({
      tenantId: tenantSettings.tenantId,
      kbRequireReview: tenantSettings.kbRequireReview,
      kbVersioningEnabled: tenantSettings.kbVersioningEnabled,
      kbDefaultSpaceId: tenantSettings.kbDefaultSpaceId,
    })

  const updated = rows[0]
  if (!updated) {
    // Fallback: re-read settings (should not happen in practice)
    return getKbSettings(db, tenantId)
  }

  return {
    tenant_id: updated.tenantId,
    kb_require_review: updated.kbRequireReview,
    kb_versioning_enabled: updated.kbVersioningEnabled,
    kb_default_space_id: updated.kbDefaultSpaceId ?? null,
  }
}
