"use client";

import {
  useCallback,
  useMemo,
  useRef,
  useState,
  type KeyboardEvent,
} from "react";

import PersonAddOutlinedIcon from "@mui/icons-material/PersonAddOutlined";
import SearchIcon from "@mui/icons-material/Search";
import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import ClickAwayListener from "@mui/material/ClickAwayListener";
import Divider from "@mui/material/Divider";
import IconButton from "@mui/material/IconButton";
import Paper from "@mui/material/Paper";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";

import { getStakeholderUsers } from "@/features/stakeholder/service/stakeholder-service";
import type { StakeholderUser } from "@/features/stakeholder/stakeholder-data";
import {
  getMeetingRequestGuestUsers,
  type MeetingGuestUser,
} from "../meeting-calendar-service";

export type GuestEntry = {
  id: string;
  name: string;
  email: string;
  avatar?: string | null;
  type: "user" | "email";
};

type UserOption = {
  id: string;
  name: string;
  email: string;
  avatar?: string | null;
};

type MeetingGuestPickerProps = {
  value: GuestEntry[];
  onChange: (guests: GuestEntry[]) => void;
  meetingRequestId?: number;
  governmentAgencies?: {
    id: number;
    name: string;
  }[];
  error?: boolean;
  helperText?: string;
};

function initials(name: string) {
  return name
    .split(" ")
    .slice(0, 2)
    .map((w) => w[0])
    .join("")
    .toUpperCase();
}

function isValidEmail(value: string) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value.trim());
}

function getAgencyKey(
  governmentAgencies: MeetingGuestPickerProps["governmentAgencies"],
) {
  return (governmentAgencies ?? [])
    .map((agency) => agency.id)
    .filter((agencyId) => Number.isInteger(agencyId))
    .sort((a, b) => a - b)
    .join(",");
}

function mapStakeholderUser(user: StakeholderUser): UserOption | null {
  const email = user.email?.trim();

  if (!email) return null;

  return {
    id: String(user.id),
    name: user.name?.trim() || email,
    email,
    avatar: user.avatar ?? null,
  };
}

function mapMeetingGuestUser(user: MeetingGuestUser): UserOption | null {
  const email = user.email?.trim();

  if (!email) return null;

  return {
    id: String(user.id),
    name: user.name?.trim() || email,
    email,
    avatar: user.avatar ?? null,
  };
}

function uniqueUserOptions(users: UserOption[]) {
  const uniqueUsers = new Map<string, UserOption>();

  for (const user of users) {
    const key = user.id || user.email.toLowerCase();

    if (!uniqueUsers.has(key)) {
      uniqueUsers.set(key, user);
    }
  }

  return Array.from(uniqueUsers.values());
}

function GuestChip({
  guest,
  onRemove,
  borderColor,
  chipBg,
  textColor,
}: {
  guest: GuestEntry;
  onRemove: () => void;
  borderColor: string;
  chipBg: string;
  textColor: string;
}) {
  return (
    <Box
      sx={{
        display: "inline-flex",
        alignItems: "center",
        gap: 0.75,
        pl: 0.5,
        pr: 1,
        py: 0.25,
        border: `1px solid ${borderColor}`,
        borderRadius: "100px",
        bgcolor: chipBg,
        maxWidth: 220,
      }}
    >
      <Avatar
        src={guest.avatar ?? undefined}
        alt={guest.name}
        sx={{ width: 22, height: 22, fontSize: 9, fontWeight: 600 }}
      >
        {initials(guest.name || guest.email)}
      </Avatar>

      <Typography
        noWrap
        sx={{
          fontSize: 12,
          fontWeight: 500,
          color: textColor,
          maxWidth: 140,
        }}
      >
        {guest.name || guest.email}
      </Typography>

      <Box
        component="button"
        type="button"
        onClick={onRemove}
        aria-label={`Remove ${guest.name || guest.email}`}
        sx={{
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          width: 14,
          height: 14,
          borderRadius: "50%",
          bgcolor: "transparent",
          border: "none",
          cursor: "pointer",
          color: textColor,
          flexShrink: 0,
          opacity: 0.55,
          p: 0,
          "&:hover": { opacity: 1 },
        }}
      >
        ×
      </Box>
    </Box>
  );
}

