import { createClientFromRequest } from 'npm:@base44/sdk@0.8.40';

const HOME_BY_ROLE = {
  owner_admin: '/admin',
  admin: '/admin',
  builder: '/builder',
  customer: '/portal',
  reviewer: '/admin',
};

Deno.serve(async (req) => {
  try {
    const base44 = createClientFromRequest(req);

    // The accepting user MUST be authenticated. Anonymous calls are rejected.
    const user = await base44.auth.me();
    if (!user) return Response.json({ error: 'You must be signed in to accept an invitation.' }, { status: 401 });

    let body;
    try { body = await req.json(); } catch (_) { body = {}; }
    const token = typeof body?.token === 'string' ? body.token.trim() : '';
    if (!token || token.length < 16) {
      return Response.json({ error: 'Invalid invitation link.' }, { status: 400 });
    }

    // Resolve the invitation server-side from the opaque token only.
    // The client never supplies the role — it is read from the verified record.
    const invitations = await base44.asServiceRole.entities.Invitation.filter({ token });
    const inv = (invitations || [])[0];
    if (!inv) return Response.json({ error: 'Invalid invitation link.' }, { status: 404 });
    if (inv.status !== 'pending') return Response.json({ error: `This invitation is ${inv.status}.` }, { status: 409 });
    if (inv.expiry_date && new Date(inv.expiry_date) < new Date()) {
      await base44.asServiceRole.entities.Invitation.update(inv.id, { status: 'expired' });
      return Response.json({ error: 'This invitation has expired.' }, { status: 410 });
    }

    const actor = user.full_name || user.email || 'Invitation Acceptance';

    // Link or create the WorkshopAccount using ONLY fields sourced from the
    // server-verified invitation. The user cannot influence the assigned role.
    const existing = await base44.asServiceRole.entities.WorkshopAccount.filter({ user_id: user.id });
    const acc = (existing || [])[0];
    const role = inv.intended_role;
    const preset = inv.permission_preset || inv.intended_role;

    if (acc) {
      await base44.asServiceRole.entities.WorkshopAccount.update(acc.id, {
        role,
        permission_preset: preset,
        custom_permissions: inv.custom_permissions || undefined,
        customer_uuid: inv.linked_customer_uuid || acc.customer_uuid || undefined,
        customer_number: inv.linked_customer_number || acc.customer_number || undefined,
        builder_profile_uuid: inv.linked_builder_profile_uuid || acc.builder_profile_uuid || undefined,
        invitation_uuid: inv.uuid,
        account_status: 'Active',
        email_verified: true,
        last_login: new Date().toISOString(),
        updated_by_name: actor,
      });
    } else {
      await base44.asServiceRole.entities.WorkshopAccount.create({
        uuid: 'account-' + crypto.randomUUID(),
        user_id: user.id,
        email: inv.email || user.email,
        display_name: user.full_name || inv.email || user.email,
        role,
        permission_preset: preset,
        custom_permissions: inv.custom_permissions,
        account_status: 'Active',
        email_verified: true,
        customer_uuid: inv.linked_customer_uuid,
        customer_number: inv.linked_customer_number,
        builder_profile_uuid: inv.linked_builder_profile_uuid,
        invitation_uuid: inv.uuid,
        last_login: new Date().toISOString(),
        created_by_name: actor,
        updated_by_name: actor,
      });
    }

    // Mark the invitation accepted atomically after the account is provisioned.
    await base44.asServiceRole.entities.Invitation.update(inv.id, {
      status: 'accepted',
      accepted_date: new Date().toISOString(),
      accepted_by_user_id: user.id,
      updated_by_name: actor,
    });

    await base44.asServiceRole.entities.AuditEvent.create({
      uuid: 'audit-' + crypto.randomUUID(),
      event_type: 'invitation_accepted',
      record_type: 'Invitation',
      record_uuid: inv.uuid,
      actor_name: actor,
      summary: `Accepted invitation as ${role}`,
      details: `User ${user.id} linked to ${role} account.`,
    });

    return Response.json({ ok: true, role, redirect: HOME_BY_ROLE[role] || '/portal' });
  } catch (error) {
    return Response.json({ error: error?.message || 'Unable to accept invitation.' }, { status: 500 });
  }
});