import { useCallback, useEffect, useMemo, useState } from "react";
import { Stack, Group, Title, Button, Card, Text, Table, Badge, Loader, Pagination, Grid, TextInput, Select, Box, Modal, Flex, ThemeIcon, Avatar, UnstyledButton, LoadingOverlay, Divider } from "@mantine/core";
import { IconArrowsRightLeft, IconGift, IconRefresh, IconCheck, IconWallet, IconSend, IconUsers, IconSearch } from "@tabler/icons-react";
import { getMyBalances, getMyTransactions, getMyEntitlements } from "@/lib/features/points-transfer/query";
import type { PointsEntitlement } from "@/lib/features/points-transfer/types";
import { MemberTransferPanel } from "./MemberTransferPanel";
import { NotesCell } from "./NotesCell";
import { PageSizeSelect } from "./PageSizeSelect";
import { notifications } from "@mantine/notifications";
import { useRoleAccess } from "@/hooks/useRoleAccess";
import { useIsMobile } from "@/hooks/useIsMobile";

const StatCard = ({
  label,
  value,
  icon,
  color,
  valueColor,
  footer,
}: {
  label: string;
  value: string;
  icon: React.ReactNode;
  color: string;
  valueColor?: string;
  footer?: React.ReactNode;
}) => (
  <Card withBorder shadow="sm" radius="md" p="md" h="100%">
    <Group justify="space-between" align="flex-start" wrap="nowrap">
      <Stack gap={4} style={{ minWidth: 0 }}>
        <Text c="dimmed" fz={11} tt="uppercase" fw={700} lts={0.4}>{label}</Text>
        <Text fw={700} fz={{ base: 22, sm: 26 }} lh={1.2} c={valueColor} truncate>{value}</Text>
        {footer}
      </Stack>
      <ThemeIcon variant="light" color={color} size={42} radius="md">{icon}</ThemeIcon>
    </Group>
  </Card>
);

