/**
 * Edge Function: invite-user
 * Propósito: invitar usuario externo (client_editor/client_viewer) o interno (member)
 * Solo accesible por platform_admin.
 * Variables de entorno requeridas: SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, SITE_URL
 *   - SUPABASE_URL y SUPABASE_SERVICE_ROLE_KEY: disponibles automáticamente en Edge Functions
 *   - SITE_URL: agregar manualmente en Supabase Dashboard → Edge Functions → Secrets
 *     Valor producción: https://inq-roi.inqualityhq.com
 * Deploy: supabase functions deploy invite-user
 */

import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

interface InviteUserRequest {
  email: string
  name: string
  platform_role: 'client_editor' | 'client_viewer' | 'member'
  org_name?: string
}

const ALLOWED_ROLES = ['client_editor', 'client_viewer', 'member'] as const
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

Deno.serve(async (req: Request) => {
  const headers = {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'POST, OPTIONS',
    'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
  }

  // Manejar CORS preflight
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers })
  }

  if (req.method !== 'POST') {
    return new Response(JSON.stringify({ error: 'Método no permitido' }), { status: 405, headers })
  }

  const adminClient = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
  )

  // ── 1. Autenticar al llamador ──────────────────────────────────────────────

  const callerToken = req.headers.get('Authorization')?.replace('Bearer ', '')
  if (!callerToken) {
    return new Response(JSON.stringify({ error: 'Authorization header requerido' }), { status: 401, headers })
  }

  const { data: { user: caller }, error: authError } = await adminClient.auth.getUser(callerToken)
  if (authError || !caller) {
    return new Response(JSON.stringify({ error: 'Token inválido o expirado' }), { status: 401, headers })
  }

  // Verificar platform_role desde DB — el JWT no es fuente confiable para el rol
  const { data: callerProfile, error: profileError } = await adminClient
    .from('users')
    .select('platform_role')
    .eq('id', caller.id)
    .single()

  if (profileError || callerProfile?.platform_role !== 'platform_admin') {
    return new Response(JSON.stringify({ error: 'Forbidden: solo platform_admin puede invitar usuarios' }), { status: 403, headers })
  }

  // ── 2. Parsear y validar el body ──────────────────────────────────────────

  let body: InviteUserRequest
  try {
    body = await req.json() as InviteUserRequest
  } catch {
    return new Response(JSON.stringify({ error: 'Body JSON inválido' }), { status: 400, headers })
  }

  const { email, name, platform_role, org_name } = body

  if (!email || !EMAIL_REGEX.test(email)) {
    return new Response(JSON.stringify({ error: 'Email inválido o no proporcionado' }), { status: 400, headers })
  }

  if (!name?.trim()) {
    return new Response(JSON.stringify({ error: 'El campo name es requerido' }), { status: 400, headers })
  }

  if (!platform_role || !ALLOWED_ROLES.includes(platform_role)) {
    return new Response(
      JSON.stringify({ error: `platform_role debe ser uno de: ${ALLOWED_ROLES.join(', ')}` }),
      { status: 400, headers },
    )
  }

  if ((platform_role === 'client_editor' || platform_role === 'client_viewer') && !org_name?.trim()) {
    return new Response(
      JSON.stringify({ error: 'org_name es requerido para roles client_editor y client_viewer' }),
      { status: 400, headers },
    )
  }

  // ── 3. Resolver org_id ────────────────────────────────────────────────────

  let orgId: string

  if (platform_role === 'member') {
    // Nuevo miembro InQuality → la org es siempre InQuality (is_provider = true)
    const { data: inqOrg, error: inqOrgError } = await adminClient
      .from('organizations')
      .select('id')
      .eq('is_provider', true)
      .single()

    if (inqOrgError || !inqOrg) {
      return new Response(
        JSON.stringify({ error: 'No se encontró la organización InQuality en la base de datos' }),
        { status: 500, headers },
      )
    }
    orgId = inqOrg.id
  } else {
    // Usuario cliente → buscar org por nombre exacto (trim), crear si no existe
    const trimmedOrgName = org_name!.trim()

    const { data: existingOrg } = await adminClient
      .from('organizations')
      .select('id')
      .eq('name', trimmedOrgName)
      .single()

    if (existingOrg) {
      orgId = existingOrg.id
    } else {
      const { data: newOrg, error: createOrgError } = await adminClient
        .from('organizations')
        .insert({ name: trimmedOrgName, is_provider: false })
        .select('id')
        .single()

      if (createOrgError || !newOrg) {
        return new Response(
          JSON.stringify({ error: `Error al crear organización: ${createOrgError?.message ?? 'desconocido'}` }),
          { status: 500, headers },
        )
      }
      orgId = newOrg.id
    }
  }

  // ── 4. Invitar usuario vía Auth Admin API ─────────────────────────────────
  // inviteUserByEmail crea el usuario en auth.users y envía el email de bienvenida.
  // Si el email ya existe en auth.users, retorna un error descriptivo.

  const { data: inviteData, error: inviteError } = await adminClient.auth.admin.inviteUserByEmail(
    email,
    {
      data: { full_name: name.trim() }, // se almacena en raw_user_meta_data
      redirectTo: `${Deno.env.get('SITE_URL') ?? ''}/auth/callback`,
    },
  )

  if (inviteError) {
    return new Response(
      JSON.stringify({ error: inviteError.message }),
      { status: 400, headers },
    )
  }

  // ── 5. Crear fila en public.users ─────────────────────────────────────────
  // UPSERT con ignoreDuplicates: false para manejar la race condition con handle_new_user:
  // si el trigger ya creó la fila (emails @inquality.com.py), actualizar platform_role y org_id.

  const { error: upsertError } = await adminClient
    .from('users')
    .upsert(
      {
        id: inviteData.user.id,
        name: name.trim(),
        platform_role,
        org_id: orgId,
      },
      { onConflict: 'id', ignoreDuplicates: false },
    )

  if (upsertError) {
    return new Response(
      JSON.stringify({ error: `Error al crear perfil de usuario: ${upsertError.message}` }),
      { status: 500, headers },
    )
  }

  return new Response(
    JSON.stringify({ success: true, userId: inviteData.user.id }),
    { status: 200, headers },
  )
})
