import React, { useMemo } from 'react';
import { Avatar, Box, Icon, IconButton, Icons, IconSrc, Scroll, Text, color, config } from 'folds';
import { EventType } from 'matrix-js-sdk';
import { Page, PageContent, PageHeader } from '../../components/page';
import { SequenceCard } from '../../components/sequence-card';
import { useRoom } from '../../hooks/useRoom';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { getMemberAvatarMxc, getMemberName } from '../../utils/room';
import { mxcUrlToHttp } from '../../utils/matrix';
import { UserAvatar } from '../../components/user-avatar';

// ── Helpers ───────────────────────────────────────────────────────────────────

function formatDate(ts: number): string {
  return new Date(ts).toLocaleDateString(undefined, {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  });
}

// ── Section header ────────────────────────────────────────────────────────────

function SectionHeader({ label }: { label: string }) {
  return (
    <Text size="L400" priority="300">
      {label}
    </Text>
  );
}

// ── Stat tile ─────────────────────────────────────────────────────────────────

function StatTile({ icon, count, label }: { icon: IconSrc; count: number; label: string }) {
  return (
    <Box
      direction="Column"
      alignItems="Center"
      gap="100"
      style={{
        flex: 1,
        minWidth: 64,
        padding: `${config.space.S300} ${config.space.S200}`,
        borderRadius: config.radii.R300,
        border: `1px solid ${color.Surface.ContainerLine}`,
        background: color.Surface.Container,
      }}
    >
      <Icon src={icon} size="300" />
      <Text size="H4" style={{ fontWeight: 700 }}>
        {count}
      </Text>
      <Text size="T200" priority="300" align="Center">
        {label}
      </Text>
    </Box>
  );
}

// ── Main component ────────────────────────────────────────────────────────────

type RoomInsightsProps = {
  requestClose: () => void;
};

