import { useState, useEffect, useCallback, useRef } from 'react';
import {
  Container,
  Title,
  Text,
  Table,
  Badge,
  Group,
  Alert,
  Loader,
  Center,
  Stack,
  TextInput,
  Modal,
  Code,
  Button,
  ActionIcon,
  Tooltip,
} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import {
  IconAlertCircle,
  IconDatabase,
  IconSearch,
  IconPlayerPlay,
  IconTrash,
  IconRefresh,
  IconTrashX,
} from '@tabler/icons-react';
import { apiClient } from '../lib/api';
import type { MessageCacheEvent, MessageCacheStats } from '../types';
import type { AxiosError } from 'axios';

const ITEMS_PER_PAGE = 50;

function getApiErrorMessage(err: unknown, fallback: string): string {
  const axiosErr = err as AxiosError<unknown>;
  const responseData = axiosErr?.response?.data;

  if (typeof responseData === 'string' && responseData.trim() !== '') {
    return responseData.trim();
  }

  if (responseData && typeof responseData === 'object') {
    const maybeMessage = (responseData as { message?: unknown }).message;
    const maybeError = (responseData as { error?: unknown }).error;
    if (typeof maybeMessage === 'string' && maybeMessage.trim() !== '') {
      return maybeMessage.trim();
    }
    if (typeof maybeError === 'string' && maybeError.trim() !== '') {
      return maybeError.trim();
    }
  }

  if (err instanceof Error && err.message.trim() !== '') {
    return err.message;
  }

  return fallback;
}

