import React, { useEffect, useState } from "react";
import { Stack, Title, Text, Timeline, Badge, Group, Loader, ScrollArea, Paper, ActionIcon, Tooltip, Box, Code, Divider, Flex, Button, Modal, TextInput, Pagination } from "@mantine/core";
import { IconHistory, IconRefresh, IconBell, IconTarget, IconCalendarEvent, IconSettings, IconSearch } from "@tabler/icons-react";
import { getAdminActivityLogs } from "@/lib/features/activity-logs/query";
import { getAudienceMembers } from "@/lib/features/notifications/action";
import { useRoleAccess } from "@/hooks/useRoleAccess";
import moment from "moment";

export interface AdminActivityLog {
  id: string;
  admin_email: string;
  action: string;
  method: string;
  url: string;
  status_code: number;
  payload?: any;
  before_payload?: any;
  log_category: string;
  performed_at: string;
}

interface ContextualLogsProps {
  adminEmail?: string;
  logCategory?: string;
  entityId?: string;
  title?: string;
  limit?: number;
}

const LogDataSummary: React.FC<{ payload: any; beforePayload?: any }> = ({ payload, beforePayload }) => {
  const [modalData, setModalData] = useState<{ title: string, items: any[] } | null>(null);
  const [searchQuery, setSearchQuery] = useState("");
  const [modalPage, setModalPage] = useState(1);
  const [fetchingEmails, setFetchingEmails] = useState(false);
  const pageSize = 50;

  const filteredModalItems = modalData?.items.filter(item => {
    if (!searchQuery) return true;
    const strItem = typeof item === 'object' ? JSON.stringify(item) : String(item);
    return strItem.toLowerCase().includes(searchQuery.toLowerCase());
  }) || [];

  const paginatedItems = filteredModalItems.slice((modalPage - 1) * pageSize, modalPage * pageSize);
  const totalPages = Math.ceil(filteredModalItems.length / pageSize);

  if (!payload && !beforePayload) return null;
  const data = typeof payload === "string" ? JSON.parse(payload) : (payload || {});
  const oldData = typeof beforePayload === "string" ? JSON.parse(beforePayload) : (beforePayload || null);

  const isChanged = (key: string) => {
    if (!oldData) return false;
    return JSON.stringify(data[key]) !== JSON.stringify(oldData[key]);
  };

  const Section = ({ icon: Icon, title, children }: { icon: any, title: string, children: React.ReactNode }) => (
    <Box mb="md">
      <Group gap="xs" mb={8}>
        <Icon size={18} stroke={1.5} color="var(--mantine-color-blue-6)" />
        <Text size="sm" fw={700} tt="uppercase" c="dimmed">{title}</Text>
      </Group>
      <Box pl={26}>
        {children}
      </Box>
      <Divider mt="xs" variant="dashed" />
    </Box>
  );

  const RenderField = ({ label, value, fieldName }: { label: string, value: any, fieldName?: string }) => {
    if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) return null;
    const changed = fieldName ? isChanged(fieldName) : false;
    console.log(value, "label");
    return (
      <Group gap="xs" wrap="nowrap" align="flex-start" mb={4}>
        <Text size="sm" fw={600} style={{ minWidth: '120px' }}>{label}:</Text>
        <Box style={{
          backgroundColor: changed ? 'var(--mantine-color-orange-0)' : 'transparent',
          borderLeft: changed ? '2px solid var(--mantine-color-orange-5)' : 'none',
          paddingLeft: changed ? '4px' : '0',
          borderRadius: '2px',
          flex: 1
        }}
          size="sm">
          {targetValue(value, label)}
        </Box>
      </Group>
    );
  };

  const targetValue = (value: any, label: string) => {
    const isMembersField = label.toLowerCase().includes('member') || label.toLowerCase().includes('email');
    let items: any[] = [];

    if (Array.isArray(value)) {
      items = value;
    } else if (typeof value === 'string' && (isMembersField || (value.includes('@') && !['title', 'message', 'body', 'name', 'custom data'].includes(label.toLowerCase())))) {
      items = value.split(/[\s,]+/).filter(Boolean);
    }

    if (isMembersField && items.length > 0) {
      return (
        <Badge
          size="md"
          variant="filled"
          color="blue"
          style={{ cursor: 'pointer', textTransform: 'none' }}
          onClick={() => { setModalData({ title: label, items }); setModalPage(1); }}
        >
          View {items.length} {label}
        </Badge>
      );
    }

    if (items.length > 3) {
      return (
        <Group gap={4}>
          <Flex gap={4} wrap="wrap">
            {items.slice(0, 3).map((v, i) => (
              <Badge key={i} size="sm" variant="light" radius="sm" style={{ textTransform: 'none' }}>
                {typeof v === 'object' ? JSON.stringify(v) : v}
              </Badge>
            ))}
          </Flex>
          <Badge
            size="sm"
            variant="filled"
            color="blue"
            style={{ cursor: 'pointer', textTransform: 'none' }}
            onClick={() => { setModalData({ title: label, items }); setModalPage(1); }}
          >
            + {items.length - 3} more
          </Badge>
        </Group>
      );
    }

    if (Array.isArray(value)) return <Flex gap={4} wrap="wrap">{value.map((v, i) => <Badge key={i} size="sm" variant="light" radius="sm" style={{ textTransform: 'none' }}>{typeof v === 'object' ? JSON.stringify(v) : v}</Badge>)}</Flex>;
    if (typeof value === 'object') return <Code fz="xs">{JSON.stringify(value)}</Code>;
    return <Text size="sm">{String(value)}</Text>;
  };

  let targetCriteria = data.target_criteria;
  if (typeof targetCriteria === 'string') try { targetCriteria = JSON.parse(targetCriteria); } catch (e) { }
  targetCriteria = targetCriteria || {};

  let additionalData = data.additional_data;
  if (typeof additionalData === 'string') try { additionalData = JSON.parse(additionalData); } catch (e) { }
  additionalData = additionalData || {};

  const scheduleDetails = additionalData.schedule_details || {};

  const country = targetCriteria.country || data.country;
  const city = targetCriteria.city || data.city;
  const membershipType = targetCriteria.membershipType || data.membershipType;

  const notificationType = scheduleDetails.notificationType || data.notificationType;
  const scheduleDate = data.scheduled_at || data.scheduleDate || scheduleDetails.scheduleDate;
  const timeZone = scheduleDetails.timeZone || data.timeZone;

  const persist = additionalData.persist !== undefined ? additionalData.persist : data.persist;
  const customData = additionalData.customData || data.customData;

  const hasContent = !!(data.title || data.text || data.body || data.name);
  const hasTargeting = !!(country || city || membershipType || Object.keys(targetCriteria).length > 0);
  const hasScheduling = !!(notificationType || scheduleDate || timeZone);
  const hasOptions = persist !== undefined || !!customData || Object.keys(additionalData).length > 0;
  
  const isSystemMetric = data.chunkSize !== undefined || data.sentCount !== undefined;
  const isSystemError = !!data.error;

  const handleFetchResolvedEmails = async () => {
    setFetchingEmails(true);
    try {
      const criteria = {
        country,
        city,
        membershipType,
        ...targetCriteria
      };
      const res = await getAudienceMembers(criteria, 1000, 0); // Preview first 1000
      if (res.success && res.data) {
        setModalData({ title: "Resolved Emails", items: res.data.items.map(i => i.email) });
        setModalPage(1);
      }
    } catch (e) {
      console.error("Failed to fetch resolved emails", e);
    } finally {
      setFetchingEmails(false);
    }
  };

  return (
    <Paper withBorder p="md" bg="gray.0" radius="md">
      <Stack gap={0}>
        {hasContent && (
          <Section icon={IconBell} title="Step 1 - Notification">
            <RenderField label="Title" value={data.title} fieldName="title" />
            <RenderField label="Message" value={data.text || data.body} fieldName="body" />
            <RenderField label="Internal Name" value={data.name} fieldName="name" />
            <RenderField label="Image URL" value={data.image_url} fieldName="image_url" />
          </Section>
        )}

        {hasTargeting && (
          <Section icon={IconTarget} title="Step 2 - Target">
            <Box mb="xs">
              <Button
                variant="light"
                size="compact-xs"
                leftSection={<IconSearch size={12} />}
                onClick={handleFetchResolvedEmails}
                loading={fetchingEmails}
              >
                Preview All Targeted Emails
              </Button>
            </Box>
            <RenderField label="Country" value={country} fieldName="target_criteria" />
            <RenderField label="City" value={city} fieldName="target_criteria" />
            <RenderField label="Membership" value={membershipType} fieldName="target_criteria" />
            {Object.entries(targetCriteria).map(([k, v]) => {
              if (['country', 'city', 'membershipType'].includes(k)) return null;
              return <RenderField key={k} label={k.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())} value={v} fieldName="target_criteria" />;
            })}
          </Section>
        )}

        {hasScheduling && (
          <Section icon={IconCalendarEvent} title="Step 3 - Scheduling">
            <RenderField label="Type" value={notificationType} fieldName="additional_data" />
            <RenderField label="Schedule" value={scheduleDate ? moment(scheduleDate).format("LLL") : null} fieldName="scheduled_at" />
            <RenderField label="Timezone" value={timeZone} fieldName="additional_data" />
            {Object.entries(scheduleDetails).map(([k, v]) => {
              if (['notificationType', 'timeZone', 'scheduleDate'].includes(k)) return null;
              return <RenderField key={k} label={k.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())} value={v} fieldName="additional_data" />;
            })}
          </Section>
        )}

        {hasOptions && (
          <Section icon={IconSettings} title="Step 4 - Additional Options">
            <RenderField label="Persist Log" value={persist !== undefined ? (persist ? "Yes" : "No") : null} fieldName="additional_data" />
            <RenderField label="Custom Data" value={customData} fieldName="additional_data" />
            {Object.entries(additionalData).map(([k, v]) => {
              if (['persist', 'customData', 'schedule_details'].includes(k)) return null;
              return <RenderField key={k} label={k.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())} value={v} fieldName="additional_data" />;
            })}
          </Section>
        )}

        {isSystemMetric && (
          <Section icon={IconSettings} title="Execution Metrics">
            <RenderField label="Processed Chunk Size" value={data.chunkSize} />
            <RenderField label="Total Sent Count" value={data.sentCount} />
            <RenderField label="Target Audience Size" value={data.totalCount} />
            {data.deliveryStats && (
              <>
                <RenderField label="Processable Emails" value={data.deliveryStats.processableEmailAddresses?.list} />
                <RenderField label="Invalid Emails" value={data.deliveryStats.invalidEmailAddresses?.list} />
                <RenderField label="Non-Processable Emails" value={data.deliveryStats.nonProcessableEmailAddresses?.list} />
              </>
            )}
          </Section>
        )}

        {isSystemError && (
          <Section icon={IconBell} title="System Error">
            <RenderField label="Error Details" value={data.error} />
          </Section>
        )}

        {!hasContent && !hasTargeting && !hasScheduling && !isSystemMetric && !isSystemError && Object.keys(data).length > 0 && (
          <Code block fz="xs" style={{ whiteSpace: 'pre-wrap' }}>
            {JSON.stringify(data, null, 2)}
          </Code>
        )}

        {oldData && (
          <Group justify="flex-end" mt="xs">
            <Badge color="orange" variant="dot" size="sm">Highlighted fields indicate changes</Badge>
          </Group>
        )}

        {/* Modal for viewing large arrays / email lists */}
        <Modal
          opened={!!modalData}
          onClose={() => { setModalData(null); setSearchQuery(""); setModalPage(1); }}
          title={<Text fw={600} size="md">All {modalData?.title} Entries</Text>}
          size="lg"
          zIndex={1000}
          centered
        >
          <Box mb="md">
            <TextInput
              placeholder="Search entries..."
              value={searchQuery}
              onChange={(e) => { setSearchQuery(e.currentTarget.value); setModalPage(1); }}
              leftSection={<IconSearch size={14} />}
              size="sm"
            />
          </Box>
          <ScrollArea h={400} offsetScrollbars>
            <Stack gap="xs">
              {paginatedItems.map((item, idx) => (
                <Code key={idx} block fz="sm" style={{ whiteSpace: 'pre-wrap' }}>
                  {typeof item === 'object' ? JSON.stringify(item, null, 2) : item}
                </Code>
              ))}
              {filteredModalItems.length === 0 && (
                <Text size="sm" c="dimmed" ta="center" py="md">No entries matched your search.</Text>
              )}
            </Stack>
          </ScrollArea>
          {totalPages > 1 && (
            <Group justify="center" mt="md">
              <Pagination
                total={totalPages}
                value={modalPage}
                onChange={setModalPage}
                size="sm"
              />
            </Group>
          )}
        </Modal>
      </Stack>
    </Paper>
  );
};

