import type {
  CoreMemberDetailed,
  VpAccountDetails,
} from "@/lib/features/members/types";
import type { CoreAccountOverview } from "@/lib/features/members/query";
import type { CuratedEventsBooking } from "@/lib/features/bookings/curated/types";
import type { CoreBookingUnit } from "@/lib/features/bookings/types";
import {
  ActionIcon,
  Badge,
  Divider,
  Flex,
  Group,
  Stack,
  Tabs,
  Text,
  Title,
} from "@mantine/core";
import {
  IconArrowLeft,
  IconClipboardText,
  IconFileDescription,
  IconUserOff,
  IconUsers,
} from "@tabler/icons-react";
import { useEffect, useState } from "react";
import moment from "moment";
import { Link, useLocation, useNavigate } from "react-router";
import AccountDetails from "./(widgets)/accountDetails";
import DeleteAccountControl from "./(widgets)/deleteAccountControl";
import AccountDeletionPanel from "./(widgets)/accountDeletionPanel";
import { AccountOverview } from "./(widgets)/accountOverview";
import { MemberPointsControl } from "./(widgets)/memberPoints";
import { accountStatusTone } from "@/routes/members/_components/statusColors";
import MemberContacts from "./(widgets)/memberContacts";
import MembershipBookings from "./(widgets)/membershipBookings";
import type { BookingTabValue } from "./(widgets)/membershipBookings";

