// BalanceAccountsTable — one-row-per-active-account table on /balance.
//
// Issue #141 (Bilan #3) introduced the table with name/category/latest-value/Δ%
// + actions menu. Issue #142 (Bilan #4) adds 4 return columns, computed via
// the Modified Dietz `compute_account_return` Tauri command:
//
//   - 3M (last 90 days)
//   - 1A (last 365 days)
//   - Depuis création (from earliest snapshot date to today)
//   - Non-ajusté (simple `(V_end - V_start) / V_start`, no contribution
//     weighting — shown side-by-side as a sanity check / explanation)
//
// Returns load lazily on mount via `Promise.all` over (account × horizon),
// keyed by `account_id`. Each cell renders "—" while loading and shows the
// `is_partial` / `has_no_transfers_warning` badges via tooltip when set.
//
// Issue #142 also adds a "Lier transferts" item in the per-row actions menu
// that opens `LinkTransfersModal` (the modal handles its own state; this
// component just bubbles up the request via `onLinkTransfers`).

import { Fragment, useEffect, useMemo, useState } from "react";
import type { ReactNode } from "react";
import { useTranslation } from "react-i18next";
import {
  Archive,
  MoreVertical,
  Link as LinkIcon,
  AlertTriangle,
  ChevronDown,
  ChevronRight,
  ListTree,
} from "lucide-react";
import type {
  AccountLatestSnapshot,
  AccountPeriodAnchor,
  AccountUnrealizedGain,
  LatentGainRollup,
} from "../../services/balance.service";
import { computeAccountReturn } from "../../services/balance.service";
import {
  getPreference,
  setPreference,
} from "../../services/userPreferenceService";
import type { AccountReturn } from "../../shared/types";
import { renderCategoryLabelFromAccount } from "../../utils/renderCategoryLabel";

/**
 * Preference key persisting whether the 4 Modified-Dietz return columns are
 * expanded. Absent/anything-but-"1" → collapsed (the spec default). Stored via
 * `userPreferenceService` so the choice survives across sessions (Issue #204).
 */
const SHOW_RETURNS_PREF_KEY = "balance_show_returns";

const cadFormatter = (locale: string) =>
  new Intl.NumberFormat(locale, {
    style: "currency",
    currency: "CAD",
    maximumFractionDigits: 2,
  });

/** Horizon definition: how many days back from today to start the period. */
type HorizonKey = "3M" | "1A" | "since";

interface HorizonRange {
  key: HorizonKey;
  /** ISO date for `period_start`. */
  from: string;
  /** ISO date for `period_end` (always today, computed in the local civil day). */
  to: string;
}

function localISO(d: Date): string {
  const yy = d.getFullYear();
  const mm = String(d.getMonth() + 1).padStart(2, "0");
  const dd = String(d.getDate()).padStart(2, "0");
  return `${yy}-${mm}-${dd}`;
}

function isoDaysAgo(days: number, today: Date): string {
  const d = new Date(today);
  d.setDate(d.getDate() - days);
  return localISO(d);
}

interface BalanceAccountsTableProps {
  accounts: AccountLatestSnapshot[];
  periodAnchor: AccountPeriodAnchor[];
  onArchiveAccount?: (account: AccountLatestSnapshot) => void;
  onLinkTransfers?: (account: AccountLatestSnapshot) => void;
  /**
   * Open the "détailler en titres" wizard for a *simple* account (Issue #215).
   * The action is only offered on `kind === 'simple'` rows; once detailed, the
   * flip is one-way (service backstop #212) so no inverse action is exposed.
   */
  onDetailAccount?: (account: AccountLatestSnapshot) => void;
  /**
   * Earliest snapshot date across the whole profile, used to anchor the
   * "depuis création" horizon. Falls back to "1A" range if not provided
   * (avoids triggering computation against the unix epoch).
   */
  sinceCreationDate?: string | null;
  /**
   * Per-account unrealized (latent) gain keyed by `account_id`, prefetched by
   * `useBalanceOverview` from each detailed account's latest holdings (Issue
   * #216). Drives the latent-gain column + the per-security drill-down. Only
   * detailed accounts with holdings appear; absent ⇒ no figure / no drill-down.
   */
  latentGainByAccount?: Record<number, AccountUnrealizedGain>;
  /** Latent gain rolled up by asset class / envelope, for the summary block (#216). */
  latentGainRollup?: LatentGainRollup;
  /** vehicle_type code (incl. 'none') → translated label, for the envelope rollup (#216). */
  vehicleLabels?: Record<string, string>;
}

