'use client';

import {VStack} from '@astryxdesign/core/Layout';
import {Button} from '@astryxdesign/core/Button';
import {PanelCard} from '@/shared/components/patterns/PanelCard';
import {ActivityFeed} from '@/shared/components/patterns/ActivityItem';
import {SkeletonRows} from '@/shared/components/patterns/LoadingState';
import {EmptyPanel} from '@/shared/components/patterns/EmptyPanel';
import type {ActivityEntry, ActivityTone} from '@/shared/components/patterns/ActivityItem';
import type {ActivityEvent, ActivityKind} from '@/features/dashboard/types/dashboard';
import type {IconKey} from '@/shared/utils/icons';
import type {Resource} from '@/shared/hooks/useResource';

/**
 * Each event kind gets its own glyph, so the feed can be skimmed by category
 * without reading a word of it.
 *
 * Only one kind carries semantic colour. An expiry is the single event here a
 * merchant may need to act on; redemptions, purchases, check-ins and openings
 * are the shop working normally, and colouring them would make the one thing
 * that matters harder to find.
 */
const KIND: Record<
  ActivityKind,
  {icon: IconKey; tone: ActivityTone; toneLabel: string}
> = {
  purchase: {icon: 'purchases', tone: 'neutral', toneLabel: 'Purchase'},
  reward_redeemed: {icon: 'lyts', tone: 'neutral', toneLabel: 'Reward'},
  staff_checked_in: {icon: 'staff', tone: 'neutral', toneLabel: 'Staff'},
  store_opened: {icon: 'stores', tone: 'neutral', toneLabel: 'Store'},
  reward_expired: {icon: 'alert', tone: 'warning', toneLabel: 'Alert'},
};

function toEntries(events: ActivityEvent[]): ActivityEntry[] {
  return events.map((e) => ({
    id: e.id,
    title: e.title,
    detail: e.detail,
    at: e.at,
    ...KIND[e.kind],
  }));
}

/**
 * The feed panel, in two sizes.
 *
 * Bounded by default: `limit` caps the rows and `height` caps the box, because
 * an uncapped feed is the one panel on a dashboard that grows without limit as
 * the business gets busier. It reached 784px — taller than any chart on the
 * page — which is how an operational log ends up outweighing the insights it
 * was meant to support.
 *
 * Pass `viewAllHref` and the header offers the full history instead. Pass
 * neither and it renders everything, which is what the Activity page wants.
 */
export function ActivityTimeline({
  resource,
  title = 'Recent activity',
  subtitle = 'Live feed across the selected store and period',
  limit,
  height,
  viewAllHref,
}: {
  resource: Resource<ActivityEvent[]>;
  title?: string;
  subtitle?: string;
  /** Rows to show. Omit for the complete history. */
  limit?: number;
  /** Fixed content height in px. The list scrolls inside it rather than pushing
   *  the card taller, so the panel's footprint is the same on every load. */
  height?: number;
  viewAllHref?: string;
}) {
  return (
    <PanelCard
      title={title}
      subtitle={subtitle}
      resource={resource}
      loading={<SkeletonRows count={limit ?? 6} />}
      actions={
        viewAllHref ? (
          <Button
            variant="ghost"
            size="sm"
            label="View all"
            href={viewAllHref}
          />
        ) : undefined
      }
      empty={
        <EmptyPanel
          icon="alert"
          title="No activity yet"
          description="Events appear here as customers redeem rewards and staff check in."
        />
      }
    >
      {(events) =>
        height ? (
          <VStack height={height} isScrollable>
            <ActivityFeed entries={toEntries(events)} limit={limit} />
          </VStack>
        ) : (
          <ActivityFeed entries={toEntries(events)} limit={limit} />
        )
      }
    </PanelCard>
  );
}
