import { useState } from 'react';
import { Link } from 'react-router-dom';
import { Lock, ShieldCheck, Server, ExternalLink, Settings, Copy, MessagesSquare, Users, QrCode } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { QRCodeCanvas } from '@/components/ui/qrcode';
import { useAuthor } from '@/hooks/useAuthor';
import { useTranslation } from '@/contexts/language';
import { useToast } from '@/hooks/useToast';
import { genUserName } from '@/lib/genUserName';
import { sanitizeUrl, urlDomain } from '@/lib/sanitizeUrl';
import { resolveCordnEndpoint } from '@/lib/cordn/endpoint';
import { CORDN_RELAY_URL, coordinatorAddUrl, CORDN_HOME, SKATESPOTS_COORDINATOR } from '@/lib/coordinator';
import { cn } from '@/lib/utils';
import type { CrewCoordinator, SkateCrew } from '@/lib/types';
import { nip19 } from 'nostr-tools';
/**
* The crew's encrypted-chat card (sidebar).
*
* A crew has **two** chats and the card must not conflate them:
* - the **Chat** tab — built-in NIP-17 group chat, always on, no setup; and
* - the **Private chat** tab — real MLS (forward secrecy, member removal),
* created once by an admin and routed through a coordinator.
*
* It leads with an honest status for each and a one-tap entry into the private
* chat; the coordinator details and any external clients (Staircase / Cordn web)
* are secondary. ⚠️ The status must match the tab: an earlier version badged
* "Private chat · On" while the MLS tab said "not created yet".
*/
export function CrewCoordinatorCard({
crew,
isFounder,
canManage,
nativeGroupExists,
}: {
crew: SkateCrew;
isFounder: boolean;
/** Founder/admin — may create the MLS group. */
canManage: boolean;
/** Whether this device already holds the crew's MLS group (local check). */
nativeGroupExists: boolean | undefined;
}) {
const { t } = useTranslation();
const { coordinator } = crew;
// Which relay the messages actually travel over — a `wss://` coordinator URL
// IS the relay; an `https://` one is addressed by pubkey over the shared
// ContextVM relay (public). The copy below must not overclaim either way.
const endpoint = resolveCordnEndpoint(crew);
const overPublicRelay = endpoint?.relayUrl === CORDN_RELAY_URL;
const privateChatTab = `/crew/${crew.pubkey}/${crew.identifier}?tab=mls`;
const mlsLabel =
nativeGroupExists === true
? t('socialUi.crewCoordinator.on')
: nativeGroupExists === undefined
? t('socialUi.crewCoordinator.checking')
: canManage
? t('socialUi.crewCoordinator.setUpChat')
: t('socialUi.crewCoordinator.joinChat');
const mlsCta =
nativeGroupExists === true
? t('socialUi.crewCoordinator.openChat')
: canManage
? t('socialUi.crewCoordinator.setUpChat')
: t('socialUi.crewCoordinator.joinChat');
return (
{t('socialUi.crewCoordinator.chatWord')}
{t('socialUi.crewCoordinator.chatRowDesc')}
{t('socialUi.crewCoordinator.privateChatName')}
{mlsLabel}
{t('socialUi.crewCoordinator.privateChatDesc')}
{t('socialUi.crewCoordinator.deliveredOver')}{' '}
{urlDomain(endpoint.relayUrl) || endpoint.relayUrl}
{overPublicRelay ? ` ${t('socialUi.crewCoordinator.sharedRelay')}` : ` ${t('socialUi.crewCoordinator.ownRelay')}`}
{t('socialUi.crewCoordinator.chatRowDesc')}{' '}
{overPublicRelay
? t('socialUi.crewCoordinator.publicWarning')
: t('socialUi.crewCoordinator.ownRelaySafe')}
{t('socialUi.crewCoordinator.openInAnotherApp')}
{t('socialUi.crewCoordinator.advancedA')}{' '}
{t('socialUi.crewCoordinator.cordnCoordinator')}
?{' '}
{t('socialUi.coordinator.scanToJoin')}
{t('socialUi.crewCoordinator.runBy')}
{name}