export const MyPointsTab = () => {
  const isMobile = useIsMobile();
  const { checkClientAccess, isSuperAdmin } = useRoleAccess();
  const hasAccess = isSuperAdmin() || checkClientAccess("read", "my-points");

  const [balanceData, setBalanceData] = useState<{ balance: number; account: string } | null>(null);
  const [loading, setLoading] = useState(true);

  const [transactions, setTransactions] = useState<any[]>([]);
  const [txTotal, setTxTotal] = useState(0);
  const [totalPointsTransferred, setTotalPointsTransferred] = useState(0);
  const [totalUniqueUsers, setTotalUniqueUsers] = useState(0);
  const [searchQuery, setSearchQuery] = useState("");
  const [txPage, setTxPage] = useState(1);
  const [txPerPage, setTxPerPage] = useState(5);

  const [panelOpened, setPanelOpened] = useState(false);

  const [entitlements, setEntitlements] = useState<PointsEntitlement[]>([]);
  const [loadingEntitlements, setLoadingEntitlements] = useState(false);
  const [selectedEntitlement, setSelectedEntitlement] = useState<string | null>(null);

  const [selectedMemberForPopup, setSelectedMemberForPopup] = useState<any | null>(null);

  const fetchData = useCallback(async () => {
    if (!hasAccess) {
      setLoading(false);
      return;
    }
    setLoading(true);
    setLoadingEntitlements(true);
    try {
      const balRes = await getMyBalances();
      if (balRes.success) {
        setBalanceData(balRes.data);
      }

      const entRes = await getMyEntitlements();
      if (entRes.success && entRes.data) {
        const filteredAndSorted = entRes.data
          .filter((e: PointsEntitlement) => e.Status === "ACTIVE" && e.Balance > 0)
          .sort((a: PointsEntitlement, b: PointsEntitlement) => b.Balance - a.Balance);
        setEntitlements(filteredAndSorted);
        if (filteredAndSorted.length > 0) {
          setSelectedEntitlement(filteredAndSorted[0].PointsEntitlementID.toString());
        }
      }

      const offset = (txPage - 1) * txPerPage;
      const txRes = await getMyTransactions(txPerPage, offset, searchQuery);
      if (txRes.success && txRes.data) {
        setTransactions(txRes.data.transactions);
        setTxTotal(txRes.data.total);
        setTotalPointsTransferred(txRes.data.totalPoints);
        setTotalUniqueUsers(txRes.data.totalUsers);
      }
    } catch (err) {
      notifications.show({ color: "red", message: "Failed to load data" });
    } finally {
      setLoading(false);
      setLoadingEntitlements(false);
    }
  }, [txPage, txPerPage, hasAccess, searchQuery]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  const activeEntitlement = useMemo(
    () => entitlements.find(e => e.PointsEntitlementID.toString() === selectedEntitlement),
    [entitlements, selectedEntitlement],
  );

  const memberTransactions = useMemo(
    () => (selectedMemberForPopup
      ? transactions.filter(tx => tx.target_contact_id === selectedMemberForPopup.target_contact_id)
      : []),
    [transactions, selectedMemberForPopup],
  );

  if (!hasAccess) {
    return (
      <Stack align="center" mt="xl" gap={6}>
        <Title order={3}>Access Denied</Title>
        <Text c="dimmed" ta="center">Only mapped managers have access to this page.</Text>
      </Stack>
    );
  }

  if (loading && !balanceData) {
    return (
      <Group justify="center" mt="xl">
        <Loader />
      </Group>
    );
  }

  if (balanceData?.account === "Unmapped") {
    return (
      <Stack align="center" mt="xl" gap="xs" px="md">
        <IconGift size={64} color="var(--mantine-color-gray-4)" />
        <Title order={3}>Account Not Mapped</Title>
        <Text c="dimmed" ta="center" maw={420}>
          Your account has not been linked to a ViewPoint membership yet. Please contact a Super Admin.
        </Text>
      </Stack>
    );
  }

  const totalPages = Math.ceil(txTotal / txPerPage);
  const rangeStart = txTotal === 0 ? 0 : (txPage - 1) * txPerPage + 1;
  const rangeEnd = Math.min(txPage * txPerPage, txTotal);

  return (
    <Stack gap="lg" p={{ base: "xs", sm: 20 }}>
      <Flex
        direction={{ base: "column", sm: "row" }}
        justify="space-between"
        align={{ base: "stretch", sm: "center" }}
        gap="sm"
      >
        <div>
          <Title order={2} fz={{ base: "h3", sm: "h2" }}>My Points</Title>
          <Text c="dimmed" size="sm">Manage and transfer your ViewPoint points to members.</Text>
        </div>
        <Group gap="sm" wrap="nowrap">
          <Button
            variant="default"
            leftSection={<IconRefresh size={16} />}
            onClick={fetchData}
            loading={loading}
            flex={{ base: 1, sm: "0 0 auto" }}
          >
            Sync
          </Button>
          <Button
            leftSection={<IconArrowsRightLeft size={16} />}
            onClick={() => setPanelOpened(true)}
            flex={{ base: 1, sm: "0 0 auto" }}
          >
            Transfer to Member
          </Button>
        </Group>
      </Flex>

      <Grid gutter={{ base: "sm", sm: "md" }}>
        <Grid.Col span={{ base: 12, sm: 6, lg: 4 }}>
          <StatCard
            label="Available Balance"
            value={`${balanceData?.balance?.toLocaleString() || 0} pts`}
            icon={<IconWallet size={22} />}
            color="blue"
            footer={<Badge variant="light" color="blue" size="sm">Acc: {balanceData?.account || "-"}</Badge>}
          />
        </Grid.Col>

        <Grid.Col span={{ base: 12, sm: 6, lg: 4 }}>
          <StatCard
            label="Total Transferred"
            value={`${totalPointsTransferred.toLocaleString()} pts`}
            icon={<IconSend size={22} />}
            color="red"
            valueColor="red"
          />
        </Grid.Col>

        <Grid.Col span={{ base: 12, sm: 12, lg: 4 }}>
          <StatCard
            label="Total Unique Members"
            value={`${totalUniqueUsers.toLocaleString()} members`}
            icon={<IconUsers size={22} />}
            color="grape"
          />
        </Grid.Col>
      </Grid>

      <Card withBorder shadow="sm" radius="md" p={{ base: "sm", sm: "lg" }}>
        <Select
          label="Select Points Entitlement"
          description="Transfers draw from your entitlements, highest balance first."
          placeholder={loadingEntitlements ? "Loading..." : entitlements.length === 0 ? "No active entitlements available" : "Select entitlement to view details"}
          data={entitlements.map(e => ({
            value: e.PointsEntitlementID.toString(),
            label: `[${e.CustomType} - ${e.EntitlementYear}] ${e.PointsClubName} | ${e.Balance} pts | Expires: ${new Date(e.ExpiryDate).toLocaleDateString()}`
          }))}
          renderOption={({ option, checked }) => {
            const e = entitlements.find(ent => ent.PointsEntitlementID.toString() === option.value);
            if (!e) return <Text size="sm">{option.label}</Text>;
            return (
              <Group justify="space-between" wrap="nowrap" w="100%">
                <Stack gap={0} style={{ flex: 1, minWidth: 0 }}>
                  <Group justify="space-between" wrap="nowrap" gap="xs">
                    <Text size="sm" fw={checked ? 700 : 500} truncate>[{e.CustomType} - {e.EntitlementYear}] {e.PointsClubName}</Text>
                    <Badge size="xs" variant="light" color={e.Status === "ACTIVE" ? "green" : "gray"} style={{ flexShrink: 0 }}>{e.Status}</Badge>
                  </Group>
                  <Group justify="space-between" wrap="nowrap" mt={4} gap="xs">
                    <Text size="sm" c="dimmed">Balance: <strong>{e.Balance} pts</strong></Text>
                    <Text size="sm" c="dimmed">Expires: {new Date(e.ExpiryDate).toLocaleDateString()}</Text>
                  </Group>
                </Stack>
                {checked && <IconCheck size={18} color="var(--mantine-color-blue-6)" style={{ flexShrink: 0 }} />}
              </Group>
            );
          }}
          value={selectedEntitlement}
          onChange={setSelectedEntitlement}
          disabled={loadingEntitlements || entitlements.length === 0}
          withAsterisk
        />

        {activeEntitlement && (
          <>
            <Divider my="sm" />
            <Group gap="xs" wrap="wrap">
              <Badge variant="light" color="teal">{activeEntitlement.PointsClubName}</Badge>
              <Badge variant="light" color="blue">{activeEntitlement.Balance.toLocaleString()} pts available</Badge>
              <Badge variant="light" color="orange">
                Expires {new Date(activeEntitlement.ExpiryDate).toLocaleDateString()}
              </Badge>
              <Badge variant="light" color="gray">
                {activeEntitlement.CustomType} · {activeEntitlement.EntitlementYear}
              </Badge>
            </Group>
          </>
        )}
      </Card>

      <Card withBorder shadow="sm" radius="md" p={{ base: "sm", sm: "lg" }} pos="relative">
        <LoadingOverlay visible={loading} zIndex={5} overlayProps={{ blur: 1 }} loaderProps={{ size: "sm" }} />
        <Flex
          direction={{ base: "column", sm: "row" }}
          justify="space-between"
          align={{ base: "stretch", sm: "center" }}
          gap="sm"
          mb="md"
        >
          <Group gap="xs">
            <Title order={4}>Transfer History</Title>
            <Badge variant="light" color="gray" size="sm">{txTotal}</Badge>
          </Group>
          <TextInput
            placeholder="Search transfers..."
            leftSection={<IconSearch size={14} />}
            value={searchQuery}
            onChange={(e) => {
              setSearchQuery(e.currentTarget.value);
              setTxPage(1);
            }}
            size="xs"
            w={{ base: "100%", sm: 250 }}
          />
        </Flex>
        <Table.ScrollContainer minWidth={860}>
          <Table verticalSpacing="sm" highlightOnHover>
            <Table.Thead>
              <Table.Tr>
                <Table.Th>Date</Table.Th>
                <Table.Th>Transfer To</Table.Th>
                <Table.Th>Account / Contact ID</Table.Th>
                <Table.Th>Application</Table.Th>
                <Table.Th>Points</Table.Th>
                <Table.Th>Notes</Table.Th>
                <Table.Th>Status</Table.Th>
              </Table.Tr>
            </Table.Thead>
            <Table.Tbody>
              {transactions.length === 0 ? (
                <Table.Tr>
                  <Table.Td colSpan={7}>
                    <Stack align="center" gap={4} py="lg">
                      <IconGift size={28} color="var(--mantine-color-gray-4)" />
                      <Text c="dimmed" size="sm">
                        {searchQuery ? "No transfers match your search." : "No transactions found"}
                      </Text>
                    </Stack>
                  </Table.Td>
                </Table.Tr>
              ) : (
                transactions.map((tx) => (
                  <Table.Tr key={tx.id}>
                    <Table.Td>
                      <Text size="sm" style={{ whiteSpace: "nowrap" }}>
                        {tx.created_at ? new Date(tx.created_at).toLocaleString() : "-"}
                      </Text>
                    </Table.Td>
                    <Table.Td>
                      {tx.target_first_name ? (
                        <UnstyledButton onClick={() => setSelectedMemberForPopup(tx)} w="100%">
                          <Group gap="xs" wrap="nowrap">
                            <Avatar size={28} radius="xl" color="blue" variant="light">
                              {`${tx.target_first_name?.[0] || ""}${tx.target_last_name?.[0] || ""}`.toUpperCase()}
                            </Avatar>
                            <Box style={{ minWidth: 0 }}>
                              <Text size="sm" fw={500} truncate>{tx.target_first_name} {tx.target_last_name}</Text>
                              {tx.target_email && <Text size="sm" c="dimmed" truncate>{tx.target_email}</Text>}
                            </Box>
                          </Group>
                        </UnstyledButton>
                      ) : (
                        <Text size="sm" c="dimmed">-</Text>
                      )}
                    </Table.Td>
                    <Table.Td>
                      {tx.target_account_id ? (
                        <Stack gap={0}>
                          <Text size="sm" fw={500}>Acc: {tx.target_account_id}</Text>
                          <Text size="sm" c="dimmed">Contact: {tx.target_contact_id}</Text>
                        </Stack>
                      ) : (
                        <Text size="sm" c="dimmed">Not linked</Text>
                      )}
                    </Table.Td>
                    <Table.Td>
                      <Badge variant="outline" color="blue">
                        {tx.application || "Admin Console"}
                      </Badge>
                    </Table.Td>
                    <Table.Td fw={600} c="red" style={{ whiteSpace: "nowrap" }}>- {tx.points}</Table.Td>
                    <Table.Td>
                      <NotesCell value={tx.notes} maw={220} />
                    </Table.Td>
                    <Table.Td>
                      <Badge variant="light" color={tx.status === "SUCCESS" ? "green" : "gray"}>
                        {tx.status}
                      </Badge>
                    </Table.Td>
                  </Table.Tr>
                ))
              )}
            </Table.Tbody>
          </Table>
        </Table.ScrollContainer>

        {txTotal > 0 && (
          <Flex
            direction={{ base: "column", sm: "row" }}
            justify="space-between"
            align="center"
            gap="sm"
            mt="md"
          >
            <Group gap="md" wrap="wrap">
              <Text size="sm" c="dimmed">Showing {rangeStart}–{rangeEnd} of {txTotal}</Text>
              <PageSizeSelect
                value={txPerPage}
                onChange={(v) => { setTxPerPage(v); setTxPage(1); }}
              />
            </Group>
            <Pagination
              value={txPage}
              onChange={setTxPage}
              total={totalPages}
              size="sm"
              siblings={1}
              boundaries={1}
            />
          </Flex>
        )}
      </Card>

      <MemberTransferPanel
        opened={panelOpened}
        onClose={() => setPanelOpened(false)}
        maxPoints={balanceData?.balance || 0}
        onSuccess={() => {
          setTxPage(1);
          fetchData();
        }}
      />

      <Modal
        opened={!!selectedMemberForPopup}
        onClose={() => setSelectedMemberForPopup(null)}
        title={<Title order={4}>Member Profile</Title>}
        size="xl"
        // An "xl" modal wrapping a 600px-wide table is unusable on a phone:
        // the sheet itself scrolls sideways. Full screen keeps the header,
        // badges and table scroll all in view.
        fullScreen={isMobile}
      >
        {selectedMemberForPopup && (
          <Stack gap="md">
            <Flex
              direction={{ base: "column", sm: "row" }}
              justify="space-between"
              align={{ base: "flex-start", sm: "center" }}
              gap="sm"
            >
              <Group gap="sm" wrap="nowrap">
                <Avatar size={44} radius="xl" color="blue" variant="light">
                  {`${selectedMemberForPopup.target_first_name?.[0] || ""}${selectedMemberForPopup.target_last_name?.[0] || ""}`.toUpperCase() || "?"}
                </Avatar>
                <Box style={{ minWidth: 0 }}>
                  <Text size="lg" fw={600}>
                    {selectedMemberForPopup.target_first_name
                      ? `${selectedMemberForPopup.target_first_name} ${selectedMemberForPopup.target_last_name}`
                      : `Contact ${selectedMemberForPopup.target_contact_id}`}
                  </Text>
                  {selectedMemberForPopup.target_email && (
                    <Text c="dimmed" size="sm" truncate>{selectedMemberForPopup.target_email}</Text>
                  )}
                </Box>
              </Group>
              <Group gap="xs" wrap="wrap">
                <Badge size="md" variant="light" color="cyan">Acc: {selectedMemberForPopup.target_account_id}</Badge>
                <Badge size="md" variant="light" color="grape">Con: {selectedMemberForPopup.target_contact_id}</Badge>
              </Group>
            </Flex>

            <Divider />

            <Title order={5}>Recent Transfer History</Title>
            <Table.ScrollContainer minWidth={600}>
              <Table verticalSpacing="sm" striped>
                <Table.Thead>
                  <Table.Tr>
                    <Table.Th>Date</Table.Th>
                    <Table.Th>Points</Table.Th>
                    <Table.Th>Notes</Table.Th>
                    <Table.Th>Reference</Table.Th>
                    <Table.Th>Status</Table.Th>
                  </Table.Tr>
                </Table.Thead>
                <Table.Tbody>
                  {memberTransactions.length === 0 ? (
                    <Table.Tr>
                      <Table.Td colSpan={5} ta="center">
                        <Text c="dimmed" size="sm" my="sm">No transfers on this page for this member.</Text>
                      </Table.Td>
                    </Table.Tr>
                  ) : (
                    memberTransactions.map((tx) => (
                      <Table.Tr key={`popup-${tx.id}`}>
                        <Table.Td style={{ whiteSpace: "nowrap" }}>{tx.created_at ? new Date(tx.created_at).toLocaleString() : "-"}</Table.Td>
                        <Table.Td fw={600} c="red">- {tx.points}</Table.Td>
                        <Table.Td><NotesCell value={tx.notes} maw={240} /></Table.Td>
                        <Table.Td>{tx.viewpoint_ref_id || "-"}</Table.Td>
                        <Table.Td>
                          <Badge variant="light" color={tx.status === "SUCCESS" ? "green" : "gray"}>
                            {tx.status}
                          </Badge>
                        </Table.Td>
                      </Table.Tr>
                    ))
                  )}
                </Table.Tbody>
              </Table>
            </Table.ScrollContainer>
          </Stack>
        )}
      </Modal>
    </Stack>
  );
}
