"use client";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
import * as React from "react";
import { Users, Link2, Plus, Filter } from "lucide-react";
import { EmptyState } from "@open-mercato/ui/backend/EmptyState";
import { Button } from "@open-mercato/ui/primitives/button";
import { Badge } from "@open-mercato/ui/primitives/badge";
import { flash } from "@open-mercato/ui/backend/FlashMessages";
import { apiCallOrThrow, readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
import {
  readVersionedIdSet,
  writeVersionedIdSet
} from "@open-mercato/shared/lib/browser/versionedPreference";
import { useT } from "@open-mercato/shared/lib/i18n/context";
import { createTranslatorWithFallback } from "@open-mercato/shared/lib/i18n/translate";
import { useAppEvent } from "@open-mercato/ui/backend/injection/useAppEvent";
import { CreatePersonDialog } from "./CreatePersonDialog.js";
import { PersonCard } from "./PersonCard.js";
import { coerceDisplayName } from "../../lib/displayName.js";
import { DecisionMakersFooter } from "./DecisionMakersFooter.js";
import { RolesSection } from "./RolesSection.js";
import { LinkEntityDialog } from "../linking/LinkEntityDialog.js";
import { createPersonLinkAdapter } from "../linking/adapters/personAdapter.js";
const COMPANY_PEOPLE_PAGE_SIZE = 20;
const STARRED_PEOPLE_STORAGE_VERSION = 1;
function normalizeCompanyPerson(record) {
  const id = typeof record.id === "string" ? record.id : null;
  if (!id) return null;
  const displayName = typeof record.displayName === "string" && record.displayName.trim().length ? record.displayName.trim() : typeof record.display_name === "string" && record.display_name.trim().length ? record.display_name.trim() : null;
  if (!displayName) return null;
  return {
    id,
    displayName,
    primaryEmail: typeof record.primaryEmail === "string" ? record.primaryEmail : typeof record.primary_email === "string" ? record.primary_email : null,
    primaryPhone: typeof record.primaryPhone === "string" ? record.primaryPhone : typeof record.primary_phone === "string" ? record.primary_phone : null,
    status: typeof record.status === "string" ? record.status : null,
    lifecycleStage: typeof record.lifecycleStage === "string" ? record.lifecycleStage : typeof record.lifecycle_stage === "string" ? record.lifecycle_stage : null,
    jobTitle: typeof record.jobTitle === "string" ? record.jobTitle : typeof record.job_title === "string" ? record.job_title : null,
    department: typeof record.department === "string" ? record.department : null,
    createdAt: typeof record.createdAt === "string" ? record.createdAt : typeof record.created_at === "string" ? record.created_at : null,
    organizationId: typeof record.organizationId === "string" ? record.organizationId : typeof record.organization_id === "string" ? record.organization_id : null,
    temperature: typeof record.temperature === "string" ? record.temperature : null,
    source: typeof record.source === "string" ? record.source : null,
    linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : typeof record.linked_at === "string" ? record.linked_at : null
  };
}
function mergeCompanyPeople(items) {
  const merged = /* @__PURE__ */ new Map();
  items.forEach((item) => merged.set(item.id, item));
  return Array.from(merged.values());
}
function matchesCompanyPersonSearch(person, query) {
  const normalizedQuery = query.trim().toLowerCase();
  if (!normalizedQuery.length) return true;
  const haystack = [
    person.displayName,
    person.jobTitle ?? "",
    person.primaryEmail ?? "",
    person.primaryPhone ?? "",
    person.department ?? ""
  ].join(" ").toLowerCase();
  return haystack.includes(normalizedQuery);
}
function sortCompanyPeople(items, sortMode) {
  return [...items].sort((left, right) => {
    if (sortMode === "recent") {
      const leftTimestamp = Date.parse(left.linkedAt ?? left.createdAt ?? "") || 0;
      const rightTimestamp = Date.parse(right.linkedAt ?? right.createdAt ?? "") || 0;
      return rightTimestamp - leftTimestamp;
    }
    const leftLabel = coerceDisplayName(left.displayName).trim().toLowerCase();
    const rightLabel = coerceDisplayName(right.displayName).trim().toLowerCase();
    if (sortMode === "name-desc") return rightLabel.localeCompare(leftLabel);
    return leftLabel.localeCompare(rightLabel);
  });
}
function CompanyPeopleSection({
  companyId,
  companyName,
  initialPeople,
  addActionLabel,
  emptyLabel,
  emptyState,
  onPeopleChange,
  onActionChange,
  translator,
  onLoadingChange,
  onDataRefresh,
  runGuardedMutation
}) {
  const tHook = useT();
  const fallbackTranslator = React.useMemo(
    () => createTranslatorWithFallback(tHook),
    [tHook]
  );
  const translate = translator ?? fallbackTranslator;
  const [people, setPeople] = React.useState(initialPeople);
  const [removingId, setRemovingId] = React.useState(null);
  const [linkDialogOpen, setLinkDialogOpen] = React.useState(false);
  const [createDialogOpen, setCreateDialogOpen] = React.useState(false);
  const [searchQuery, setSearchQuery] = React.useState("");
  const [sortMode, setSortMode] = React.useState("name-asc");
  const [filtersOpen, setFiltersOpen] = React.useState(true);
  const [visiblePeople, setVisiblePeople] = React.useState([]);
  const [listPage, setListPage] = React.useState(1);
  const [listTotalPages, setListTotalPages] = React.useState(1);
  const [listTotalCount, setListTotalCount] = React.useState(initialPeople.length);
  const [listLoading, setListLoading] = React.useState(true);
  const [starredIds, setStarredIds] = React.useState(
    () => readVersionedIdSet(`om:starred-people:${companyId}`, STARRED_PEOPLE_STORAGE_VERSION)
  );
  const pendingPeopleChangeRef = React.useRef(false);
  const runWriteMutation = React.useCallback(
    async (operation, mutationPayload) => {
      if (!runGuardedMutation) {
        return operation();
      }
      return runGuardedMutation(operation, mutationPayload);
    },
    [runGuardedMutation]
  );
  const toggleStar = React.useCallback(
    (personId) => {
      setStarredIds((prev) => {
        const next = new Set(prev);
        if (next.has(personId)) next.delete(personId);
        else next.add(personId);
        writeVersionedIdSet(`om:starred-people:${companyId}`, STARRED_PEOPLE_STORAGE_VERSION, next);
        return next;
      });
    },
    [companyId]
  );
  const displayedPeople = React.useMemo(
    () => visiblePeople.length > 0 ? visiblePeople : people,
    [people, visiblePeople]
  );
  const totalLinkedPeople = listTotalCount > 0 ? listTotalCount : displayedPeople.length;
  const decisionMakerNames = React.useMemo(
    () => displayedPeople.filter((person) => starredIds.has(person.id)).map((person) => person.displayName),
    [displayedPeople, starredIds]
  );
  React.useEffect(() => {
    const action = {
      label: addActionLabel,
      onClick: () => {
        setCreateDialogOpen(true);
      }
    };
    onActionChange?.(action);
    return () => {
      onActionChange?.(null);
    };
  }, [addActionLabel, onActionChange]);
  React.useEffect(() => {
    pendingPeopleChangeRef.current = false;
    setPeople(initialPeople);
  }, [initialPeople]);
  React.useEffect(() => {
    if (!pendingPeopleChangeRef.current) return;
    pendingPeopleChangeRef.current = false;
    onPeopleChange?.(people);
  }, [onPeopleChange, people]);
  const loadVisiblePeople = React.useCallback(async () => {
    setListLoading(true);
    try {
      const params = new URLSearchParams({
        page: String(listPage),
        pageSize: String(COMPANY_PEOPLE_PAGE_SIZE),
        sort: sortMode
      });
      if (searchQuery.trim().length > 0) {
        params.set("search", searchQuery.trim());
      }
      const payload = await readApiResultOrThrow(
        `/api/customers/companies/${encodeURIComponent(companyId)}/people?${params.toString()}`,
        void 0,
        {
          errorMessage: translate(
            "customers.companies.detail.people.loadError",
            "Failed to load people."
          )
        }
      );
      const nextTotalCount = typeof payload.total === "number" ? payload.total : 0;
      setVisiblePeople(Array.isArray(payload.items) ? payload.items : []);
      setListPage(typeof payload.page === "number" ? payload.page : listPage);
      setListTotalCount(
        (current) => searchQuery.trim().length > 0 ? Math.max(current, nextTotalCount) : nextTotalCount
      );
      setListTotalPages(typeof payload.totalPages === "number" ? payload.totalPages : 1);
    } catch {
      setVisiblePeople([]);
      if (searchQuery.trim().length === 0) {
        setListTotalCount(0);
      }
      setListTotalPages(1);
    } finally {
      setListLoading(false);
    }
  }, [companyId, listPage, searchQuery, sortMode, translate]);
  React.useEffect(() => {
    void loadVisiblePeople();
  }, [loadVisiblePeople]);
  useAppEvent("customers.person_company_link.deleted", (event) => {
    const payload = event.payload;
    if (payload && payload.companyEntityId === companyId) {
      void loadVisiblePeople();
    }
  }, [companyId, loadVisiblePeople]);
  React.useEffect(() => {
    setListPage(1);
  }, [searchQuery, sortMode]);
  const applyPeopleChange = React.useCallback(
    (updater) => {
      setPeople((current) => {
        const next = updater(current);
        if (next !== current) {
          pendingPeopleChangeRef.current = true;
        }
        return next;
      });
    },
    []
  );
  const handleLinkConfirm = React.useCallback(
    async ({
      addedIds,
      optionsById
    }) => {
      if (!addedIds.length) return;
      onLoadingChange?.(true);
      try {
        for (const personId of addedIds) {
          await runWriteMutation(
            () => (
              // optimistic-lock-exempt: person-company link add/remove
              apiCallOrThrow(
                `/api/customers/people/${encodeURIComponent(personId)}/companies`,
                {
                  method: "POST",
                  headers: { "content-type": "application/json" },
                  body: JSON.stringify({ companyId })
                },
                {
                  errorMessage: translate(
                    "customers.companies.detail.people.linkError",
                    "Failed to link person to company."
                  )
                }
              )
            ),
            {
              personId,
              companyId
            }
          );
        }
        const optimisticPeople = addedIds.map((personId) => {
          const option = optionsById[personId];
          if (!option) return null;
          return {
            id: option.id,
            displayName: option.label,
            primaryEmail: null,
            primaryPhone: null,
            jobTitle: option.subtitle ?? null
          };
        }).filter((entry) => entry !== null);
        if (optimisticPeople.length > 0) {
          applyPeopleChange((current) => mergeCompanyPeople([...current, ...optimisticPeople]));
          setListTotalCount((current) => current + optimisticPeople.length);
        }
        await loadVisiblePeople();
        flash(
          addedIds.length === 1 ? translate(
            "customers.companies.detail.people.linkSuccess",
            "Person linked to company."
          ) : translate(
            "customers.companies.detail.people.linkSuccessMultiple",
            "{{count}} people linked to company.",
            { count: String(addedIds.length) }
          ),
          "success"
        );
      } catch (err) {
        try {
          await onDataRefresh?.();
        } catch {
        }
        const message = err instanceof Error ? err.message : translate(
          "customers.companies.detail.people.linkError",
          "Failed to link person to company."
        );
        flash(message, "error");
        throw err;
      } finally {
        onLoadingChange?.(false);
      }
    },
    [
      applyPeopleChange,
      companyId,
      loadVisiblePeople,
      onDataRefresh,
      onLoadingChange,
      runWriteMutation,
      translate
    ]
  );
  const personLinkAdapter = React.useMemo(
    () => createPersonLinkAdapter({
      dialogTitle: translate("customers.linking.person.dialogTitle", "Link person"),
      dialogSubtitle: companyName ? translate(
        "customers.linking.person.dialogSubtitleFor",
        "Link an existing contact to {{name}}",
        { name: companyName }
      ) : translate(
        "customers.linking.person.dialogSubtitle",
        "Link an existing contact to this company"
      ),
      sectionLabel: translate("customers.linking.person.sectionLabel", "MATCHING CONTACTS"),
      searchPlaceholder: translate(
        "customers.linking.person.searchPlaceholder",
        "Search all people\u2026"
      ),
      searchEmptyHint: translate(
        "customers.linking.person.searchEmpty",
        "No matching people found."
      ),
      selectedEmptyHint: translate(
        "customers.linking.person.selectedEmpty",
        "No people selected."
      ),
      confirmButtonLabel: translate("customers.linking.person.confirmButton", "Link person"),
      showLinkSettings: true,
      roleOptions: [
        { id: "decision_maker", label: "Decision maker" },
        { id: "budget_holder", label: "Budget holder" },
        { id: "stakeholder", label: "Stakeholder" },
        { id: "contact", label: "Contact" }
      ],
      excludeLinkedCompanyId: companyId,
      addNew: {
        title: translate("customers.linking.person.addNew", "Add new contact"),
        subtitle: translate(
          "customers.linking.person.addNewSubtitle",
          "Company will be filled in automatically"
        ),
        render: ({ onCancel }) => /* @__PURE__ */ jsx(
          CreatePersonDialog,
          {
            open: true,
            onClose: onCancel,
            companyId,
            companyName: companyName ?? companyId,
            runGuardedMutation: runWriteMutation,
            onPersonCreated: () => {
              void loadVisiblePeople();
              void onDataRefresh?.();
              setLinkDialogOpen(false);
              onCancel();
            }
          }
        )
      }
    }),
    [companyId, companyName, loadVisiblePeople, onDataRefresh, runWriteMutation, translate]
  );
  const handleRemove = React.useCallback(
    async (personId) => {
      if (!personId || removingId) return;
      setRemovingId(personId);
      onLoadingChange?.(true);
      try {
        await runWriteMutation(
          () => (
            // optimistic-lock-exempt: person-company link add/remove
            apiCallOrThrow(
              `/api/customers/people/${encodeURIComponent(personId)}/companies/${encodeURIComponent(companyId)}`,
              { method: "DELETE" },
              {
                errorMessage: translate(
                  "customers.companies.detail.people.removeError",
                  "Failed to unlink person from company."
                )
              }
            )
          ),
          {
            personId,
            companyId
          }
        );
        await loadVisiblePeople();
        flash(
          translate(
            "customers.companies.detail.people.removeSuccess",
            "Person unlinked from company."
          ),
          "success"
        );
      } catch (err) {
        const message = err instanceof Error ? err.message : translate(
          "customers.companies.detail.people.removeError",
          "Failed to unlink person from company."
        );
        flash(message, "error");
      } finally {
        setRemovingId(null);
        onLoadingChange?.(false);
      }
    },
    [
      companyId,
      loadVisiblePeople,
      onLoadingChange,
      removingId,
      runWriteMutation,
      translate
    ]
  );
  const linkAction = /* @__PURE__ */ jsxs(
    Button,
    {
      type: "button",
      variant: "outline",
      size: "sm",
      onClick: () => setLinkDialogOpen(true),
      children: [
        /* @__PURE__ */ jsx(Link2, { className: "mr-1.5 h-4 w-4" }),
        translate(
          "customers.companies.detail.people.linkAction",
          "Link existing person"
        )
      ]
    }
  );
  const addPersonAction = /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: () => setCreateDialogOpen(true), children: [
    /* @__PURE__ */ jsx(Plus, { className: "mr-1.5 h-4 w-4" }),
    addActionLabel
  ] });
  if (!listLoading && totalLinkedPeople === 0) {
    return /* @__PURE__ */ jsxs(Fragment, { children: [
      /* @__PURE__ */ jsxs(
        EmptyState,
        {
          icon: /* @__PURE__ */ jsx(Users, { className: "h-10 w-10 text-muted-foreground" }),
          title: emptyState.title,
          actionLabel: emptyState.actionLabel,
          onAction: () => setCreateDialogOpen(true),
          children: [
            /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyLabel }),
            /* @__PURE__ */ jsx("div", { className: "mt-4", children: linkAction })
          ]
        }
      ),
      /* @__PURE__ */ jsx(
        LinkEntityDialog,
        {
          open: linkDialogOpen,
          onOpenChange: setLinkDialogOpen,
          adapter: personLinkAdapter,
          initialSelectedIds: [],
          onConfirm: handleLinkConfirm,
          runGuardedMutation: runWriteMutation
        }
      ),
      /* @__PURE__ */ jsx(
        CreatePersonDialog,
        {
          open: createDialogOpen,
          onClose: () => setCreateDialogOpen(false),
          companyId,
          companyName: companyName ?? companyId,
          runGuardedMutation: runWriteMutation,
          onPersonCreated: () => {
            setCreateDialogOpen(false);
            void loadVisiblePeople();
            void onDataRefresh?.();
          }
        }
      )
    ] });
  }
  return /* @__PURE__ */ jsxs(Fragment, { children: [
    /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
      /* @__PURE__ */ jsx(
        RolesSection,
        {
          entityType: "company",
          entityId: companyId,
          entityName: companyName ?? null
        }
      ),
      /* @__PURE__ */ jsx("section", { className: "rounded-lg border bg-card px-4 py-4 sm:px-5", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
        /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 xl:flex-row xl:items-start xl:justify-between", children: [
          /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
            /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
              /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold", children: translate(
                "customers.companies.detail.people.sectionTitle",
                "People"
              ) }),
              /* @__PURE__ */ jsx(
                Badge,
                {
                  variant: "secondary",
                  className: "rounded-full px-2 py-0 text-xs font-semibold",
                  children: totalLinkedPeople
                }
              )
            ] }),
            /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: translate(
              "customers.companies.detail.people.sectionSubtitle",
              "Employees and decision makers on the client side"
            ) })
          ] }),
          /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 xl:justify-end", children: [
            linkAction,
            addPersonAction
          ] })
        ] }),
        totalLinkedPeople > 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-center", children: [
          filtersOpen ? /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
            "input",
            {
              type: "text",
              value: searchQuery,
              onChange: (event) => setSearchQuery(event.target.value),
              placeholder: translate(
                "customers.companies.detail.people.searchPlaceholder",
                "Search by name, role, email..."
              ),
              className: "h-10 w-full rounded-md border bg-background px-3 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring"
            }
          ) }) : null,
          /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 lg:justify-end", children: [
            /* @__PURE__ */ jsxs(
              Button,
              {
                type: "button",
                variant: "outline",
                size: "sm",
                onClick: () => setFiltersOpen((current) => !current),
                className: "h-10",
                children: [
                  /* @__PURE__ */ jsx(Filter, { className: "mr-1.5 h-4 w-4" }),
                  translate(
                    "customers.companies.detail.people.filter",
                    "Filters"
                  )
                ]
              }
            ),
            filtersOpen ? /* @__PURE__ */ jsxs(
              "select",
              {
                value: sortMode,
                onChange: (event) => setSortMode(event.target.value),
                className: "h-10 min-w-[11rem] rounded-md border bg-background px-3 text-sm focus:outline-none focus:ring-1 focus:ring-ring",
                children: [
                  /* @__PURE__ */ jsx("option", { value: "name-asc", children: translate(
                    "customers.companies.detail.people.sortNameAsc",
                    "Sort: Name A-Z"
                  ) }),
                  /* @__PURE__ */ jsx("option", { value: "name-desc", children: translate(
                    "customers.companies.detail.people.sortNameDesc",
                    "Sort: Name Z-A"
                  ) }),
                  /* @__PURE__ */ jsx("option", { value: "recent", children: translate(
                    "customers.companies.detail.people.sortRecent",
                    "Sort: Recently linked"
                  ) })
                ]
              }
            ) : null
          ] })
        ] }) : null,
        listLoading ? /* @__PURE__ */ jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: translate("customers.companies.detail.people.loading", "Loading people\u2026") }) : visiblePeople.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
          /* @__PURE__ */ jsx(
            "div",
            {
              className: "grid items-start gap-4",
              style: {
                gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 19.5rem), 1fr))"
              },
              children: visiblePeople.map((person) => /* @__PURE__ */ jsx(
                PersonCard,
                {
                  person,
                  isStarred: starredIds.has(person.id),
                  onToggleStar: toggleStar,
                  onUnlink: handleRemove
                },
                person.id
              ))
            }
          ),
          listTotalPages > 1 ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-border/60 pt-3 text-sm text-muted-foreground", children: [
            /* @__PURE__ */ jsx("span", { children: translate(
              "customers.companies.detail.people.pageSummary",
              "Page {{page}} of {{total}}",
              {
                page: listPage,
                total: listTotalPages
              }
            ) }),
            /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
              /* @__PURE__ */ jsx(
                Button,
                {
                  type: "button",
                  variant: "outline",
                  size: "sm",
                  onClick: () => setListPage((current) => Math.max(1, current - 1)),
                  disabled: listPage <= 1,
                  children: translate("customers.companies.detail.people.previous", "Previous")
                }
              ),
              /* @__PURE__ */ jsx(
                Button,
                {
                  type: "button",
                  variant: "outline",
                  size: "sm",
                  onClick: () => setListPage((current) => Math.min(listTotalPages, current + 1)),
                  disabled: listPage >= listTotalPages,
                  children: translate("customers.companies.detail.people.next", "Next")
                }
              )
            ] })
          ] }) : null
        ] }) : totalLinkedPeople > 0 ? /* @__PURE__ */ jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: translate(
          "customers.companies.detail.people.noSearchResults",
          "No people match your search."
        ) }) : null
      ] }) }),
      /* @__PURE__ */ jsx(
        DecisionMakersFooter,
        {
          names: decisionMakerNames,
          onSendInvitation: () => {
            const starredEmails = displayedPeople.filter((person) => starredIds.has(person.id) && person.primaryEmail).map((person) => person.primaryEmail);
            if (starredEmails.length > 0) {
              window.open(`mailto:${starredEmails.join(",")}`, "_blank");
            }
          }
        }
      )
    ] }),
    /* @__PURE__ */ jsx(
      LinkEntityDialog,
      {
        open: linkDialogOpen,
        onOpenChange: setLinkDialogOpen,
        adapter: personLinkAdapter,
        initialSelectedIds: [],
        onConfirm: handleLinkConfirm,
        runGuardedMutation: runWriteMutation
      }
    ),
    /* @__PURE__ */ jsx(
      CreatePersonDialog,
      {
        open: createDialogOpen,
        onClose: () => setCreateDialogOpen(false),
        companyId,
        companyName: companyName ?? companyId,
        runGuardedMutation: runWriteMutation,
        onPersonCreated: () => {
          setCreateDialogOpen(false);
          void loadVisiblePeople();
          void onDataRefresh?.();
        }
      }
    )
  ] });
}
var CompanyPeopleSection_default = CompanyPeopleSection;
export {
  CompanyPeopleSection,
  CompanyPeopleSection_default as default,
  matchesCompanyPersonSearch,
  mergeCompanyPeople,
  normalizeCompanyPerson,
  sortCompanyPeople
};
//# sourceMappingURL=CompanyPeopleSection.js.map
