"use client";

/**
 * Landing-page header account slot.
 *
 * Signed out: the marketing calls to action ("Connexion" / "Créer un agent").
 * Signed in: the visitor's avatar, name and role, linking to whichever
 * dashboard belongs to them.
 *
 * Destination is decided by role, not by a fixed path:
 *   platform admin -> /admin   (the operator console)
 *   everyone else  -> /home    (which forwards to /conversations or /onboarding)
 *
 * Platform-admin status comes from `amIPlatformAdmin`, the same server-side
 * check that guards the console itself, so this cannot be spoofed into showing
 * an operator badge.
 *
 * That query is wrapped in an error boundary on purpose. Convex's `useQuery`
 * THROWS when a query fails rather than returning undefined, so a deployment
 * that cannot verify the Clerk token (a missing issuer in `auth.config.ts`, for
 * example) would otherwise take the entire marketing page down for anyone
 * logged in. The fallback degrades to the ordinary member view.
 */

import { Component, type ReactNode } from "react";
import Link from "next/link";
import { useOrganization, useUser } from "@clerk/nextjs";
import { useQuery } from "convex/react";
import { ArrowRightIcon } from "lucide-react";
import { api } from "@workspace/backend/_generated/api";

type Labels = {
  signIn: string;
  createAgent: string;
  dashboard: string;
  superadmin: string;
  admin: string;
  member: string;
  openDashboard: string;
};

type Styles = Record<string, string>;

/** Renders `fallback` instead of crashing when a child query throws. */
class QueryBoundary extends Component<
  { fallback: ReactNode; children: ReactNode },
  { failed: boolean }
> {
  state = { failed: false };
  static getDerivedStateFromError() {
    return { failed: true };
  }
  render() {
    return this.state.failed ? this.props.fallback : this.props.children;
  }
}

function AccountChip({
  labels,
  styles,
  name,
  imageUrl,
  role,
  href,
}: {
  labels: Labels;
  styles: Styles;
  name: string;
  imageUrl?: string;
  role: string;
  href: string;
}) {
  return (
    <Link href={href} className={styles.account} title={labels.openDashboard}>
      {imageUrl ? (
        // Clerk serves the avatar; next/image would need its host allowlisted.
        // eslint-disable-next-line @next/next/no-img-element
        <img src={imageUrl} alt="" className={styles.accountAvatar} />
      ) : (
        <span className={styles.accountAvatarFallback} aria-hidden>
          {name.charAt(0).toUpperCase()}
        </span>
      )}
      <span className={styles.accountText}>
        <span className={styles.accountName}>{name}</span>
        <span className={styles.accountRole}>{role}</span>
      </span>
      <ArrowRightIcon size={15} className={styles.dirIcon} />
    </Link>
  );
}

/** Runs the privileged check. Isolated so only this can trip the boundary. */
function AdminAwareChip({
  labels,
  styles,
  name,
  imageUrl,
  orgRole,
}: {
  labels: Labels;
  styles: Styles;
  name: string;
  imageUrl?: string;
  orgRole?: string;
}) {
  const isPlatformAdmin = useQuery((api as any).admin.dashboard.amIPlatformAdmin, {}) as
    | boolean
    | undefined;

  const role = isPlatformAdmin
    ? labels.superadmin
    : orgRole === "org:admin"
      ? labels.admin
      : labels.member;

  return (
    <AccountChip
      labels={labels}
      styles={styles}
      name={name}
      imageUrl={imageUrl}
      role={role}
      href={isPlatformAdmin ? "/admin" : "/home"}
    />
  );
}

export function HeaderAccount({ labels, styles }: { labels: Labels; styles: Styles }) {
  const { isLoaded, isSignedIn, user } = useUser();
  const { membership } = useOrganization();

  // Hold the slot until Clerk resolves, so the signed-out buttons never flash
  // for someone who is actually logged in.
  if (!isLoaded) {
    return <span className={styles.accountPlaceholder} aria-hidden />;
  }

  if (!isSignedIn) {
    return (
      <>
        <Link href="/sign-in" className={styles.signIn}>
          {labels.signIn}
        </Link>
        <Link href="/sign-up" className={styles.headerCta}>
          {labels.createAgent} <ArrowRightIcon size={16} className={styles.dirIcon} />
        </Link>
      </>
    );
  }

  const name =
    user.fullName ||
    user.firstName ||
    user.primaryEmailAddress?.emailAddress ||
    labels.dashboard;
  const imageUrl = user.imageUrl || undefined;

  return (
    <QueryBoundary
      fallback={
        <AccountChip
          labels={labels}
          styles={styles}
          name={name}
          imageUrl={imageUrl}
          role={labels.member}
          href="/home"
        />
      }
    >
      <AdminAwareChip
        labels={labels}
        styles={styles}
        name={name}
        imageUrl={imageUrl}
        orgRole={membership?.role}
      />
    </QueryBoundary>
  );
}