function UserRow({
  user,
  isAdded,
  onAdd,
  mutedColor,
  textColor,
}: {
  user: UserOption;
  isAdded: boolean;
  onAdd: () => void;
  mutedColor: string;
  textColor: string;
}) {
  return (
    <Box
      sx={{
        display: "flex",
        alignItems: "center",
        px: 2,
        py: 1.5,
        gap: 1.5,
        cursor: isAdded ? "default" : "pointer",
        "&:hover": { bgcolor: isAdded ? "transparent" : "action.hover" },
        opacity: isAdded ? 0.5 : 1,
      }}
      onClick={() => {
        if (!isAdded) onAdd();
      }}
    >
      <Avatar
        src={user.avatar ?? undefined}
        alt={user.name}
        sx={{ width: 40, height: 40, fontSize: 14, fontWeight: 700 }}
      >
        {initials(user.name || user.email)}
      </Avatar>

      <Box sx={{ minWidth: 0, flex: 1 }}>
        <Typography
          sx={{
            fontSize: 14,
            fontWeight: 500,
            color: textColor,
            lineHeight: 1.3,
            fontFamily: "Roboto, sans-serif",
          }}
          noWrap
        >
          {user.name.toUpperCase() || user.email}
        </Typography>
        <Typography
          sx={{
            fontSize: 13,
            fontWeight: 400,
            color: mutedColor,
            lineHeight: 1.3,
            mt: 0.25,
          }}
          noWrap
        >
          {user.email}
        </Typography>
      </Box>
    </Box>
  );
}

