"use client";

// ============================================================
// Team Management — a CRM people + roles module, redesigned as
// a creative "crew" experience.
//   · Crew hero  : avatar stack, live presence, headline stats
//   · Members    : people gallery (cards) ⇄ compact list, with
//                  role filter chips, search, MULTI-role chips,
//                  deal-load meters and row actions
//   · Roles      : permission-coverage rings + live toggle matrix
//   · Invites    : envelope timeline with resend / revoke
// Data comes from useTeamData(): the local mock when the Shell
// isn't configured, or the live be-crm data door (crm.team.*)
// when it is. A member can hold MANY roles.
// ============================================================

import { useEffect, useMemo, useState } from "react";
import {
  Avatar, Btn, Field, Icon, Modal, Pill, StatusDot, Toggle, useToast,
} from "./ui";
import { permissionGroups, allPermissionIds } from "./team-data";
import { useTeamData, type UiMember, type UiRole, type UiStatus } from "@/lib/team-api";

const STATUS_LABEL: Record<UiStatus, string> = { active: "Active", away: "Away", offline: "Offline" };
const toDot = (s: UiStatus) => (s === "offline" ? "offline" : s === "away" ? "away" : "online");
const EMAIL_RE = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;

export function TeamManagement() {
  const toast = useToast();
  const team = useTeamData();
  const { members, roles, invites, live } = team;

  const [tab, setTab] = useState("members");
  const [view, setView] = useState<"grid" | "list">("grid");
  const [query, setQuery] = useState("");
  const [roleFilter, setRoleFilter] = useState("all");
  const [inviteOpen, setInviteOpen] = useState(false);
  const [editing, setEditing] = useState<UiMember | null>(null);
  const [confirmRemove, setConfirmRemove] = useState<UiMember | null>(null);

  const roleById = useMemo(() => Object.fromEntries(roles.map((r) => [r.id, r])), [roles]);
  const assignableRoles = useMemo(() => roles.filter((r) => !r.isOwner), [roles]);
  const countByRole = useMemo(() => {
    const m: Record<string, number> = {};
    for (const mem of members) for (const rid of mem.roleIds) m[rid] = (m[rid] ?? 0) + 1;
    return m;
  }, [members]);
  const maxDeals = useMemo(() => Math.max(1, ...members.map((m) => m.deals)), [members]);

  const filtered = useMemo(() => {
    const q = query.trim().toLowerCase();
    return members.filter((m) => {
      const matchRole = roleFilter === "all" || m.roleIds.includes(roleFilter);
      const matchQ = !q || m.name.toLowerCase().includes(q) || m.email.toLowerCase().includes(q) || m.title.toLowerCase().includes(q);
      return matchRole && matchQ;
    });
  }, [members, query, roleFilter]);

  const activeCount = members.filter((m) => m.status === "active").length;

  /* ---- mutations (async; live → data door, mock → local) ---- */
  async function saveRoles(m: UiMember, roleIds: string[]) {
    try {
      await team.setMemberRoles(m.id, roleIds);
      toast.push({ tone: "success", title: "Roles updated", desc: `${m.name} now holds ${roleIds.length} role${roleIds.length === 1 ? "" : "s"}.` });
    } catch (e) { toast.push({ tone: "error", title: "Couldn't update roles", desc: (e as Error).message }); }
  }
  async function removeMember(m: UiMember) {
    setConfirmRemove(null);
    try { await team.removeMember(m.id); toast.push({ tone: "info", title: "Member removed", desc: `${m.name} no longer has access.` }); }
    catch (e) { toast.push({ tone: "error", title: "Couldn't remove member", desc: (e as Error).message }); }
  }
  async function togglePerm(roleId: string, permId: string, granted: boolean) {
    try { await team.setPermission(roleId, permId, granted); }
    catch (e) { toast.push({ tone: "error", title: "Couldn't update permission", desc: (e as Error).message }); }
  }

  // Crew stack — show online folks first, capped to 6 with a +N bubble.
  const stack = [...members].sort((a, b) => Number(b.status === "active") - Number(a.status === "active"));
  const stackShown = stack.slice(0, 6);
  const stackRest = members.length - stackShown.length;

  return (
    <div className="view tm">
      {/* ---- Crew hero ---------------------------------------- */}
      <header className="tm-hero">
        <div className="tm-hero-orbs" aria-hidden />
        <div className="tm-hero-grid" aria-hidden />
        <div className="tm-hero-main">
          <div className="tm-stack" aria-hidden>
            {stackShown.map((m, i) => (
              <span key={m.id} className="tm-stack-av" style={{ zIndex: stackShown.length - i }}>
                <Avatar initials={m.initials} gradient={m.gradient} size={46} status={toDot(m.status)} />
              </span>
            ))}
            {stackRest > 0 && <span className="tm-stack-more">+{stackRest}</span>}
          </div>
          <div className="tm-hero-copy">
            <div className="tm-hero-eyebrow">
              <Icon name="team" size={13} /> Your crew · LynkedUp Pro
              {live && <Pill tone="green" style={{ marginLeft: 8 }}>Live</Pill>}
            </div>
            <h1>Team Management</h1>
            <p>Manage your crew, assign roles and control exactly what each person can do.</p>
            <div className="tm-hero-live">
              <span className="tm-pulse" /><b>{activeCount}</b> online now
              <span className="tm-hero-dot" /> {members.length} members
              <span className="tm-hero-dot" /> {invites.length} invites pending
            </div>
          </div>
        </div>
        <div className="tm-hero-actions">
          <Btn icon="plus" onClick={() => setInviteOpen(true)}>Invite member</Btn>
        </div>
      </header>

      {/* ---- Tabs --------------------------------------------- */}
      <div className="tm-tabs" role="tablist">
        {[
          { value: "members", label: "Members", icon: "people", badge: members.length },
          { value: "roles", label: "Roles & Permissions", icon: "shield", badge: roles.length },
          { value: "invites", label: "Invites", icon: "mail", badge: invites.length },
        ].map((t) => (
          <button key={t.value} role="tab" aria-selected={tab === t.value} className={`tm-tab ${tab === t.value ? "active" : ""}`} onClick={() => setTab(t.value)}>
            <Icon name={t.icon} size={16} /> <span>{t.label}</span>
            <span className="tm-tab-badge">{t.badge}</span>
          </button>
        ))}
      </div>

      {team.error && <div className="card tm-empty" style={{ borderColor: "var(--red, #ef4444)" }}><p>Couldn&apos;t load team data: {team.error}</p></div>}

      {/* ---- MEMBERS ------------------------------------------ */}
      {tab === "members" && (
        <div className="view-body">
          <div className="tm-toolbar">
            <div className="tm-search">
              <Icon name="search" size={16} />
              <input className="ds-input flush" placeholder="Search by name, email or title…" value={query} onChange={(e) => setQuery(e.target.value)} />
              {query && <button className="tm-search-x" aria-label="Clear" onClick={() => setQuery("")}><Icon name="x" size={14} /></button>}
            </div>
            <div className="tm-viewtoggle" role="group" aria-label="Layout">
              <button className={view === "grid" ? "on" : ""} aria-label="Gallery view" onClick={() => setView("grid")}><Icon name="subtasks" size={15} /></button>
              <button className={view === "list" ? "on" : ""} aria-label="List view" onClick={() => setView("list")}><Icon name="leaderboard" size={15} /></button>
            </div>
          </div>

          {/* Role filter chips */}
          <div className="tm-chips">
            <button className={`tm-chip ${roleFilter === "all" ? "on" : ""}`} onClick={() => setRoleFilter("all")}>
              <span className="tm-chip-dot" style={{ background: "var(--text-2)" }} /> All <i>{members.length}</i>
            </button>
            {roles.filter((r) => (countByRole[r.id] ?? 0) > 0).map((r) => (
              <button key={r.id} className={`tm-chip ${roleFilter === r.id ? "on" : ""}`} style={{ ["--rc" as string]: r.color }} onClick={() => setRoleFilter(r.id)}>
                <span className="tm-chip-dot" style={{ background: r.color }} /> {r.name} <i>{countByRole[r.id] ?? 0}</i>
              </button>
            ))}
          </div>

          {team.live && team.loading && members.length === 0 ? (
            <div className="card tm-empty"><span className="tm-empty-ic"><Icon name="people" size={24} /></span><p>Loading your crew…</p></div>
          ) : filtered.length === 0 ? (
            <div className="card tm-empty"><span className="tm-empty-ic"><Icon name="search" size={24} /></span><p>No members match your search.</p><Btn variant="soft" size="sm" onClick={() => { setQuery(""); setRoleFilter("all"); }}>Clear filters</Btn></div>
          ) : view === "grid" ? (
            <div className="tm-gallery">
              {filtered.map((m) => (
                <article className="card tm-pcard" key={m.id} style={{ ["--rc" as string]: roleById[m.roleIds[0]]?.color }}>
                  <span className="tm-pcard-bg" aria-hidden />
                  <div className="tm-pcard-top">
                    <span className="tm-pcard-av"><Avatar initials={m.initials} gradient={m.gradient} size={58} status={toDot(m.status)} /></span>
                    <RowMenu disabled={m.isOwner} onEdit={() => setEditing(m)} onRemove={() => setConfirmRemove(m)} />
                  </div>
                  <div className="tm-pcard-name">{m.name}{m.isOwner && <span className="tm-crown" title="Account owner"><Icon name="star" size={13} /></span>}</div>
                  <div className="tm-pcard-title">{m.title || <span className="tm-dash">No title</span>}</div>
                  <div className="tm-pcard-email"><Icon name="mail" size={12} /> {m.email}</div>

                  <div className="tm-pcard-role">
                    <RoleChips roleIds={m.roleIds} roleById={roleById} />
                  </div>

                  <div className="tm-meter" title={`${m.deals} open deals`}>
                    <div className="tm-meter-h"><span>Deal load</span><b>{m.deals}</b></div>
                    <span className="tm-meter-track"><span className="tm-meter-fill" style={{ width: `${Math.round((m.deals / maxDeals) * 100)}%` }} /></span>
                  </div>

                  <div className="tm-pcard-foot">
                    <span className="tm-statuscell"><StatusDot status={toDot(m.status)} /> {STATUS_LABEL[m.status]}</span>
                    <span className="tm-lastactive">{m.lastActive}</span>
                  </div>
                </article>
              ))}
            </div>
          ) : (
            <div className="card card-pad-0 tm-table">
              <div className="tm-row tm-head">
                <span>Member</span><span>Roles</span><span>Status</span><span className="tm-c-num">Open deals</span><span className="tm-c-act" />
              </div>
              {filtered.map((m) => (
                <div className="tm-row" key={m.id}>
                  <div className="tm-member">
                    <Avatar initials={m.initials} gradient={m.gradient} size={40} status={toDot(m.status)} />
                    <div className="tm-member-meta">
                      <div className="tm-name">{m.name}{m.isYou && <Pill tone="orange" style={{ marginLeft: 8 }}>You{m.isOwner ? " · Owner" : ""}</Pill>}</div>
                      <div className="tm-sub">{m.title ? `${m.title} · ` : ""}{m.email}</div>
                    </div>
                  </div>
                  <div className="tm-rolecell"><RoleChips roleIds={m.roleIds} roleById={roleById} /></div>
                  <div className="tm-statuscell">
                    <StatusDot status={toDot(m.status)} /><span>{STATUS_LABEL[m.status]}</span>
                    <span className="tm-lastactive">{m.lastActive}</span>
                  </div>
                  <div className="tm-c-num">{m.deals > 0 ? <b>{m.deals}</b> : <span className="tm-dash">—</span>}</div>
                  <div className="tm-c-act"><RowMenu disabled={m.isOwner} onEdit={() => setEditing(m)} onRemove={() => setConfirmRemove(m)} /></div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* ---- ROLES -------------------------------------------- */}
      {tab === "roles" && (
        <div className="view-body tm-roles">
          {roles.map((r) => {
            const pct = Math.round((r.perms.length / allPermissionIds.length) * 100);
            return (
              <div className="card tm-rolecard" key={r.id} style={{ ["--rc" as string]: r.color }}>
                <div className="tm-rolecard-head">
                  <span className="tm-ring" style={{ ["--pct" as string]: pct }}>
                    <span className="tm-ring-in"><Icon name={r.isOwner ? "star" : r.system ? "shield-check" : "shield"} size={17} /></span>
                  </span>
                  <div className="tm-rolecard-title">
                    <div className="tm-rolecard-name">{r.name}{r.system && <Pill tone="muted" style={{ marginLeft: 8 }}>System</Pill>}</div>
                    <div className="tm-rolecard-sub">{countByRole[r.id] ?? 0} {(countByRole[r.id] ?? 0) === 1 ? "member" : "members"} · {r.perms.length}/{allPermissionIds.length} permissions</div>
                  </div>
                </div>
                {r.description && <p className="tm-rolecard-desc">{r.description}</p>}

                {r.attire.length > 0 && (
                  <div className="tm-attire">
                    <div className="tm-attire-h"><Icon name="user" size={13} /> Attire &amp; appearance</div>
                    <ul className="tm-attire-list">
                      {r.attire.map((a) => (<li key={a}><span className="tm-attire-dot" />{a}</li>))}
                    </ul>
                  </div>
                )}

                {r.overlap && (
                  <div className="tm-overlap">
                    <span className="tm-overlap-ic"><Icon name="info" size={14} /></span>
                    <div><b>Common overlap</b><p>{r.overlap}</p></div>
                  </div>
                )}

                <div className="tm-permlist">
                  {permissionGroups.map((g) => (
                    <div className="tm-permgroup" key={g.id}>
                      <div className="tm-permgroup-h"><Icon name={g.icon} size={13} /> {g.title}</div>
                      {g.perms.map((p) => {
                        const granted = r.perms.includes(p.id);
                        const locked = r.isOwner;
                        return (
                          <div className={`tm-perm ${granted ? "on" : ""}`} key={p.id}>
                            <div className="tm-perm-meta">
                              <span className="tm-perm-label">{p.label}</span>
                              <span className="tm-perm-desc">{p.desc}</span>
                            </div>
                            <Toggle checked={granted} disabled={locked} onChange={() => togglePerm(r.id, p.id, !granted)} label={p.label} />
                          </div>
                        );
                      })}
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {/* ---- INVITES ------------------------------------------ */}
      {tab === "invites" && (
        <div className="view-body card card-pad-0">
          <div className="tm-invite-head">
            <div>
              <h3>Pending invitations</h3>
              <p>People you&apos;ve invited who haven&apos;t joined yet.</p>
            </div>
            <Btn icon="plus" size="sm" onClick={() => setInviteOpen(true)}>New invite</Btn>
          </div>
          {invites.length === 0 ? (
            <div className="tm-empty"><span className="tm-empty-ic"><Icon name="mail" size={24} /></span><p>No pending invites. Everyone&apos;s on board.</p></div>
          ) : (
            <div className="tm-invites">
              {invites.map((inv) => (
                <div className="tm-inviterow" key={inv.id}>
                  <span className="tm-invite-ic"><Icon name="mail" size={16} /></span>
                  <div className="tm-invite-meta">
                    <div className="tm-name">{inv.email}</div>
                    <div className="tm-sub">Invited by {inv.invitedBy} · {inv.sentAt}</div>
                  </div>
                  <RoleChips roleIds={inv.roleIds} roleById={roleById} />
                  <div className="tm-invite-actions">
                    {inv.token && (
                      <Btn variant="soft" size="sm" icon="copy" onClick={async () => {
                        const link = `${window.location.origin}/portal/invite?token=${inv.token}`;
                        try { await navigator.clipboard.writeText(link); toast.push({ tone: "success", title: "Invite link copied", desc: `Send it to ${inv.email} to join.` }); }
                        catch { toast.push({ tone: "info", title: "Invite link", desc: link }); }
                      }}>Copy link</Btn>
                    )}
                    <Btn variant="soft" size="sm" icon="refresh" onClick={async () => {
                      try { await team.resendInvite(inv.id); toast.push({ tone: "success", title: "Invite resent", desc: `A fresh link was sent to ${inv.email}.` }); }
                      catch (e) { toast.push({ tone: "error", title: "Couldn't resend", desc: (e as Error).message }); }
                    }}>Resend</Btn>
                    <Btn variant="ghost" size="sm" icon="x" onClick={async () => {
                      try { await team.revokeInvite(inv.id); toast.push({ tone: "info", title: "Invite revoked" }); }
                      catch (e) { toast.push({ tone: "error", title: "Couldn't revoke", desc: (e as Error).message }); }
                    }}>Revoke</Btn>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      <InviteModal
        open={inviteOpen}
        roles={assignableRoles}
        onClose={() => setInviteOpen(false)}
        onInvite={async (email, roleIds) => {
          setInviteOpen(false);
          try {
            await team.invite(email, roleIds);
            setTab("invites");
            toast.push({ tone: "success", title: "Invitation sent", desc: `${email} was invited with ${roleIds.length} role${roleIds.length === 1 ? "" : "s"}.` });
          } catch (e) { toast.push({ tone: "error", title: "Couldn't send invite", desc: (e as Error).message }); }
        }}
      />

      <EditMemberModal
        member={editing}
        roles={assignableRoles}
        onClose={() => setEditing(null)}
        onSave={async (id, title, roleIds) => {
          const m = editing;
          setEditing(null);
          if (!m) return;
          try {
            await team.updateMember(id, { title, roleIds });
            toast.push({ tone: "success", title: "Member updated" });
          } catch (e) { toast.push({ tone: "error", title: "Couldn't update member", desc: (e as Error).message }); }
        }}
      />

      <Modal
        open={!!confirmRemove}
        onClose={() => setConfirmRemove(null)}
        title="Remove member"
        subtitle={confirmRemove ? `${confirmRemove.name} will lose access immediately.` : ""}
        icon="alert"
        size="sm"
        footer={
          <>
            <Btn variant="ghost" onClick={() => setConfirmRemove(null)}>Cancel</Btn>
            <Btn variant="danger" icon="trash" onClick={() => confirmRemove && removeMember(confirmRemove)}>Remove member</Btn>
          </>
        }
      >
        <p className="tm-confirm-text">Their open deals and assignments stay in the workspace and can be reassigned afterwards. This action can be undone by re-inviting them.</p>
      </Modal>
    </div>
  );
}

/* ---------------------------------------------------------- */
/* Role chips — show every role a member/invite holds          */
/* ---------------------------------------------------------- */

function RoleChips({ roleIds, roleById }: { roleIds: string[]; roleById: Record<string, UiRole> }) {
  if (roleIds.length === 0) return <span className="tm-dash">No role</span>;
  return (
    <span className="tm-rolechips">
      {roleIds.map((rid) => {
        const role = roleById[rid];
        return (
          <span className="tm-rolebadge" style={{ ["--rc" as string]: role?.color }} key={rid}>
            <Icon name={role?.isOwner ? "star" : "shield"} size={12} /> {role?.name ?? rid}
          </span>
        );
      })}
    </span>
  );
}

/* ---------------------------------------------------------- */
/* Row actions menu                                            */
/* ---------------------------------------------------------- */

function RowMenu({ onEdit, onRemove, disabled }: { onEdit: () => void; onRemove: () => void; disabled?: boolean }) {
  const [open, setOpen] = useState(false);
  if (disabled) return <span className="tm-menu-lock" title="The owner can't be edited"><Icon name="lock" size={15} /></span>;
  return (
    <div className="tm-menu">
      <button className="ds-iconbtn" aria-label="Member actions" onClick={() => setOpen((o) => !o)}><Icon name="dots" size={18} /></button>
      {open && (
        <>
          <div className="tm-menu-scrim" onClick={() => setOpen(false)} />
          <div className="tm-menu-pop" role="menu">
            <button onClick={() => { setOpen(false); onEdit(); }}><Icon name="edit" size={15} /> Edit member</button>
            <button onClick={() => { setOpen(false); onEdit(); }}><Icon name="shield" size={15} /> Change roles</button>
            <div className="tm-menu-sep" />
            <button className="danger" onClick={() => { setOpen(false); onRemove(); }}><Icon name="trash" size={15} /> Remove</button>
          </div>
        </>
      )}
    </div>
  );
}

/* ---------------------------------------------------------- */
/* Multi-role picker — checkbox chips, ≥1 required             */
/* ---------------------------------------------------------- */

function RolePicker({ roles, selected, onToggle }: { roles: UiRole[]; selected: string[]; onToggle: (id: string) => void }) {
  return (
    <div className="tm-rolepicker">
      {roles.map((r) => {
        const on = selected.includes(r.id);
        return (
          <button type="button" key={r.id} className={`tm-rolepick ${on ? "on" : ""}`} style={{ ["--rc" as string]: r.color }} onClick={() => onToggle(r.id)} aria-pressed={on}>
            <span className="tm-rolepick-check">{on && <Icon name="check" size={12} />}</span>
            <span className="tm-roledot" /> {r.name}
          </button>
        );
      })}
    </div>
  );
}

/* ---------------------------------------------------------- */
/* Invite modal                                                */
/* ---------------------------------------------------------- */

function InviteModal({ open, roles, onClose, onInvite }: { open: boolean; roles: UiRole[]; onClose: () => void; onInvite: (email: string, roleIds: string[]) => void }) {
  const [email, setEmail] = useState("");
  const [roleIds, setRoleIds] = useState<string[]>([]);
  const valid = EMAIL_RE.test(email.trim()) && roleIds.length > 0;

  function toggle(id: string) { setRoleIds((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id])); }
  function submit() { if (!valid) return; onInvite(email.trim(), roleIds); setEmail(""); setRoleIds([]); }

  return (
    <Modal
      open={open}
      onClose={onClose}
      title="Invite a team member"
      subtitle="They'll get an email with a secure link to set up their account."
      icon="people"
      footer={
        <>
          <Btn variant="ghost" onClick={onClose}>Cancel</Btn>
          <Btn icon="send" disabled={!valid} onClick={submit}>Send invitation</Btn>
        </>
      }
    >
      <div className="tm-form">
        <Field label="Work email" required hint={email && !EMAIL_RE.test(email.trim()) ? undefined : "We'll send the invite here."} error={email && !EMAIL_RE.test(email.trim()) ? "Enter a valid email address." : undefined}>
          <input className="ds-input" type="email" placeholder="name@company.com" value={email} onChange={(e) => setEmail(e.target.value)} />
        </Field>
        <Field label="Assign roles" required hint="Pick one or more. Roles decide what this person can see and do.">
          <RolePicker roles={roles} selected={roleIds} onToggle={toggle} />
        </Field>
      </div>
    </Modal>
  );
}

/* ---------------------------------------------------------- */
/* Edit member modal — job title + multi-role                  */
/* ---------------------------------------------------------- */

function EditMemberModal({ member, roles, onClose, onSave }: { member: UiMember | null; roles: UiRole[]; onClose: () => void; onSave: (id: string, title: string, roleIds: string[]) => void }) {
  const [title, setTitle] = useState("");
  const [roleIds, setRoleIds] = useState<string[]>([]);

  const key = member?.id ?? "";
  useEffect(() => { if (member) { setTitle(member.title); setRoleIds(member.roleIds); } }, [key]); // eslint-disable-line react-hooks/exhaustive-deps

  if (!member) return null;
  const valid = roleIds.length > 0;
  function toggle(id: string) { setRoleIds((s) => (s.includes(id) ? s.filter((x) => x !== id) : [...s, id])); }

  return (
    <Modal
      open={!!member}
      onClose={onClose}
      title={`Edit ${member.name}`}
      subtitle={member.email}
      icon="edit"
      footer={
        <>
          <Btn variant="ghost" onClick={onClose}>Cancel</Btn>
          <Btn icon="check" disabled={!valid} onClick={() => onSave(member.id, title, roleIds)}>Save changes</Btn>
        </>
      }
    >
      <div className="tm-form">
        <div className="tm-edit-hero">
          <Avatar initials={member.initials} gradient={member.gradient} size={52} />
          <div>
            <div className="tm-name">{member.name}</div>
            <div className="tm-sub">Joined {member.joined} · {member.deals} open deals</div>
          </div>
        </div>
        <Field label="Job title">
          <input className="ds-input" value={title} onChange={(e) => setTitle(e.target.value)} placeholder="e.g. Senior Sales Rep" />
        </Field>
        <Field label="Roles" required hint="A member can hold several roles — permissions are the union of all of them.">
          <RolePicker roles={roles} selected={roleIds} onToggle={toggle} />
        </Field>
      </div>
    </Modal>
  );
}