export function RoomInsights({ requestClose }: RoomInsightsProps) {
  const mx = useMatrixClient();
  const room = useRoom();
  const useAuthentication = useMediaAuthentication();

  const stats = useMemo(() => {
    const events = room.getLiveTimeline().getEvents();

    // ── A. Message count by member ──────────────────────────────────────────
    const msgCounts = new Map<string, number>();
    for (const ev of events) {
      if (ev.getType() === EventType.RoomMessage && !ev.isDecryptionFailure()) {
        const sender = ev.getSender();
        if (sender) msgCounts.set(sender, (msgCounts.get(sender) ?? 0) + 1);
      }
    }
    const top5 = [...msgCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5);

    // ── B. Top 5 reactions ──────────────────────────────────────────────────
    const reactionCounts = new Map<string, number>();
    for (const ev of events) {
      if (ev.getType() === EventType.Reaction) {
        const key = ev.getContent()['m.relates_to']?.key as string | undefined;
        if (key) reactionCounts.set(key, (reactionCounts.get(key) ?? 0) + 1);
      }
    }
    const top5Reactions = [...reactionCounts.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5);

    // ── C. Media breakdown ──────────────────────────────────────────────────
    const mediaCounts = { image: 0, video: 0, audio: 0, file: 0 };
    for (const ev of events) {
      if (ev.getType() !== EventType.RoomMessage) continue;
      const msgtype = ev.getContent().msgtype as string | undefined;
      if (msgtype === 'm.image') mediaCounts.image++;
      else if (msgtype === 'm.video') mediaCounts.video++;
      else if (msgtype === 'm.audio') mediaCounts.audio++;
      else if (msgtype === 'm.file') mediaCounts.file++;
    }

    // ── D. Activity heatmap — messages per hour ─────────────────────────────
    const hourBuckets = new Array<number>(24).fill(0);
    for (const ev of events) {
      if (ev.getType() === EventType.RoomMessage) {
        hourBuckets[new Date(ev.getTs()).getHours()]++;
      }
    }

    // ── E. Summary stats ────────────────────────────────────────────────────
    const totalMessages = [...msgCounts.values()].reduce((a, b) => a + b, 0);
    const uniqueParticipants = msgCounts.size;

    // Single-pass min/max — `Math.min(...allTs)` spreads one arg per message and
    // overflows the call stack (RangeError) on a large paginated timeline.
    let oldestTs: number | null = null;
    let newestTs: number | null = null;
    for (const ev of events) {
      if (ev.getType() !== EventType.RoomMessage) continue;
      const ts = ev.getTs();
      if (oldestTs === null || ts < oldestTs) oldestTs = ts;
      if (newestTs === null || ts > newestTs) newestTs = ts;
    }

    return {
      top5,
      top5Reactions,
      mediaCounts,
      hourBuckets,
      totalMessages,
      uniqueParticipants,
      oldestTs,
      newestTs,
      totalCached: events.length,
    };
  }, [room]);

  const maxHour = Math.max(...stats.hourBuckets, 1);
  const maxMsgCount = stats.top5.length > 0 ? (stats.top5[0]?.[1] ?? 1) : 1;

  return (
    <Page>
      <PageHeader outlined={false}>
        <Box grow="Yes" gap="200">
          <Box grow="Yes" alignItems="Center" gap="200">
            <Icon src={Icons.Info} size="200" />
            <Text as="h2" size="H3" truncate>
              Insights
            </Text>
          </Box>
          <Box shrink="No">
            <IconButton onClick={requestClose} variant="Surface" aria-label="Close">
              <Icon src={Icons.Cross} />
            </IconButton>
          </Box>
        </Box>
      </PageHeader>

      <Box grow="Yes">
        <Scroll hideTrack visibility="Hover">
          <PageContent>
            <Box direction="Column" gap="500">
              {/* ── Disclaimer banner ── */}
              <SequenceCard variant="SurfaceVariant" gap="200" alignItems="Center">
                <Icon src={Icons.Warning} size="200" style={{ color: color.Warning.Main }} />
                <Box direction="Column" gap="100">
                  <Text size="T300">
                    <strong>
                      Based on {stats.totalMessages} locally cached message
                      {stats.totalMessages !== 1 ? 's' : ''}
                    </strong>
                  </Text>
                  {stats.oldestTs !== null && stats.newestTs !== null && (
                    <Text size="T200" priority="300">
                      from {formatDate(stats.oldestTs)} to {formatDate(stats.newestTs)}
                    </Text>
                  )}
                </Box>
              </SequenceCard>

              {/* ── Summary row ── */}
              <Box direction="Column" gap="200">
                <SectionHeader label="Summary" />
                <Box gap="200" wrap="Wrap">
                  <Box
                    direction="Column"
                    alignItems="Center"
                    gap="100"
                    style={{
                      flex: 1,
                      minWidth: 80,
                      padding: `${config.space.S300} ${config.space.S200}`,
                      borderRadius: config.radii.R300,
                      border: `1px solid ${color.Surface.ContainerLine}`,
                      background: color.Surface.Container,
                    }}
                  >
                    <Text
                      size="H5"
                      style={{
                        fontWeight: 700,
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        whiteSpace: 'nowrap',
                        maxWidth: '100%',
                      }}
                    >
                      {stats.totalMessages.toLocaleString()}
                    </Text>
                    <Text size="T200" priority="300" align="Center">
                      Messages
                    </Text>
                  </Box>
                  <Box
                    direction="Column"
                    alignItems="Center"
                    gap="100"
                    style={{
                      flex: 1,
                      minWidth: 80,
                      padding: `${config.space.S300} ${config.space.S200}`,
                      borderRadius: config.radii.R300,
                      border: `1px solid ${color.Surface.ContainerLine}`,
                      background: color.Surface.Container,
                    }}
                  >
                    <Text
                      size="H5"
                      style={{
                        fontWeight: 700,
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        whiteSpace: 'nowrap',
                        maxWidth: '100%',
                      }}
                    >
                      {stats.uniqueParticipants.toLocaleString()}
                    </Text>
                    <Text size="T200" priority="300" align="Center">
                      Participants
                    </Text>
                  </Box>
                  <Box
                    direction="Column"
                    alignItems="Center"
                    gap="100"
                    style={{
                      flex: 1,
                      minWidth: 80,
                      padding: `${config.space.S300} ${config.space.S200}`,
                      borderRadius: config.radii.R300,
                      border: `1px solid ${color.Surface.ContainerLine}`,
                      background: color.Surface.Container,
                    }}
                  >
                    <Text
                      size="H5"
                      style={{
                        fontWeight: 700,
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                        whiteSpace: 'nowrap',
                        maxWidth: '100%',
                      }}
                    >
                      {stats.totalCached.toLocaleString()}
                    </Text>
                    <Text size="T200" priority="300" align="Center">
                      Cached events
                    </Text>
                  </Box>
                </Box>
              </Box>

              {/* ── Media shared ── */}
              <Box direction="Column" gap="200">
                <SectionHeader label="Media Shared" />
                <Box gap="200" wrap="Wrap">
                  <StatTile icon={Icons.Photo} count={stats.mediaCounts.image} label="Images" />
                  <StatTile
                    icon={Icons.VideoCamera}
                    count={stats.mediaCounts.video}
                    label="Videos"
                  />
                  <StatTile icon={Icons.Headphone} count={stats.mediaCounts.audio} label="Audio" />
                  <StatTile icon={Icons.File} count={stats.mediaCounts.file} label="Files" />
                </Box>
              </Box>

              {/* ── Most active members ── */}
              {stats.top5.length > 0 && (
                <Box direction="Column" gap="200">
                  <SectionHeader label="Most Active Members" />
                  <Box direction="Column" gap="200">
                    {stats.top5.map(([userId, count], index) => {
                      const displayName = getMemberName(room, userId);
                      const avatarMxc = getMemberAvatarMxc(room, userId);
                      const avatarUrl = avatarMxc
                        ? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, 32, 32, 'crop') ??
                          undefined)
                        : undefined;
                      const barWidth = `${Math.max(4, (count / maxMsgCount) * 100)}%`;

                      return (
                        <Box key={userId} alignItems="Center" gap="200">
                          {/* Rank */}
                          <Text
                            size="T300"
                            priority="300"
                            style={{ width: 16, flexShrink: 0, textAlign: 'center' }}
                          >
                            {index + 1}
                          </Text>

                          {/* Avatar */}
                          <Box shrink="No">
                            <Avatar size="200" radii="300">
                              <UserAvatar
                                userId={userId}
                                src={avatarUrl}
                                alt={displayName}
                                renderFallback={() => <Icon size="50" src={Icons.User} filled />}
                              />
                            </Avatar>
                          </Box>

                          {/* Name + bar */}
                          <Box
                            grow="Yes"
                            direction="Column"
                            gap="100"
                            style={{ overflow: 'hidden' }}
                          >
                            <Text size="T300" truncate style={{ lineHeight: 1 }}>
                              {displayName}
                            </Text>
                            <Box alignItems="Center" gap="200">
                              <div
                                style={{
                                  height: 6,
                                  width: barWidth,
                                  background: color.Primary.Main,
                                  borderRadius: config.radii.R300,
                                  transition: 'width 0.3s ease',
                                  flexShrink: 0,
                                }}
                              />
                              <Text size="T200" priority="300" style={{ flexShrink: 0 }}>
                                {count}
                              </Text>
                            </Box>
                          </Box>
                        </Box>
                      );
                    })}
                  </Box>
                </Box>
              )}

              {/* ── Top reactions ── */}
              {stats.top5Reactions.length > 0 && (
                <Box direction="Column" gap="200">
                  <SectionHeader label="Top Reactions" />
                  <Box gap="200" wrap="Wrap">
                    {stats.top5Reactions.map(([emoji, count]) => (
                      <Box
                        key={emoji}
                        alignItems="Center"
                        gap="100"
                        style={{
                          padding: `${config.space.S100} ${config.space.S200}`,
                          borderRadius: config.radii.R300,
                          border: `1px solid ${color.Surface.ContainerLine}`,
                          background: color.Surface.Container,
                          flexShrink: 0,
                        }}
                      >
                        <Text size="H5">{emoji}</Text>
                        <Text size="T300" priority="300">
                          {count}
                        </Text>
                      </Box>
                    ))}
                  </Box>
                </Box>
              )}

              {/* ── Activity by hour ── */}
              <Box direction="Column" gap="200">
                <SectionHeader label="Activity by Hour" />
                <Box
                  direction="Column"
                  gap="100"
                  style={{
                    padding: config.space.S300,
                    borderRadius: config.radii.R300,
                    border: `1px solid ${color.Surface.ContainerLine}`,
                    background: color.Surface.Container,
                  }}
                >
                  {/* Bars */}
                  <Box
                    alignItems="End"
                    style={{
                      height: 60,
                      gap: 2,
                    }}
                  >
                    {stats.hourBuckets.map((count, h) => (
                      <Box
                        key={h}
                        direction="Column"
                        alignItems="Center"
                        style={{ flex: 1, height: '100%', justifyContent: 'flex-end' }}
                      >
                        <div
                          title={`${h}:00 — ${count} message${count !== 1 ? 's' : ''}`}
                          style={{
                            width: '100%',
                            height: `${Math.max(2, (count / maxHour) * 48)}px`,
                            background:
                              count > 0 && count === maxHour
                                ? color.Primary.Main
                                : color.SurfaceVariant.Container,
                            borderRadius: `${config.radii.R300} ${config.radii.R300} 0 0`,
                            transition: 'height 0.2s ease',
                          }}
                        />
                      </Box>
                    ))}
                  </Box>

                  {/* Hour labels: show 0, 6, 12, 18 */}
                  <Box style={{ gap: 0 }}>
                    {stats.hourBuckets.map((_, h) => (
                      <Box key={h} justifyContent="Center" style={{ flex: 1 }}>
                        {h % 6 === 0 ? (
                          <Text size="T200" priority="300" align="Center">
                            {h}
                          </Text>
                        ) : null}
                      </Box>
                    ))}
                  </Box>
                </Box>
                <Text size="T200" priority="300">
                  Hour of day (local time, 0 = midnight)
                </Text>
              </Box>

              {/* Bottom padding */}
              <Box style={{ height: config.space.S200 }} />
            </Box>
          </PageContent>
        </Scroll>
      </Box>
    </Page>
  );
}
