"use client";

/**
 * Settings → Team
 * ───────────────
 * Org-scoped member list with per-member Brand Access editor + seat-
 * limit-aware invite flow. Reads from /api/organizations/members
 * (now returns brandAccess[] per row) and writes role + brand-access
 * via PATCH. Seat usage vs plan limit surfaces in the header and
 * gates the Invite button when the cap is hit.
 */

import { useState, useEffect, useCallback, useMemo } from "react";
import { useBrand } from "@/context/brand-context";
import { usePlan, usePlanContext } from "@/context/plan-context";
import {
  Users, UserPlus, Shield, Loader2, Check, AlertCircle, X, Mail, Pencil, Building2,
} from "lucide-react";
import { PLANS } from "@/lib/plan-config";

interface Member {
  id: string;
  role: string;
  joinedAt: string;
  user: { id: string; name: string | null; email: string; image: string | null };
  brandAccess: string[]; // brandIds with explicit grants
}

interface BrandOption { id: string; name: string; domain: string }

export default function TeamTab() {
  const { orgId, brands } = useBrand();
  const { plan } = usePlan();
  const { openUpgrade } = usePlanContext();
  const [members, setMembers] = useState<Member[]>([]);
  const [loading, setLoading] = useState(true);

  const [inviteOpen, setInviteOpen] = useState(false);
  const [inviteEmail, setInviteEmail] = useState("");
  const [inviteRole, setInviteRole] = useState("member");
  const [inviteBrandIds, setInviteBrandIds] = useState<Set<string>>(new Set());
  const [inviting, setInviting] = useState(false);
  const [inviteError, setInviteError] = useState<string | null>(null);
  const [inviteSuccess, setInviteSuccess] = useState(false);

  const [editing, setEditing] = useState<Member | null>(null);

  const brandOptions: BrandOption[] = useMemo(
    () => brands.map((b) => ({ id: b.id, name: b.name, domain: b.domain })),
    [brands],
  );

  const loadMembers = useCallback(async () => {
    if (!orgId) return;
    setLoading(true);
    try {
      const res = await fetch(`/api/organizations/members?orgId=${orgId}`);
      if (res.ok) setMembers(await res.json());
    } finally { setLoading(false); }
  }, [orgId]);

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

  // Seat headroom — compared against the current effective plan.
  const seatLimit = plan?.limits.seats ?? 2;
  const seatsUsed = members.length;
  const seatsUnlimited = seatLimit === "unlimited";
  const atSeatCap = !seatsUnlimited && typeof seatLimit === "number" && seatsUsed >= seatLimit;

  async function handleInvite() {
    if (!inviteEmail.trim() || !orgId || inviting) return;
    if (atSeatCap) {
      openUpgrade({ kind: "manual" });
      return;
    }
    setInviting(true); setInviteError(null); setInviteSuccess(false);
    try {
      const res = await fetch("/api/organizations/members", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          orgId,
          email: inviteEmail.trim().toLowerCase(),
          role: inviteRole,
          // Members only — owners/admins see everything by role.
          brandIds: inviteRole === "member" ? Array.from(inviteBrandIds) : undefined,
        }),
      });
      if (res.ok) {
        setInviteSuccess(true);
        setInviteEmail("");
        setInviteRole("member");
        setInviteBrandIds(new Set());
        await loadMembers();
        setTimeout(() => { setInviteSuccess(false); setInviteOpen(false); }, 1500);
      } else {
        const d = await res.json().catch(() => ({}));
        if (d.error === "upgrade_required") {
          openUpgrade({ kind: "manual" });
        } else {
          setInviteError(d.error || "Invite failed");
        }
      }
    } catch { setInviteError("Network error"); }
    setInviting(false);
  }

  async function saveMember(
    userId: string,
    updates: { role?: string; brandIds?: string[] },
  ) {
    if (!orgId) return;
    const res = await fetch("/api/organizations/members", {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ orgId, userId, ...updates }),
    });
    if (res.ok) { setEditing(null); await loadMembers(); }
  }

  if (loading) {
    return <div className="flex items-center justify-center py-16"><Loader2 className="w-5 h-5 text-slate-400 animate-spin" /></div>;
  }

  return (
    <div className="space-y-6">
      {/* Member list */}
      <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
        <div className="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
          <div className="flex items-center gap-2">
            <Users className="w-4 h-4 text-brand-600" />
            <h2 className="font-bold text-slate-800 text-sm">
              Team Members ({seatsUsed}{seatsUnlimited ? "" : ` of ${seatLimit}`})
            </h2>
            {atSeatCap && (
              <span className="ml-2 text-[10px] font-bold uppercase tracking-wider text-red-600 bg-red-50 px-1.5 py-0.5 rounded">
                Seat cap reached
              </span>
            )}
          </div>
          <button
            onClick={() => (atSeatCap ? openUpgrade({ kind: "manual" }) : setInviteOpen(!inviteOpen))}
            title={atSeatCap ? "You're at your plan's seat limit — upgrade for more." : undefined}
            className="flex items-center gap-1.5 px-3 py-1.5 bg-brand-600 text-white text-xs font-semibold rounded-lg hover:bg-brand-700"
          >
            <UserPlus className="w-3.5 h-3.5" /> {atSeatCap ? "Upgrade for more seats" : "Invite"}
          </button>
        </div>

        {members.length === 0 ? (
          <div className="px-6 py-8 text-center text-xs text-slate-400">No team members yet.</div>
        ) : (
          <div className="divide-y divide-slate-100">
            {members.map((m) => {
              const isImplicitAll = m.role === "owner" || m.role === "admin";
              const accessLabel = isImplicitAll
                ? "All brands"
                : m.brandAccess.length === 0
                  ? "No brands"
                  : m.brandAccess.length === 1
                    ? brandOptions.find((b) => b.id === m.brandAccess[0])?.name ?? "1 brand"
                    : `${m.brandAccess.length} brands`;
              return (
                <div key={m.id} className="px-6 py-3 flex items-center gap-3">
                  <div className="w-8 h-8 rounded-full bg-brand-100 flex items-center justify-center text-brand-700 font-bold text-xs shrink-0">
                    {(m.user.name?.[0] || m.user.email[0] || "?").toUpperCase()}
                  </div>
                  <div className="flex-1 min-w-0">
                    <p className="text-sm font-semibold text-slate-900 truncate">{m.user.name || "Unnamed"}</p>
                    <p className="text-xs text-slate-500 truncate">{m.user.email}</p>
                  </div>
                  <span
                    className="hidden md:inline-flex items-center gap-1 text-[10px] font-semibold text-slate-600 bg-slate-50 border border-slate-200 rounded-full px-2 py-0.5"
                    title={isImplicitAll ? "Full access via role" : accessLabel}
                  >
                    <Building2 className="w-2.5 h-2.5" /> {accessLabel}
                  </span>
                  <span className={`flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider rounded-full px-2 py-0.5 ${
                    m.role === "owner" ? "bg-amber-50 text-amber-700" :
                    m.role === "admin" ? "bg-brand-50 text-brand-700" :
                    "bg-slate-100 text-slate-600"
                  }`}>
                    <Shield className="w-2.5 h-2.5" /> {m.role}
                  </span>
                  {/* Owners can't be edited via this tab — a proper
                      owner-transfer UI belongs in Workspace settings. */}
                  {m.role !== "owner" && (
                    <button
                      onClick={() => setEditing(m)}
                      className="w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:bg-slate-100 hover:text-brand-600"
                      title="Edit access"
                    >
                      <Pencil className="w-3 h-3" />
                    </button>
                  )}
                </div>
              );
            })}
          </div>
        )}
      </div>

      {/* Invite form */}
      {inviteOpen && (
        <div className="bg-white rounded-xl border border-slate-200 px-6 py-5">
          <div className="flex items-center justify-between mb-3">
            <h3 className="text-sm font-bold text-slate-800">Invite Team Member</h3>
            <button onClick={() => setInviteOpen(false)} className="text-slate-400 hover:text-slate-600">
              <X className="w-4 h-4" />
            </button>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-12 gap-3">
            <div className="md:col-span-6">
              <label className="block text-[11px] font-semibold text-slate-600 mb-1">Email Address</label>
              <div className="relative">
                <Mail className="w-3.5 h-3.5 text-slate-400 absolute left-3 top-1/2 -translate-y-1/2" />
                <input
                  value={inviteEmail}
                  onChange={(e) => { setInviteEmail(e.target.value); setInviteError(null); }}
                  onKeyDown={(e) => e.key === "Enter" && handleInvite()}
                  placeholder="colleague@company.com"
                  className="w-full pl-9 pr-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500/40"
                />
              </div>
            </div>
            <div className="md:col-span-3">
              <label className="block text-[11px] font-semibold text-slate-600 mb-1">Role</label>
              <select
                value={inviteRole}
                onChange={(e) => setInviteRole(e.target.value)}
                className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg bg-white"
              >
                <option value="member">Member</option>
                <option value="admin">Admin</option>
                <option value="viewer">Viewer</option>
              </select>
            </div>
            <div className="md:col-span-3 flex items-end">
              <button
                onClick={handleInvite}
                disabled={inviting || !inviteEmail.trim()}
                className="w-full flex items-center justify-center gap-1.5 px-4 py-2 bg-brand-600 text-white text-xs font-semibold rounded-lg hover:bg-brand-700 disabled:opacity-50"
              >
                {inviting ? <Loader2 className="w-3.5 h-3.5 animate-spin" />
                  : inviteSuccess ? <Check className="w-3.5 h-3.5" />
                  : <UserPlus className="w-3.5 h-3.5" />}
                {inviting ? "Inviting…" : inviteSuccess ? "Added!" : "Add to Team"}
              </button>
            </div>
          </div>

          {/* Per-brand access — members only. Admins/Owners see
              everything via their org role so the checkboxes would
              just be noise. */}
          {inviteRole === "member" && brandOptions.length > 0 && (
            <div className="mt-4">
              <p className="text-[11px] font-semibold text-slate-600 mb-1.5">Brand Access</p>
              <div className="grid grid-cols-2 gap-1.5">
                {brandOptions.map((b) => (
                  <label key={b.id} className="flex items-center gap-2 px-2.5 py-1.5 rounded-lg border border-slate-200 cursor-pointer hover:bg-slate-50">
                    <input
                      type="checkbox"
                      checked={inviteBrandIds.has(b.id)}
                      onChange={() => {
                        setInviteBrandIds((prev) => {
                          const next = new Set(prev);
                          next.has(b.id) ? next.delete(b.id) : next.add(b.id);
                          return next;
                        });
                      }}
                      className="rounded"
                    />
                    <span className="text-xs font-medium text-slate-700 truncate">{b.name}</span>
                    <span className="text-[10px] text-slate-400 ml-auto">{b.domain}</span>
                  </label>
                ))}
              </div>
              <p className="text-[10px] text-slate-400 mt-1.5">
                Members only see brands checked here. Admins see every brand in the workspace.
              </p>
            </div>
          )}

          {inviteError && (
            <div className="mt-3 flex items-center gap-2 text-xs text-red-600">
              <AlertCircle className="w-3.5 h-3.5 shrink-0" /> {inviteError}
            </div>
          )}
        </div>
      )}

      {/* Edit-access modal */}
      {editing && (
        <EditMemberModal
          member={editing}
          brandOptions={brandOptions}
          onCancel={() => setEditing(null)}
          onSave={(updates) => saveMember(editing.user.id, updates)}
        />
      )}

      {/* Upgrade hint when at seat cap + trial note */}
      {atSeatCap && plan && (
        <div className="flex items-start gap-3 rounded-xl border border-amber-200 bg-amber-50 px-5 py-4">
          <AlertCircle className="w-4 h-4 text-amber-600 mt-0.5 shrink-0" />
          <div>
            <p className="text-sm font-semibold text-amber-900">Seat limit reached</p>
            <p className="text-xs text-amber-700 mt-0.5">
              You&apos;re using {seatsUsed} of {seatLimit} seats on {PLANS[plan.effectivePlan]?.name}.
              Upgrade for more seats or add a seat at $15–$29/mo depending on plan.
            </p>
            <button
              onClick={() => openUpgrade({ kind: "manual" })}
              className="inline-flex items-center gap-1 text-xs font-semibold text-brand-600 mt-2 hover:underline"
            >
              Upgrade plan →
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

// ─── Edit-access modal ────────────────────────────────────────────

function EditMemberModal({
  member, brandOptions, onCancel, onSave,
}: {
  member: Member;
  brandOptions: BrandOption[];
  onCancel: () => void;
  onSave: (updates: { role?: string; brandIds?: string[] }) => void;
}) {
  const [role, setRole] = useState(member.role);
  const [brandIds, setBrandIds] = useState<Set<string>>(new Set(member.brandAccess));
  const [allBrands, setAllBrands] = useState<boolean>(
    role === "owner" || role === "admin" || member.brandAccess.length === brandOptions.length,
  );

  // When role flips to admin/owner, implicit all-brands kicks in so
  // the per-brand list greys out.
  const isImplicitAll = role === "owner" || role === "admin";

  function toggleBrand(id: string) {
    setBrandIds((prev) => {
      const next = new Set(prev);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  }

  function save() {
    const updates: { role?: string; brandIds?: string[] } = {};
    if (role !== member.role) updates.role = role;
    if (!isImplicitAll) {
      // Member/viewer: explicit set. "All brands" toggle expands to
      // every brand id so the replacement list reflects it.
      updates.brandIds = allBrands ? brandOptions.map((b) => b.id) : Array.from(brandIds);
    } else {
      // Promoting to admin/owner clears explicit grants so the Team
      // tab's Access column reads "All brands" instead of a stale
      // subset.
      updates.brandIds = [];
    }
    onSave(updates);
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-900/60 p-4" onClick={onCancel}>
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-md max-h-[90vh] flex flex-col overflow-hidden" onClick={(e) => e.stopPropagation()}>
        <header className="px-5 py-4 border-b border-slate-200 flex items-center justify-between">
          <div>
            <h2 className="font-bold text-slate-900 text-sm">Edit member</h2>
            <p className="text-xs text-slate-500 mt-0.5">{member.user.email}</p>
          </div>
          <button onClick={onCancel} className="p-1.5 rounded-lg hover:bg-slate-100 text-slate-500">
            <X className="w-4 h-4" />
          </button>
        </header>

        <div className="flex-1 overflow-auto p-5 space-y-4">
          <div>
            <label className="block text-[11px] font-semibold text-slate-600 mb-1">Role</label>
            <select
              value={role}
              onChange={(e) => setRole(e.target.value)}
              className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg bg-white"
            >
              {/* Don't expose "owner" in the picker — ownership
                  transfer is a Workspace-level flow with stronger
                  guardrails. Prior owner role is preserved if it
                  was the starting value (but unreachable here). */}
              <option value="admin">Admin — see all brands</option>
              <option value="member">Member — see selected brands</option>
              <option value="viewer">Viewer — read-only selected brands</option>
            </select>
          </div>

          <div>
            <div className="flex items-center justify-between mb-1.5">
              <label className="text-[11px] font-semibold text-slate-600">Brand Access</label>
              {!isImplicitAll && (
                <label className="flex items-center gap-1.5 text-[11px] text-slate-600 cursor-pointer">
                  <input
                    type="checkbox"
                    checked={allBrands}
                    onChange={() => setAllBrands((v) => !v)}
                    className="rounded"
                  />
                  All brands (current + future)
                </label>
              )}
            </div>
            {isImplicitAll ? (
              <div className="rounded-lg border border-slate-200 bg-slate-50 px-3 py-3 text-xs text-slate-500">
                {role === "admin" ? "Admins" : "Owners"} see every brand in the workspace — per-brand grants don&apos;t apply.
              </div>
            ) : (
              <div className={`grid grid-cols-1 gap-1 max-h-56 overflow-auto ${allBrands ? "opacity-50 pointer-events-none" : ""}`}>
                {brandOptions.map((b) => (
                  <label key={b.id} className="flex items-center gap-2 px-2.5 py-1.5 rounded-lg border border-slate-200 cursor-pointer hover:bg-slate-50">
                    <input
                      type="checkbox"
                      checked={allBrands || brandIds.has(b.id)}
                      onChange={() => toggleBrand(b.id)}
                      disabled={allBrands}
                      className="rounded"
                    />
                    <span className="text-xs font-medium text-slate-700 flex-1 truncate">{b.name}</span>
                    <span className="text-[10px] text-slate-400">{b.domain}</span>
                  </label>
                ))}
              </div>
            )}
          </div>
        </div>

        <footer className="flex items-center justify-end gap-2 px-5 py-3 border-t border-slate-200 bg-slate-50">
          <button onClick={onCancel} className="px-4 py-2 text-xs font-semibold text-slate-600">Cancel</button>
          <button onClick={save} className="px-4 py-2 bg-brand-600 text-white text-xs font-semibold rounded-lg hover:bg-brand-700">
            Save
          </button>
        </footer>
      </div>
    </div>
  );
}