export const ContextualLogs: React.FC<ContextualLogsProps> = ({
  adminEmail,
  logCategory,
  entityId,
  title = "Recent Activity",
  limit = 5,
}) => {
  const { checkClientAccess } = useRoleAccess();
  const canViewAdminLogs = checkClientAccess("read", "admin-logs");
  const [logs, setLogs] = useState<AdminActivityLog[]>([]);
  const [loading, setLoading] = useState(true);
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);

  const fetchLogs = async (pageNum = 1, append = false) => {
    // Never fetch logs without admin-logs access — avoids a 403 that would log
    // the user out.
    if (!canViewAdminLogs) return;
    setLoading(true);
    try {
      const res = await getAdminActivityLogs(
        {
          admin_email: adminEmail ? [adminEmail] : undefined,
          log_category: logCategory ? [logCategory] : undefined,
          entity_id: entityId,
          pageSize: limit,
          page: pageNum
        },
        new Request(window.location.href)
      );
      if (res.success && res.data) {
        // Filter out GET requests to keep the timeline focused on actions
        const mutationsOnly = res.data.items.filter(log => ["POST", "PUT", "PATCH", "DELETE", "BACKGROUND"].includes(log.method));

        if (append) {
          setLogs(prev => [...prev, ...mutationsOnly]);
        } else {
          setLogs(mutationsOnly);
        }
        setHasMore(res.data.items.length === limit);
      }
    } catch (e) {
      console.error("Failed to fetch contextual logs", e);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    setPage(1);
    fetchLogs(1, false);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [adminEmail, logCategory, entityId, canViewAdminLogs]);

  // Users without log access never see contextual logs (and never fetch them).
  if (!canViewAdminLogs) return null;

  const loadMore = () => {
    const nextPage = page + 1;
    setPage(nextPage);
    fetchLogs(nextPage, true);
  };

  return (
    <Paper p="md" withBorder radius="md" style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
      <Stack gap="md" style={{ flex: 1 }}>
        <Group justify="space-between">
          <Group gap="xs">
            <IconHistory size={20} color="var(--mantine-color-blue-6)" />
            <Title order={6}>{title}</Title>
          </Group>
          <Group gap="xs">
            <Tooltip label="Refresh">
              <ActionIcon variant="subtle" onClick={() => fetchLogs(1, false)} loading={loading}>
                <IconRefresh size={16} />
              </ActionIcon>
            </Tooltip>
            <Button size="md" variant="subtle" color="blue" onClick={() => window.open('/admin/logs', '_blank')}>
              View Global Logs
            </Button>
          </Group>
        </Group>

        {loading && logs.length === 0 ? (
          <Group justify="center" py="md">
            <Loader size="sm" />
          </Group>
        ) : logs.length === 0 ? (
          <Text size="xs" c="dimmed" ta="center" py="md">
            No recent activity found.
          </Text>
        ) : (
          <ScrollArea h={600} offsetScrollbars>
            <Timeline active={-1} bulletSize={22} lineWidth={2}>
              {logs.map((log) => (
                <Timeline.Item
                  key={log.id}
                  bullet={
                    <ActionIcon
                      size={22}
                      radius="xl"
                      variant="light"
                      color={log.payload ? "blue" : "gray"}
                      onClick={() => log.payload && setExpandedId(expandedId === log.id ? null : log.id)}
                    >
                      <IconHistory size={12} />
                    </ActionIcon>
                  }
                  title={
                    <Group justify="space-between">
                      <Group gap="xs">
                        <Text size="sm" fw={700}>
                          {log.action.replace("/v1/admin-console/", "")}
                        </Text>
                        <Badge size="sm" variant="light" color={log.status_code >= 400 ? "red" : "blue"}>
                          {log.method}
                        </Badge>
                      </Group>
                      {log.payload && (
                        <Text
                          size="md"
                          c="blue"
                          style={{ cursor: 'pointer', textDecoration: 'underline' }}
                          onClick={() => setExpandedId(expandedId === log.id ? null : log.id)}
                        >
                          {expandedId === log.id ? "Hide Details" : "Show Info"}
                        </Text>
                      )}
                    </Group>
                  }
                >
                  <Text size="sm" c="dimmed" mt={2}>
                    {moment(log.performed_at).fromNow()} • {log.admin_email}
                  </Text>

                  {expandedId === log.id && (
                    <Box mt="xs">
                      <LogDataSummary payload={log.payload} beforePayload={log.before_payload} />
                    </Box>
                  )}
                </Timeline.Item>
              ))}
            </Timeline>
            {hasMore && (
              <Button
                variant="subtle"
                fullWidth
                size="xs"
                mt="md"
                onClick={loadMore}
                loading={loading}
              >
                Load More Activity
              </Button>
            )}
          </ScrollArea>
        )}
      </Stack>
    </Paper>
  );
};
