import 'server-only'
import { createAdminClient } from '@/lib/supabase/admin'
import { AUTO_ADDITION_METHODS } from '@/lib/domain/auto-participants'
import type { TripParticipant } from '@/types/db'

/**
 * Participant rows as they leave the server for a trip view (§40, Task 10.2,
 * 2026-09-30). Auto-added rows carry the NAMES behind their provenance so the
 * People tab can say "Auto-added via John Smith" / "Auto-added by CP Star
 * LLC"; the rule id itself never reaches the client.
 */
export type WorkspaceParticipant = TripParticipant & {
  triggering_user_name?: string | null
  triggering_company_name?: string | null
}

type Admin = ReturnType<typeof createAdminClient>

/**
 * Resolve `triggering_user_id` → a name (the trip's own participant list
 * first, then `profiles`) and `triggering_company_id` → the company's display
 * name. Tolerant of migration 0049 not being applied: rows are selected with
 * `*`, so the columns are simply absent and nothing is looked up.
 */
export async function enrichParticipantProvenance(
  rows: TripParticipant[],
  admin: Admin = createAdminClient(),
): Promise<WorkspaceParticipant[]> {
  const auto = rows.filter((r) => !!r.addition_method && (AUTO_ADDITION_METHODS as string[]).includes(r.addition_method))
  const userIds = [...new Set(auto.map((r) => r.triggering_user_id).filter((id): id is string => !!id))]
  const companyIds = [...new Set(auto.map((r) => r.triggering_company_id).filter((id): id is string => !!id))]

  const userNames = new Map<string, string>()
  for (const r of rows) if (r.user_id && (r.name || r.email) && !userNames.has(r.user_id)) userNames.set(r.user_id, r.name || r.email)
  const missingUsers = userIds.filter((id) => !userNames.has(id))
  const companyNames = new Map<string, string>()

  const [profiles, companies] = await Promise.all([
    missingUsers.length
      ? admin.from('profiles').select('id, full_name, email').in('id', missingUsers)
      : Promise.resolve({ data: null as null | { id: string; full_name: string | null; email: string | null }[] }),
    companyIds.length
      ? admin.from('companies').select('id, display_name, legal_name').in('id', companyIds)
      : Promise.resolve({ data: null as null | { id: string; display_name: string | null; legal_name: string | null }[] }),
  ])
  for (const p of (profiles.data ?? []) as { id: string; full_name: string | null; email: string | null }[]) {
    const name = p.full_name || p.email
    if (name) userNames.set(p.id, name)
  }
  for (const c of (companies.data ?? []) as { id: string; display_name: string | null; legal_name: string | null }[]) {
    const name = c.display_name || c.legal_name
    if (name) companyNames.set(c.id, name)
  }

  return rows.map((r) => {
    // The rule id is server-side detail (§40): never serialized to a viewer.
    const { auto_participant_rule_id: _ruleId, ...rest } = r
    void _ruleId
    const isAuto = !!r.addition_method && (AUTO_ADDITION_METHODS as string[]).includes(r.addition_method)
    return {
      ...rest,
      triggering_user_name: isAuto && r.triggering_user_id ? userNames.get(r.triggering_user_id) ?? null : null,
      triggering_company_name: isAuto && r.triggering_company_id ? companyNames.get(r.triggering_company_id) ?? null : null,
    }
  })
}