const MemberClientPage: React.FC<{
  account: VpAccountDetails;
  contacts: CoreMemberDetailed[];
  bookings?: { data: CoreBookingUnit[]; totalRows: number };
  /**
   * Internal-property and external (RCI) bookings, shown as separate tabs on
   * the standalone member page. Embeds that only have one list keep using
   * `bookings` above.
   */
  bookingsByType?: {
    internal: { data: CoreBookingUnit[]; totalRows: number };
    external: { data: CoreBookingUnit[]; totalRows: number };
  };
  curatedBookings?: { data: CuratedEventsBooking[]; totalRows: number };
  bookingEntityType?: BookingTabValue;
  /** Booking history is capability-gated; hides the tab when false. */
  canViewBookings?: boolean;
  /**
   * Whether the reader may retire this account.
   *
   * Passed in from the loader rather than read from the cookie here: the
   * client-side check cannot see a cookie during the server render, so deciding it
   * in this component kept the button and the tab out of the server HTML.
   */
  canDeleteAccount?: boolean;
  /** Where the user came from (promo drilldowns redirect here). */
  backHref?: string;
  backLabel?: string;
  /** `member-points` read; hides the on-demand points control. */
  canViewPoints?: boolean;
  overview?: CoreAccountOverview;
  /**
   * If true (default), the active tab is read from `?tab=` and writes to the
   * URL on change. Set to false when rendering inside a Drawer/Modal so we
   * don't pollute the host page's URL.
   */
  syncTabWithUrl?: boolean;
  /**
   * Absolute base path to route contact clicks to (e.g. "/admin/members/123").
   * When provided, contact rows navigate to `${contactHrefBase}/${member_number}`
   * instead of the default relative navigation. Set this when this component is
   * embedded under a route that doesn't have a nested contact route.
   */
  contactHrefBase?: string;
  /**
   * Optional points allocated to this member (from the promo code reward, when
   * viewed inside a promo-code-campaigns context). When provided, surfaced on
   * the AccountDetails widget. Standalone members page leaves this undefined.
   */
  pointsAllocated?: number | null;
}> = ({
  account,
  contacts,
  bookings,
  bookingsByType,
  curatedBookings,
  bookingEntityType = "internal",
  canViewBookings = false,
  canViewPoints = false,
  canDeleteAccount = false,
  backHref,
  backLabel,
  overview,
  syncTabWithUrl = true,
  contactHrefBase,
  pointsAllocated,
}) => {
  const navigate = useNavigate();
  const { search } = useLocation();
  // Retiring an account and reading why it was retired are the same privilege, and
  // both are super admin — core refuses either to anyone else regardless.
  const canDelete = canDeleteAccount;
  const searchParams = new URLSearchParams(search);
  const paramsTab = searchParams.get("tab") ?? "accountDetails";
  const [selectedTab, setSelectedTab] = useState(
    syncTabWithUrl ? (paramsTab ?? "accountDetails") : "accountDetails",
  );
  useEffect(() => {
    if (syncTabWithUrl) setSelectedTab(paramsTab);
  }, [paramsTab, syncTabWithUrl]);
  const handleTabClick = (value: string) => {
    setSelectedTab(value);
    if (!syncTabWithUrl) return;

    const nextSearchParams = new URLSearchParams(search);
    nextSearchParams.set("tab", value);
    if (value === "bookings") {
      nextSearchParams.set("type", bookingEntityType);
      nextSearchParams.set("page", "1");
      nextSearchParams.set("pageSize", "50");
    } else {
      nextSearchParams.delete("type");
      nextSearchParams.delete("page");
      nextSearchParams.delete("pageSize");
    }
    navigate(`?${nextSearchParams.toString()}`);
  };
  return (
    <Stack gap={"sm"} pb={34}>
      <Group
        justify="space-between"
        align="flex-start"
        wrap="nowrap"
        mb={20}
        pb={20}
        px={28}
        style={{
          borderBottom:
            "1px solid light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-4))",
        }}
      >
        <Stack gap={"xs"}>
          {backHref ? (
            <Group gap={6}>
              <ActionIcon
                variant="subtle"
                component={Link}
                to={backHref}
                aria-label="Back"
              >
                <IconArrowLeft size={18} />
              </ActionIcon>
              <Text fz={12} c="dimmed">
                Back{backLabel ? ` to ${backLabel}` : ""}
              </Text>
            </Group>
          ) : null}
          <Flex direction={"row"} gap={"xs"} align={"center"}>
            <Title fz={"h3"} fw={500}>
              {account.AccountID}
            </Title>
            <Divider orientation="vertical" h={26} my={"auto"} />
            <Text c="var(--promo-accent)" size="18px" tt={"capitalize"}>
              {account.AccountType?.toLowerCase()}
            </Text>
          </Flex>
          {/* Last login sits with the identity, not in the KPI row: it describes
            the member, and as a tile it competed with the figures. */}
          {overview?.lastSession ? (
            <Text fz={12} c="dimmed">
              Last login {moment(overview.lastSession.created_at).fromNow()} ·{" "}
              {overview.lastSession.application_type ?? "unknown app"}
              {overview.lastSession.application_version
                ? ` ${overview.lastSession.application_version}`
                : ""}
              {overview.lastSession.os ? ` · ${overview.lastSession.os}` : ""}
              {overview.lastSession.ip_address
                ? ` · ${overview.lastSession.ip_address}`
                : ""}
              {overview.lastSession.member_number
                ? ` · member ${overview.lastSession.member_number}`
                : ""}
            </Text>
          ) : overview ? (
            <Text fz={12} c="dimmed">
              No app login recorded
            </Text>
          ) : null}
          <Badge
            {...accountStatusTone(account?.AccountStatus)}
            radius={4}
            fz={12}
            tt={"capitalize"}
            size="lg"
            fw={500}
          >
            {account?.AccountStatus?.toLowerCase()}
          </Badge>
        </Stack>

        {/* Points live on the header line: the figure describes the account, and
            the lookup stays a deliberate click (it round-trips to Viewpoint). */}
        <MemberPointsControl
          membershipNumber={canViewPoints ? account?.AccountID : undefined}
        />

        {/* Super admin only, and it renders nothing for anyone else. Sits beside the
            points control because both describe the account as a whole rather than
            anything inside a tab. */}
        {canDelete && (
          <DeleteAccountControl membershipNumber={account?.AccountID} />
        )}
      </Group>

      <AccountOverview overview={overview} />

      {/* Tabs */}
      <Tabs defaultValue="accountDetails" value={selectedTab} mt="md">
        <Tabs.List px={28}>
          {TAB_HEADS.filter(({ value }) => {
            if (value === "bookings") return canViewBookings;
            // The deletion tab is a super-admin surface: it carries the reason
            // someone closed the account and the button that undoes it.
            if (value === "deletion") return canDelete;
            return true;
          }).map(({ label, value, icon }) => (
            <Tabs.Tab
              key={value}
              fw={500}
              fz={14}
              value={value}
              onClick={() => handleTabClick(value)}
            >
              <Flex align={"center"} gap={3}>
                {icon}
                <Text>{label}</Text>
              </Flex>
            </Tabs.Tab>
          ))}
        </Tabs.List>

        <Tabs.Panel value="accountDetails" pt="md">
          {account ? (
            <AccountDetails
              account={account ?? {}}
              pointsAllocated={pointsAllocated}
            />
          ) : (
            ""
          )}
        </Tabs.Panel>

        <Tabs.Panel value="members" pt="md">
          {contacts ? (
            <MemberContacts
              contacts={contacts}
              contactHrefBase={contactHrefBase}
            />
          ) : (
            ""
          )}
        </Tabs.Panel>

        <Tabs.Panel value="deletion" pt="md">
          {canDelete && account?.AccountID ? (
            <AccountDeletionPanel accountId={account.AccountID} />
          ) : null}
        </Tabs.Panel>

        <Tabs.Panel value="bookings" pt="md">
          {canViewBookings ? (
            <MembershipBookings
              bookings={
                bookingsByType ?? {
                  internal: bookings ?? { data: [], totalRows: 0 },
                  external: { data: [], totalRows: 0 },
                }
              }
              curatedBookings={curatedBookings}
              selectedBookingType={bookingEntityType}
              enableTypeTabs={Boolean(bookingsByType) && syncTabWithUrl}
            />
          ) : null}
        </Tabs.Panel>
      </Tabs>
    </Stack>
  );
};

export default MemberClientPage;

const TAB_HEADS = [
  {
    label: "Account Details",
    value: "accountDetails",
    icon: <IconClipboardText size={20} />,
  },
  {
    label: "Members",
    value: "members",
    icon: <IconUsers size={20} />,
  },
  {
    label: "Bookings",
    value: "bookings",
    icon: <IconFileDescription size={19} />,
  },
  {
    label: "Deletion",
    value: "deletion",
    icon: <IconUserOff size={19} />,
  },
];