export function MeetingGuestPicker({
  value,
  onChange,
  meetingRequestId,
  governmentAgencies = [],
  error = false,
  helperText,
}: MeetingGuestPickerProps) {
  const theme = useTheme();
  const isDark = theme.palette.mode === "dark";

  const borderColor = isDark ? alpha("#ffffff", 0.14) : "#f5f5f5";
  const softBackground = isDark ? alpha("#ffffff", 0.04) : "#fafafa";
  const textColor = isDark ? "#e5e7eb" : "#181d27";
  const mutedColor = isDark ? "#9ca3af" : "#535862";
  const chipBg = isDark ? alpha("#ffffff", 0.08) : "#f5f5f5";
  const popupBg = isDark ? "#1e293b" : "#ffffff";
  const shadowColor = isDark ? "rgba(0,0,0,0.5)" : "rgba(0,0,0,0.10)";

  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const [allUsers, setAllUsers] = useState<UserOption[]>([]);
  const [loadingUsers, setLoadingUsers] = useState(false);
  const [loadedAgencyKey, setLoadedAgencyKey] = useState("");
  const searchRef = useRef<HTMLInputElement>(null);
  const anchorRef = useRef<HTMLDivElement>(null);

  const agencyKey = useMemo(
    () =>
      `${meetingRequestId ?? "no-request"}:${getAgencyKey(governmentAgencies)}`,
    [governmentAgencies, meetingRequestId],
  );
  const hasGovernmentAgencies = governmentAgencies.length > 0;
  const addedIds = new Set(value.map((g) => g.id));
  const cachedUsers = loadedAgencyKey === agencyKey ? allUsers : [];

  const filtered = cachedUsers.filter((u) => {
    const q = search.toLowerCase().trim();
    if (!q) return true;
    return (
      u.name.toLowerCase().includes(q) || u.email.toLowerCase().includes(q)
    );
  });

  const loadAgencyUsers = useCallback(async () => {
    if (agencyKey === loadedAgencyKey || loadingUsers) return;

    if (!meetingRequestId && !hasGovernmentAgencies) {
      setAllUsers([]);
      setLoadedAgencyKey(agencyKey);
      return;
    }

    setAllUsers([]);
    setLoadingUsers(true);

    try {
      let users: UserOption[] = [];

      if (meetingRequestId) {
        try {
          const meetingRequestUsers =
            await getMeetingRequestGuestUsers(meetingRequestId);

          users = meetingRequestUsers
            .map(mapMeetingGuestUser)
            .filter((user): user is UserOption => Boolean(user));
        } catch {
          users = [];
        }
      }

      if (users.length === 0 && hasGovernmentAgencies) {
        const usersByAgency = await Promise.allSettled(
          governmentAgencies.map((agency) => getStakeholderUsers(agency.id)),
        );

        users = usersByAgency
          .filter(
            (result): result is PromiseFulfilledResult<StakeholderUser[]> =>
              result.status === "fulfilled",
          )
          .flatMap((result) => result.value)
          .map(mapStakeholderUser)
          .filter((user): user is UserOption => Boolean(user));
      }

      setAllUsers(uniqueUserOptions(users));
      setLoadedAgencyKey(agencyKey);
    } catch {
      setAllUsers([]);
      setLoadedAgencyKey(agencyKey);
    } finally {
      setLoadingUsers(false);
    }
  }, [
    agencyKey,
    governmentAgencies,
    hasGovernmentAgencies,
    loadedAgencyKey,
    loadingUsers,
    meetingRequestId,
  ]);

  const closeDropdown = useCallback(() => {
    setOpen(false);
    setSearch("");
  }, []);

  const openDropdown = useCallback(async () => {
    setOpen(true);
    await loadAgencyUsers();
    setTimeout(() => searchRef.current?.focus(), 50);
  }, [loadAgencyUsers]);

  const addUser = (user: UserOption) => {
    if (addedIds.has(user.id)) return;

    onChange([
      ...value,
      {
        id: user.id,
        name: user.name,
        email: user.email,
        avatar: user.avatar,
        type: "user",
      },
    ]);
  };

  const addEmail = () => {
    const email = search.trim();

    if (!isValidEmail(email)) return;
    if (value.some((g) => g.email === email)) return;

    onChange([
      ...value,
      {
        id: `email-${email}`,
        name: email,
        email,
        avatar: null,
        type: "email",
      },
    ]);

    setSearch("");
  };

  const removeGuest = (id: string) => {
    onChange(value.filter((g) => g.id !== id));
  };

  const handleSearchKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
    if (event.key === "Enter") {
      event.preventDefault();
      addEmail();
    }
  };

  return (
    <Box sx={{ width: "100%" }}>
      {/* Trigger button */}
      <ClickAwayListener onClickAway={closeDropdown}>
        <Box ref={anchorRef} sx={{ position: "relative" }}>
          <Box
            component="button"
            type="button"
            onClick={openDropdown}
            sx={{
              width: "100%",
              height: 40,
              display: "flex",
              alignItems: "center",
              gap: 0.75,
              px: 2,
              border: `1px solid ${error ? "#f04438" : borderColor}`,
              borderRadius: "6px",
              bgcolor: softBackground,
              cursor: "pointer",
              textAlign: "left",
              transition: "border-color 0.2s",
              "&:hover": {
                borderColor: isDark ? alpha("#ffffff", 0.3) : "#d0d5dd",
              },
            }}
          >
            <Box
              component="span"
              sx={{
                display: "flex",
                alignItems: "center",
                fontSize: 18,
                color: isDark ? alpha("#ffffff", 0.5) : "#717680",
                mr: 0.25,
              }}
            >
              {/* Users icon matching Figma */}
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="1.8"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
                <circle cx="9" cy="7" r="4" />
                <path d="M23 21v-2a4 4 0 0 0-3-3.87" />
                <path d="M16 3.13a4 4 0 0 1 0 7.75" />
              </svg>
            </Box>

            <Typography
              sx={{
                fontSize: 12,
                fontWeight: 400,
                color: isDark ? alpha("#ffffff", 0.4) : "#717680",
                flex: 1,
              }}
            >
              {value.length === 0
                ? "Invite People"
                : `${value.length} guest${value.length > 1 ? "s" : ""} invited`}
            </Typography>
          </Box>

          {/* Dropdown */}
          {open && (
            <Paper
              elevation={0}
              sx={{
                position: "absolute",
                right: 0,
                top: "calc(100% + 6px)",
                width: { xs: "100%", sm: 340 },
                maxHeight: 320,
                zIndex: 1700,
                bgcolor: popupBg,
                border: `1px solid ${isDark ? alpha("#ffffff", 0.1) : "#e9eaeb"}`,
                borderRadius: "12px",
                boxShadow: `0 0 67.6px -7px ${shadowColor}`,
                overflow: "hidden",
                display: "flex",
                flexDirection: "column",
              }}
            >
              {/* Search row */}
              <Box
                sx={{
                  display: "flex",
                  alignItems: "center",
                  gap: 1,
                  px: 1.5,
                  py: 1,
                  borderBottom: `1px solid ${isDark ? alpha("#ffffff", 0.08) : "#f0f0f0"}`,
                }}
              >
                <SearchIcon
                  sx={{
                    fontSize: 20,
                    color: isDark ? alpha("#ffffff", 0.4) : "#989898",
                    flexShrink: 0,
                  }}
                />

                <Box
                  component="input"
                  ref={searchRef}
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                  onKeyDown={handleSearchKeyDown}
                  placeholder="Invite people via this email address"
                  sx={{
                    flex: 1,
                    border: "none",
                    outline: "none",
                    bgcolor: "transparent",
                    fontSize: 13,
                    fontWeight: 400,
                    color: textColor,
                    "::placeholder": {
                      color: isDark ? alpha("#ffffff", 0.3) : "#989898",
                    },
                    fontFamily: "Roboto, sans-serif",
                  }}
                />

                <Tooltip
                  title={
                    isValidEmail(search)
                      ? `Add ${search.trim()} by email`
                      : "Type a valid email and press Enter to add"
                  }
                  placement="top"
                >
                  <Box
                    component="span"
                    sx={{ display: "flex", alignItems: "center" }}
                  >
                    <IconButton
                      size="small"
                      onClick={addEmail}
                      disabled={!isValidEmail(search)}
                      sx={{
                        color: isDark ? alpha("#ffffff", 0.5) : "#717680",
                        "&:hover": { color: "#1a64a8" },
                      }}
                    >
                      <PersonAddOutlinedIcon sx={{ fontSize: 20 }} />
                    </IconButton>
                  </Box>
                </Tooltip>
              </Box>

              {/* User list */}
              <Box sx={{ overflowY: "auto", flex: 1 }}>
                {loadingUsers ? (
                  <Typography
                    sx={{
                      py: 3,
                      textAlign: "center",
                      fontSize: 12,
                      color: mutedColor,
                    }}
                  >
                    Loading…
                  </Typography>
                ) : filtered.length === 0 ? (
                  <Typography
                    sx={{
                      py: 3,
                      textAlign: "center",
                      fontSize: 12,
                      color: mutedColor,
                    }}
                  >
                    {search
                      ? "No matching users"
                      : meetingRequestId || hasGovernmentAgencies
                        ? "No users found"
                        : "No government agency selected"}
                  </Typography>
                ) : (
                  filtered.map((user, index) => (
                    <Box key={user.id}>
                      {index > 0 && (
                        <Divider
                          sx={{
                            borderColor: isDark
                              ? alpha("#ffffff", 0.06)
                              : "#f5f5f5",
                          }}
                        />
                      )}
                      <UserRow
                        user={user}
                        isAdded={addedIds.has(user.id)}
                        onAdd={() => addUser(user)}
                        mutedColor={mutedColor}
                        textColor={textColor}
                      />
                    </Box>
                  ))
                )}
              </Box>
            </Paper>
          )}
        </Box>
      </ClickAwayListener>

      {/* Selected guest chips */}
      {value.length > 0 && (
        <Box
          sx={{
            mt: 1,
            display: "flex",
            flexWrap: "wrap",
            gap: 0.75,
          }}
        >
          {value.map((guest) => (
            <GuestChip
              key={guest.id}
              guest={guest}
              onRemove={() => removeGuest(guest.id)}
              borderColor={borderColor}
              chipBg={chipBg}
              textColor={textColor}
            />
          ))}
        </Box>
      )}

      {/* Error text */}
      {helperText ? (
        <Typography
          sx={{
            mt: 0.5,
            fontSize: 12,
            color: error ? "#f04438" : mutedColor,
          }}
        >
          {helperText}
        </Typography>
      ) : null}
    </Box>
  );
}
