import { describe, expect, it } from "vitest"
import type { SupabaseClient } from "@supabase/supabase-js"

import { buildGdprExport, USER_OWNED_TABLES } from "../export"

/**
 * Tests for the GDPR export helper (KAR-529).
 *
 * The helper is a pure function around a Supabase client. We mock the client
 * with a chainable .from().select().eq().maybeSingle() shape that captures
 * the calls so the test can assert (a) every user-owned table is queried,
 * (b) the predicate column matches the configured ownership column, (c) the
 * envelope (generated_at, user_id, schema_version) is well-formed.
 */

function makeMockClient(rows: Record<string, unknown[]>): {
  client: SupabaseClient
  calls: Array<{ table: string; column?: string }>
} {
  const calls: Array<{ table: string; column?: string }> = []

  const builder = (table: string): unknown => {
    let predicateColumn: string | undefined
    const chain = {
      select() {
        return chain
      },
      eq(column: string) {
        predicateColumn = column
        return chain
      },
      maybeSingle() {
        calls.push({ table, column: predicateColumn })
        return Promise.resolve({ data: rows[table]?.[0] ?? null, error: null })
      },
      then(onfulfilled: (value: { data: unknown[]; error: null }) => unknown) {
        calls.push({ table, column: predicateColumn })
        return Promise.resolve({ data: rows[table] ?? [], error: null }).then(
          onfulfilled,
        )
      },
    }
    return chain
  }

  const client = { from: builder } as unknown as SupabaseClient
  return { client, calls }
}

describe("buildGdprExport (KAR-529)", () => {
  it("queries the profile row and every user-owned table", async () => {
    const { client, calls } = makeMockClient({})
    const result = await buildGdprExport(client, "user-123")

    expect(result.schema_version).toBe(1)
    expect(result.user_id).toBe("user-123")
    expect(result.generated_at).toMatch(/^\d{4}-\d{2}-\d{2}T/)

    const tablesQueried = calls.map((c) => c.table)
    expect(tablesQueried).toContain("user_profiles")
    for (const [table] of USER_OWNED_TABLES) {
      expect(tablesQueried).toContain(table)
    }
  })

  it("uses the configured ownership column per table", async () => {
    const { client, calls } = makeMockClient({})
    await buildGdprExport(client, "user-123")

    for (const [table, column] of USER_OWNED_TABLES) {
      const call = calls.find((c) => c.table === table)
      expect(call?.column).toBe(column)
    }
  })

  it("includes the profile row when present", async () => {
    const profileRow = { id: "p1", auth_user_id: "user-123", first_name: "X" }
    const { client } = makeMockClient({ user_profiles: [profileRow] })
    const result = await buildGdprExport(client, "user-123")
    expect(result.profile).toEqual(profileRow)
  })

  it("returns empty arrays for tables with no rows", async () => {
    const { client } = makeMockClient({})
    const result = await buildGdprExport(client, "user-456")
    for (const [table] of USER_OWNED_TABLES) {
      expect(result.tables[table]).toEqual([])
    }
  })
})