export default function MessageCachePage() {
  const [cachedEvents, setCachedEvents] = useState<MessageCacheEvent[]>([]);
  const [stats, setStats] = useState<MessageCacheStats | null>(null);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [actionLoading, setActionLoading] = useState(false);
  const [hasMore, setHasMore] = useState(false);
  const [offset, setOffset] = useState(0);
  const [totalFilteredCount, setTotalFilteredCount] = useState<number | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [eventTypeQuery, setEventTypeQuery] = useState('');
  const [debouncedEventTypeQuery, setDebouncedEventTypeQuery] = useState('');
  const [modalTitle, setModalTitle] = useState('Cached Event Data');
  const [modalContent, setModalContent] = useState('');
  const [dataModalOpened, { open: openDataModal, close: closeDataModal }] = useDisclosure(false);
  const sentinelRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedEventTypeQuery(eventTypeQuery.trim()), 350);
    return () => clearTimeout(timer);
  }, [eventTypeQuery]);

  const loadStats = useCallback(async () => {
    try {
      const cacheStats = await apiClient.getMessageCacheStats();
      setStats(cacheStats);
    } catch (err) {
      console.error(err);
    }
  }, []);

  const loadCachePage = useCallback(async (targetOffset: number, reset: boolean) => {
    try {
      if (reset) {
        setLoading(true);
      } else {
        setLoadingMore(true);
      }

      const result = await apiClient.getMessageCacheEvents({
        limit: ITEMS_PER_PAGE,
        offset: targetOffset,
        eventType: debouncedEventTypeQuery || undefined,
      });

      const pageData = result.cached_events || [];
      const nextOffset = targetOffset + pageData.length;

      if (reset) {
        setCachedEvents(pageData);
      } else {
        setCachedEvents((previousEvents) => [...previousEvents, ...pageData]);
      }

      setOffset(nextOffset);
      setTotalFilteredCount(result.filtered_count);
      setHasMore(nextOffset < result.filtered_count);
      setError(null);
    } catch (err) {
      setError(getApiErrorMessage(err, 'Failed to load cached events'));
      console.error(err);
    } finally {
      if (reset) {
        setLoading(false);
      } else {
        setLoadingMore(false);
      }
    }
  }, [debouncedEventTypeQuery]);

  useEffect(() => {
    setCachedEvents([]);
    setOffset(0);
    setHasMore(false);
    setTotalFilteredCount(null);
    loadCachePage(0, true);
    loadStats();
  }, [debouncedEventTypeQuery, loadCachePage, loadStats]);

  useEffect(() => {
    if (!sentinelRef.current || loading || loadingMore || !hasMore || error) {
      return;
    }

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0]?.isIntersecting) {
          loadCachePage(offset, false);
        }
      },
      { rootMargin: '250px' },
    );

    observer.observe(sentinelRef.current);
    return () => observer.disconnect();
  }, [loading, loadingMore, hasMore, error, offset, loadCachePage]);

  const refreshPage = async () => {
    await Promise.all([loadCachePage(0, true), loadStats()]);
  };

  const openDetailsModal = (event: MessageCacheEvent) => {
    setModalTitle(`Cached Event: ${event.event.type}`);
    setModalContent(JSON.stringify(event, null, 2));
    openDataModal();
  };

  const handleReplayEvent = async (id: string) => {
    try {
      setActionLoading(true);
      await apiClient.replayCachedEvent(id);
      notifications.show({ title: 'Success', message: 'Cached event replayed', color: 'green' });
      await refreshPage();
    } catch (err) {
      notifications.show({ title: 'Error', message: 'Failed to replay cached event', color: 'red' });
      console.error(err);
    } finally {
      setActionLoading(false);
    }
  };

  const handleDeleteEvent = async (id: string) => {
    if (!confirm('Delete this cached event?')) {
      return;
    }

    try {
      setActionLoading(true);
      await apiClient.deleteCachedEvent(id);
      notifications.show({ title: 'Success', message: 'Cached event deleted', color: 'green' });
      await refreshPage();
    } catch (err) {
      notifications.show({ title: 'Error', message: 'Failed to delete cached event', color: 'red' });
      console.error(err);
    } finally {
      setActionLoading(false);
    }
  };

  const handleReplayAll = async () => {
    if (!confirm('Replay all cached events now?')) {
      return;
    }

    try {
      setActionLoading(true);
      const result = await apiClient.replayAllCachedEvents();
      notifications.show({
        title: 'Replay complete',
        message: `Replayed ${result.replayed} events (${result.delivered} delivered, ${result.failed} failed)`,
        color: 'green',
      });
      await refreshPage();
    } catch (err) {
      notifications.show({ title: 'Error', message: 'Failed to replay cached events', color: 'red' });
      console.error(err);
    } finally {
      setActionLoading(false);
    }
  };

  const handleClearAll = async () => {
    if (!confirm('Clear all cached events? This cannot be undone.')) {
      return;
    }

    try {
      setActionLoading(true);
      const result = await apiClient.clearMessageCache();
      notifications.show({ title: 'Success', message: `Cleared ${result.cleared} cached events`, color: 'green' });
      await refreshPage();
    } catch (err) {
      notifications.show({ title: 'Error', message: 'Failed to clear message cache', color: 'red' });
      console.error(err);
    } finally {
      setActionLoading(false);
    }
  };

  if (loading) {
    return (
      <Container size="xl" py="xl">
        <Center h={400}>
          <Loader size="lg" />
        </Center>
      </Container>
    );
  }

  if (error) {
    return (
      <Container size="xl" py="xl">
        <Alert icon={<IconAlertCircle size={16} />} title="Error" color="red" mb="md">
          {error}
        </Alert>
        <Button onClick={refreshPage}>Retry</Button>
      </Container>
    );
  }

  return (
    <Container size="xl" py="xl">
      <Group justify="space-between" mb="xl" align="flex-start">
        <div>
          <Title order={2}>Message Cache</Title>
          <Text c="dimmed" size="sm">Browse and manage cached webhook events with paged loading</Text>
          <Text c="dimmed" size="sm" mt={4}>
            Cache status: {stats?.enabled ? 'enabled' : 'disabled'}
            {typeof stats?.total_count === 'number' ? ` • Total: ${stats.total_count}` : ''}
          </Text>
        </div>
        <Group>
          <Button
            variant="default"
            leftSection={<IconRefresh size={16} />}
            onClick={refreshPage}
            loading={actionLoading}
          >
            Refresh
          </Button>
          <Button
            color="blue"
            leftSection={<IconPlayerPlay size={16} />}
            onClick={handleReplayAll}
            loading={actionLoading}
            disabled={cachedEvents.length === 0}
          >
            Replay All
          </Button>
          <Button
            color="red"
            variant="light"
            leftSection={<IconTrashX size={16} />}
            onClick={handleClearAll}
            loading={actionLoading}
            disabled={cachedEvents.length === 0}
          >
            Clear Cache
          </Button>
        </Group>
      </Group>

      <Group mb="md">
        <TextInput
          placeholder="Filter by event type (e.g. message.received)"
          leftSection={<IconSearch size={16} />}
          value={eventTypeQuery}
          onChange={(e) => setEventTypeQuery(e.target.value)}
          style={{ flex: 1 }}
        />
      </Group>

      <Table highlightOnHover withTableBorder withColumnBorders>
        <Table.Thead>
          <Table.Tr>
            <Table.Th>Cached At</Table.Th>
            <Table.Th>Event Type</Table.Th>
            <Table.Th>Reason</Table.Th>
            <Table.Th>Attempts</Table.Th>
            <Table.Th>Last Attempt</Table.Th>
            <Table.Th>Details</Table.Th>
            <Table.Th>Actions</Table.Th>
          </Table.Tr>
        </Table.Thead>
        <Table.Tbody>
          {cachedEvents.length === 0 ? (
            <Table.Tr>
              <Table.Td colSpan={7}>
                <Center h={200}>
                  <Stack align="center">
                    <IconDatabase size={48} stroke={1.5} color="gray" />
                    <Text c="dimmed">
                      {debouncedEventTypeQuery ? 'No cached events match this filter' : 'No cached events'}
                    </Text>
                  </Stack>
                </Center>
              </Table.Td>
            </Table.Tr>
          ) : (
            cachedEvents.map((cachedEvent) => (
              <Table.Tr key={cachedEvent.id}>
                <Table.Td>
                  <Text size="sm">{new Date(cachedEvent.timestamp).toLocaleString()}</Text>
                </Table.Td>
                <Table.Td>
                  <Badge variant="light">{cachedEvent.event.type}</Badge>
                </Table.Td>
                <Table.Td>
                  <Text size="sm">{cachedEvent.reason || '-'}</Text>
                </Table.Td>
                <Table.Td>
                  <Badge color={cachedEvent.attempts > 0 ? 'yellow' : 'gray'} variant="light">
                    {cachedEvent.attempts}
                  </Badge>
                </Table.Td>
                <Table.Td>
                  <Text size="sm">
                    {cachedEvent.last_attempt
                      ? new Date(cachedEvent.last_attempt).toLocaleString()
                      : '-'}
                  </Text>
                </Table.Td>
                <Table.Td>
                  <Code
                    component="button"
                    onClick={() => openDetailsModal(cachedEvent)}
                    style={{ cursor: 'pointer', border: 'none' }}
                  >
                    View
                  </Code>
                </Table.Td>
                <Table.Td>
                  <Group gap="xs" wrap="nowrap">
                    <Tooltip label="Replay event">
                      <ActionIcon
                        variant="light"
                        color="blue"
                        onClick={() => handleReplayEvent(cachedEvent.id)}
                        loading={actionLoading}
                      >
                        <IconPlayerPlay size={16} />
                      </ActionIcon>
                    </Tooltip>
                    <Tooltip label="Delete event">
                      <ActionIcon
                        variant="light"
                        color="red"
                        onClick={() => handleDeleteEvent(cachedEvent.id)}
                        loading={actionLoading}
                      >
                        <IconTrash size={16} />
                      </ActionIcon>
                    </Tooltip>
                  </Group>
                </Table.Td>
              </Table.Tr>
            ))
          )}
        </Table.Tbody>
      </Table>

      <div ref={sentinelRef} />

      {loadingMore && (
        <Center mt="lg">
          <Loader size="sm" />
        </Center>
      )}

      <Group justify="space-between" mt="md">
        <Text size="sm" c="dimmed">
          {totalFilteredCount !== null
            ? `Showing ${cachedEvents.length} of ${totalFilteredCount} cached events`
            : `Showing ${cachedEvents.length} cached events`}
        </Text>
        {debouncedEventTypeQuery && (
          <Text size="sm" c="dimmed">Filtered by: "{debouncedEventTypeQuery}"</Text>
        )}
      </Group>

      <Modal
        opened={dataModalOpened}
        onClose={closeDataModal}
        title={modalTitle}
        fullScreen
      >
        <Code
          component="pre"
          block
          style={{
            whiteSpace: 'pre-wrap',
            wordBreak: 'break-word',
            minHeight: '90vh',
            overflow: 'auto',
          }}
        >
          {modalContent}
        </Code>
      </Modal>
    </Container>
  );
}