/**
 * Per-account, per-horizon return — shape used by the local cache state.
 * Indexed `[accountId][horizonKey]`.
 */
type ReturnsByAccount = Record<number, Partial<Record<HorizonKey, AccountReturn>>>;

export default function BalanceAccountsTable({
  accounts,
  periodAnchor,
  onArchiveAccount,
  onLinkTransfers,
  onDetailAccount,
  sinceCreationDate,
  latentGainByAccount = {},
  latentGainRollup,
  vehicleLabels = {},
}: BalanceAccountsTableProps) {
  const { t, i18n } = useTranslation();
  const fmt = cadFormatter(i18n.language === "fr" ? "fr-CA" : "en-CA");

  /** account_id → period anchor (start-of-period value). */
  const anchorMap = useMemo(() => {
    const m = new Map<number, AccountPeriodAnchor>();
    for (const a of periodAnchor) m.set(a.account_id, a);
    return m;
  }, [periodAnchor]);

  const [openMenuFor, setOpenMenuFor] = useState<number | null>(null);

  // Per-security drill-down (Issue #216): which detailed account rows are
  // expanded. A Set keyed by account_id; toggled by the row's chevron. The
  // holdings themselves are already prefetched in `latentGainByAccount`, so
  // expanding is a pure render — no extra DB round-trip.
  const [expandedFor, setExpandedFor] = useState<Set<number>>(new Set());
  const toggleExpanded = (accountId: number) => {
    setExpandedFor((prev) => {
      const next = new Set(prev);
      if (next.has(accountId)) next.delete(accountId);
      else next.add(accountId);
      return next;
    });
  };

  // Progressive disclosure of the 4 return columns (Issue #204). Collapsed by
  // default; the persisted choice is read once on mount. We start `false` so
  // the columns never flash open before the preference resolves.
  const [showReturns, setShowReturns] = useState(false);
  useEffect(() => {
    let cancelled = false;
    void (async () => {
      try {
        const stored = await getPreference(SHOW_RETURNS_PREF_KEY);
        if (!cancelled && stored === "1") setShowReturns(true);
      } catch {
        // Pref read failure: keep the collapsed default.
      }
    })();
    return () => {
      cancelled = true;
    };
  }, []);

  const toggleReturns = () => {
    setShowReturns((prev) => {
      const next = !prev;
      // Best-effort persist; a write failure just means the next session
      // falls back to the collapsed default.
      void setPreference(SHOW_RETURNS_PREF_KEY, next ? "1" : "0").catch(
        () => {}
      );
      return next;
    });
  };

  // Returns cache. Cleared whenever the account list changes (new accounts,
  // archive, etc.). Loaded lazily after mount — only while the columns are
  // shown, so a collapsed table never runs the Modified-Dietz computation.
  const [returns, setReturns] = useState<ReturnsByAccount>({});
  const [returnsLoading, setReturnsLoading] = useState(false);

  // Horizon definitions — recomputed once per mount via today's local civil
  // day. We don't memoize against `accounts` because the dates don't depend
  // on the row list.
  const horizons = useMemo<HorizonRange[]>(() => {
    const today = new Date();
    const todayISO = localISO(today);
    const sinceFrom = sinceCreationDate ?? isoDaysAgo(365, today);
    return [
      { key: "3M", from: isoDaysAgo(90, today), to: todayISO },
      { key: "1A", from: isoDaysAgo(365, today), to: todayISO },
      { key: "since", from: sinceFrom, to: todayISO },
    ];
  }, [sinceCreationDate]);

  useEffect(() => {
    let cancelled = false;
    async function loadReturns() {
      if (!showReturns || accounts.length === 0) {
        setReturns({});
        return;
      }
      setReturnsLoading(true);
      const next: ReturnsByAccount = {};
      // Run sequentially per account to avoid SQLite contention; per-horizon
      // we can parallelize because they hit the same table set.
      await Promise.all(
        accounts.map(async (acc) => {
          next[acc.account_id] = {};
          const tasks = horizons.map(async (h) => {
            try {
              const r = await computeAccountReturn(
                acc.account_id,
                h.from,
                h.to
              );
              next[acc.account_id]![h.key] = r;
            } catch {
              // Per-cell failure: leave the slot undefined → renders "—".
            }
          });
          await Promise.all(tasks);
        })
      );
      if (!cancelled) {
        setReturns(next);
        setReturnsLoading(false);
      }
    }
    void loadReturns();
    return () => {
      cancelled = true;
    };
  }, [accounts, horizons, showReturns]);

  if (accounts.length === 0) {
    return (
      <div className="bg-[var(--card)] border border-[var(--border)] rounded-xl p-8 text-center text-[var(--muted-foreground)] italic">
        {t("balance.overview.noAccounts")}
      </div>
    );
  }

  /** Format a return percentage with sign + colour-aware classname. */
  function renderReturnCell(r: AccountReturn | undefined) {
    if (!r) {
      return <span className="text-[var(--muted-foreground)]">—</span>;
    }
    if (r.return_pct === null) {
      return (
        <span
          className="text-[var(--muted-foreground)] inline-flex items-center gap-1"
          title={t("balance.returns.partialTooltip")}
        >
          <AlertTriangle size={12} />
          —
        </span>
      );
    }
    const pct = r.return_pct * 100;
    return (
      <span className="inline-flex items-center gap-1">
        <span
          className={
            pct >= 0 ? "text-[var(--positive)]" : "text-[var(--negative)]"
          }
        >
          {pct >= 0 ? "+" : ""}
          {pct.toFixed(2)}%
        </span>
        {r.has_no_transfers_warning && (
          <AlertTriangle
            size={12}
            className="text-amber-500"
            aria-label={t("balance.returns.noTransfersWarning")}
          />
        )}
      </span>
    );
  }

  /**
   * Unadjusted (simple) return = `(value_end - value_start) / value_start`
   * — same numbers Modified Dietz already returns when no flows exist, but
   * this column shows the simple version for ALL accounts as a side-by-side
   * sanity check. Computed from the same `AccountReturn` payload (uses the
   * `value_start` / `value_end` fields filled by the Rust side).
   */
  function renderUnadjustedCell(r: AccountReturn | undefined) {
    if (!r || r.value_start === null || r.value_end === null) {
      return <span className="text-[var(--muted-foreground)]">—</span>;
    }
    if (r.value_start === 0) {
      return <span className="text-[var(--muted-foreground)]">—</span>;
    }
    const simple = ((r.value_end - r.value_start) / r.value_start) * 100;
    return (
      <span
        className={
          simple >= 0 ? "text-[var(--positive)]" : "text-[var(--negative)]"
        }
      >
        {simple >= 0 ? "+" : ""}
        {simple.toFixed(2)}%
      </span>
    );
  }

  /**
   * Latent (unrealized) gain cell — value + % (Issue #216). `gain`/`gainPct`
   * null ⇒ the shared service guard already decided "N/A" (book_cost NULL or 0);
   * render the i18n N/A string, never a divide-by-zero. `partial` flags an
   * aggregate where some holdings had an unknown book_cost (% understated).
   */
  function renderLatentGainCell(
    gain: number | null,
    gainPct: number | null,
    partial = false
  ) {
    if (gain === null) {
      return (
        <span className="text-[var(--muted-foreground)]">
          {t("balance.latentGain.na")}
        </span>
      );
    }
    const positive = gain >= 0;
    return (
      <span
        className={`inline-flex items-center justify-end gap-1 ${
          positive ? "text-[var(--positive)]" : "text-[var(--negative)]"
        }`}
      >
        <span>
          {positive ? "+" : ""}
          {fmt.format(gain)}
        </span>
        {gainPct !== null && (
          <span className="text-xs text-[var(--muted-foreground)]">
            ({positive ? "+" : ""}
            {(gainPct * 100).toFixed(2)}%)
          </span>
        )}
        {partial && (
          <AlertTriangle
            size={12}
            className="text-amber-500"
            aria-label={t("balance.latentGain.partial")}
          />
        )}
      </span>
    );
  }

  // The latent-gain column only earns its place when at least one detailed
  // account has a computed gain — otherwise we keep the table narrow.
  const hasLatentGain = accounts.some(
    (a) => latentGainByAccount[a.account_id] !== undefined
  );

  return (
    <div className="space-y-2">
      <div className="flex justify-end">
        <button
          type="button"
          onClick={toggleReturns}
          aria-expanded={showReturns}
          className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium rounded-lg border border-[var(--border)] bg-[var(--card)] text-[var(--foreground)] hover:bg-[var(--muted)]/40"
        >
          {showReturns ? (
            <ChevronDown size={14} />
          ) : (
            <ChevronRight size={14} />
          )}
          {t(
            showReturns
              ? "balance.accountsTable.toggleReturns.hide"
              : "balance.accountsTable.toggleReturns.show"
          )}
        </button>
      </div>
      <div className="bg-[var(--card)] border border-[var(--border)] rounded-xl overflow-x-auto">
        <table className="w-full text-sm">
          <thead className="bg-[var(--muted)]/30">
          <tr>
            <th className="text-left px-4 py-3 font-medium">
              {t("balance.account.fields.name")}
            </th>
            <th className="text-left px-4 py-3 font-medium">
              {t("balance.account.fields.category")}
            </th>
            <th className="text-right px-4 py-3 font-medium">
              {t("balance.overview.latestValue")}
            </th>
            <th className="text-right px-4 py-3 font-medium">
              {t("balance.overview.periodDelta")}
            </th>
            {hasLatentGain && (
              <th
                className="text-right px-4 py-3 font-medium"
                title={t("balance.latentGain.tooltip")}
              >
                {t("balance.latentGain.column")}
              </th>
            )}
            {showReturns && (
              <>
                <th className="text-right px-4 py-3 font-medium" title={t("balance.accountsTable.return3mTooltip")}>
                  {t("balance.accountsTable.return3m")}
                </th>
                <th className="text-right px-4 py-3 font-medium" title={t("balance.accountsTable.return1yTooltip")}>
                  {t("balance.accountsTable.return1y")}
                </th>
                <th className="text-right px-4 py-3 font-medium" title={t("balance.accountsTable.sinceCreationTooltip")}>
                  {t("balance.accountsTable.sinceCreation")}
                </th>
                <th className="text-right px-4 py-3 font-medium" title={t("balance.accountsTable.unadjustedTooltip")}>
                  {t("balance.accountsTable.unadjusted")}
                </th>
              </>
            )}
            <th className="text-right px-4 py-3 font-medium w-12">
              {t("balance.account.fields.actions")}
            </th>
          </tr>
        </thead>
        <tbody>
          {accounts.map((acc) => {
            const anchor = anchorMap.get(acc.account_id);
            const deltaPct =
              acc.latest_value !== null && anchor && anchor.anchor_value !== 0
                ? ((acc.latest_value - anchor.anchor_value) /
                    Math.abs(anchor.anchor_value)) *
                  100
                : null;
            const accReturns = returns[acc.account_id] ?? {};
            const lg = latentGainByAccount[acc.account_id];
            // A detailed account is drillable once its latest holdings are
            // loaded. Simple accounts (no holdings) never expand.
            const drillable = !!lg && lg.holdings.length > 0;
            const isExpanded = drillable && expandedFor.has(acc.account_id);
            // Number of columns a drill-down sub-row must span.
            const colSpan =
              5 + (hasLatentGain ? 1 : 0) + (showReturns ? 4 : 0);
            return (
              <Fragment key={acc.account_id}>
              <tr
                className="border-t border-[var(--border)] hover:bg-[var(--muted)]/10"
              >
                <td className="px-4 py-3 font-medium">
                  <span className="inline-flex items-center gap-1.5">
                    {drillable ? (
                      <button
                        type="button"
                        onClick={() => toggleExpanded(acc.account_id)}
                        aria-expanded={isExpanded}
                        aria-label={t(
                          isExpanded
                            ? "balance.latentGain.drilldown.collapse"
                            : "balance.latentGain.drilldown.expand"
                        )}
                        className="p-0.5 -ml-1 rounded hover:bg-[var(--muted)]/40 text-[var(--muted-foreground)]"
                      >
                        {isExpanded ? (
                          <ChevronDown size={14} />
                        ) : (
                          <ChevronRight size={14} />
                        )}
                      </button>
                    ) : (
                      <span className="inline-block w-[14px]" aria-hidden />
                    )}
                    {acc.account_name}
                  </span>
                  {acc.symbol ? (
                    <span className="ml-2 text-xs text-[var(--muted-foreground)]">
                      ({acc.symbol})
                    </span>
                  ) : null}
                </td>
                <td className="px-4 py-3 text-[var(--muted-foreground)]">
                  {renderCategoryLabelFromAccount(acc, t)}
                </td>
                <td className="px-4 py-3 text-right tabular-nums">
                  {acc.latest_value !== null ? fmt.format(acc.latest_value) : "—"}
                </td>
                <td className="px-4 py-3 text-right tabular-nums">
                  {deltaPct !== null ? (
                    <span
                      className={
                        deltaPct >= 0
                          ? "text-[var(--positive)]"
                          : "text-[var(--negative)]"
                      }
                    >
                      {deltaPct >= 0 ? "+" : ""}
                      {deltaPct.toFixed(2)}%
                    </span>
                  ) : (
                    "—"
                  )}
                </td>
                {hasLatentGain && (
                  <td className="px-4 py-3 text-right tabular-nums">
                    {lg
                      ? renderLatentGainCell(
                          lg.total_gain,
                          lg.total_gain_pct,
                          lg.has_unknown_book_cost
                        )
                      : "—"}
                  </td>
                )}
                {showReturns && (
                  <>
                    <td className="px-4 py-3 text-right tabular-nums">
                      {returnsLoading && !accReturns["3M"]
                        ? "…"
                        : renderReturnCell(accReturns["3M"])}
                    </td>
                    <td className="px-4 py-3 text-right tabular-nums">
                      {returnsLoading && !accReturns["1A"]
                        ? "…"
                        : renderReturnCell(accReturns["1A"])}
                    </td>
                    <td className="px-4 py-3 text-right tabular-nums">
                      {returnsLoading && !accReturns["since"]
                        ? "…"
                        : renderReturnCell(accReturns["since"])}
                    </td>
                    <td className="px-4 py-3 text-right tabular-nums">
                      {returnsLoading && !accReturns["1A"]
                        ? "…"
                        : renderUnadjustedCell(accReturns["1A"])}
                    </td>
                  </>
                )}
                <td className="px-4 py-3 text-right relative">
                  <button
                    type="button"
                    onClick={() =>
                      setOpenMenuFor(
                        openMenuFor === acc.account_id ? null : acc.account_id
                      )
                    }
                    className="p-1 rounded hover:bg-[var(--muted)]/40"
                    aria-label={t("balance.account.fields.actions")}
                  >
                    <MoreVertical size={16} />
                  </button>
                  {openMenuFor === acc.account_id && (
                    <div className="absolute right-2 top-full z-10 mt-1 bg-[var(--card)] border border-[var(--border)] rounded-lg shadow-md py-1 min-w-[180px] text-left">
                      {onDetailAccount && acc.kind === "simple" && (
                        <button
                          type="button"
                          onClick={() => {
                            setOpenMenuFor(null);
                            onDetailAccount(acc);
                          }}
                          className="flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-[var(--muted)]/40"
                        >
                          <ListTree size={14} />
                          {t("balance.detailWizard.action")}
                        </button>
                      )}
                      {onLinkTransfers && (
                        <button
                          type="button"
                          onClick={() => {
                            setOpenMenuFor(null);
                            onLinkTransfers(acc);
                          }}
                          className="flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-[var(--muted)]/40"
                        >
                          <LinkIcon size={14} />
                          {t("balance.transfers.linkAction")}
                        </button>
                      )}
                      <button
                        type="button"
                        onClick={() => {
                          setOpenMenuFor(null);
                          onArchiveAccount?.(acc);
                        }}
                        className="flex items-center gap-2 w-full px-3 py-2 text-sm hover:bg-[var(--muted)]/40"
                      >
                        <Archive size={14} />
                        {t("balance.account.actions.archive")}
                      </button>
                    </div>
                  )}
                </td>
              </tr>
              {isExpanded && (
                <tr className="bg-[var(--muted)]/5">
                  <td colSpan={colSpan} className="px-0 py-0">
                    <div className="px-4 py-2">
                      <table className="w-full text-xs">
                        <thead>
                          <tr className="text-[var(--muted-foreground)]">
                            <th className="text-left font-medium py-1 pl-6">
                              {t("balance.latentGain.drilldown.security")}
                            </th>
                            <th className="text-right font-medium py-1">
                              {t("balance.latentGain.drilldown.value")}
                            </th>
                            <th className="text-right font-medium py-1 pr-2">
                              {t("balance.latentGain.drilldown.gain")}
                            </th>
                          </tr>
                        </thead>
                        <tbody>
                          {lg!.holdings.map((h) => (
                            <tr key={h.security_id}>
                              <td className="text-left py-1 pl-6 font-medium">
                                {h.symbol}
                              </td>
                              <td className="text-right py-1 tabular-nums">
                                {fmt.format(h.value)}
                              </td>
                              <td className="text-right py-1 pr-2 tabular-nums">
                                {renderLatentGainCell(h.gain, h.gain_pct)}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  </td>
                </tr>
              )}
              </Fragment>
            );
          })}
        </tbody>
        </table>
      </div>
      {latentGainRollup &&
        (latentGainRollup.byClass.length > 0 ||
          latentGainRollup.byVehicle.length > 0) && (
          <LatentGainSummary
            rollup={latentGainRollup}
            accounts={accounts}
            vehicleLabels={vehicleLabels}
            fmt={fmt}
            renderGain={renderLatentGainCell}
          />
        )}
    </div>
  );
}

// -----------------------------------------------------------------------------
// LatentGainSummary — aggregated latent gain by asset class / envelope (#216).
// Reuses the accounts surface (no new chart): a compact two-column block of
// rollup figures. Asset-class labels resolve from the accounts payload (same
// renderCategoryLabel path the table uses); envelope labels come from the
// shared `vehicleLabels` map BalancePage already builds.
// -----------------------------------------------------------------------------

interface LatentGainSummaryProps {
  rollup: LatentGainRollup;
  accounts: AccountLatestSnapshot[];
  vehicleLabels: Record<string, string>;
  fmt: Intl.NumberFormat;
  renderGain: (
    gain: number | null,
    gainPct: number | null,
    partial?: boolean
  ) => ReactNode;
}

function LatentGainSummary({
  rollup,
  accounts,
  vehicleLabels,
  renderGain,
}: LatentGainSummaryProps) {
  const { t } = useTranslation();

  // category_key → translated asset-class label, from the accounts payload.
  const classLabels = useMemo(() => {
    const m: Record<string, string> = {};
    for (const a of accounts) {
      if (!m[a.category_key]) {
        m[a.category_key] = renderCategoryLabelFromAccount(a, t);
      }
    }
    return m;
  }, [accounts, t]);

  const section = (
    title: string,
    buckets: LatentGainRollup["byClass"],
    labelFor: (key: string) => string
  ) => (
    <div className="flex-1 min-w-[220px]">
      <p className="text-xs font-semibold text-[var(--muted-foreground)] uppercase tracking-wide mb-1">
        {title}
      </p>
      <table className="w-full text-sm">
        <tbody>
          {buckets.map((b) => (
            <tr key={b.group_key} className="border-t border-[var(--border)]/60">
              <td className="py-1.5 text-[var(--muted-foreground)]">
                {labelFor(b.group_key)}
              </td>
              <td className="py-1.5 text-right tabular-nums">
                {renderGain(b.total_gain, b.total_gain_pct, b.has_unknown_book_cost)}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );

  return (
    <div className="mt-3 bg-[var(--card)] border border-[var(--border)] rounded-xl p-4">
      <h3 className="text-sm font-semibold mb-3">
        {t("balance.latentGain.summary.title")}
      </h3>
      <div className="flex flex-col sm:flex-row gap-6">
        {section(
          t("balance.latentGain.summary.byClass"),
          rollup.byClass,
          (key) => classLabels[key] ?? key
        )}
        {section(
          t("balance.latentGain.summary.byVehicle"),
          rollup.byVehicle,
          (key) => vehicleLabels[key] ?? key
        )}
      </div>
    </div>
  );
}
