"use client";

import { useCallback, useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { toast } from "sonner";
import { getApiErrorMessage } from "@/lib/api-error";
import { UserPlus, Trash2 } from "lucide-react";
import ClientWorkspaceLayout from "@/features/client/client-workspace-layout";
import {
  acceptPlatformInvitation,
  createPlatformUnit,
  fetchAssignableRoles,
  fetchMyPendingInvitations,
  fetchPlatformInvitations,
  fetchPlatformMembers,
  fetchPlatformUnits,
  invitePlatformMember,
  removePlatformMember,
  revokePlatformInvitation,
  updatePlatformMember,
  type AssignableRole,
  type PlatformInvitation,
  type PlatformMember,
  type PlatformUnit,
} from "@/platform/api/access-api";

function memberName(m: PlatformMember) {
  const u = m.userId;
  const full = [u.firstName, u.lastName].filter(Boolean).join(" ");
  return full || u.username || u.email;
}

function roleLabel(m: PlatformMember) {
  const a = m.roleAssignments?.[0];
  if (!a?.roleId) return "—";
  const scope =
    a.scope === "unit" ? ` (unit-scoped)` : "";
  return `${a.roleId.name}${scope}`;
}

export default function PlatformMembersAccess() {
  return (
    <ClientWorkspaceLayout title="Members & access">
      {(ctx) => (
        <MembersAccessPanel
          orgKey={
            ctx.tenantApiKey === "me"
              ? ctx.tenantClientId || ""
              : ctx.effectiveClientKey
          }
        />
      )}
    </ClientWorkspaceLayout>
  );
}

function MembersAccessPanel({ orgKey }: { orgKey: string }) {
  const [members, setMembers] = useState<PlatformMember[]>([]);
  const [units, setUnits] = useState<PlatformUnit[]>([]);
  const [invitations, setInvitations] = useState<PlatformInvitation[]>([]);
  const [roles, setRoles] = useState<AssignableRole[]>([]);
  const [loading, setLoading] = useState(true);
  const [inviteOpen, setInviteOpen] = useState(false);
  const [unitOpen, setUnitOpen] = useState(false);
  const [inviteEmail, setInviteEmail] = useState("");
  const [inviteRoleId, setInviteRoleId] = useState("");
  const [inviteScope, setInviteScope] = useState<"org" | "unit">("org");
  const [inviteUnitIds, setInviteUnitIds] = useState<string[]>([]);
  const [newUnitName, setNewUnitName] = useState("");
  const [saving, setSaving] = useState(false);

  const load = useCallback(async () => {
    if (!orgKey) return;
    setLoading(true);
    try {
      const [m, u, inv, r] = await Promise.all([
        fetchPlatformMembers(orgKey),
        fetchPlatformUnits(orgKey),
        fetchPlatformInvitations(orgKey),
        fetchAssignableRoles(orgKey),
      ]);
      setMembers(m);
      setUnits(u);
      setInvitations(inv);
      setRoles(r);
      if (!inviteRoleId && r[0]?._id) setInviteRoleId(r[0]._id);
    } catch (e) {
      toast.error(getApiErrorMessage(e, "Failed to load members"));
    } finally {
      setLoading(false);
    }
  }, [orgKey, inviteRoleId]);

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

  const sendInvite = async () => {
    if (!inviteEmail.trim()) {
      toast.error("Email is required");
      return;
    }
    try {
      setSaving(true);
      await invitePlatformMember(orgKey, {
        email: inviteEmail.trim(),
        roleId: inviteRoleId,
        scope: inviteScope,
        unitIds: inviteScope === "unit" ? inviteUnitIds : [],
      });
      toast.success("Invitation sent");
      setInviteOpen(false);
      setInviteEmail("");
      await load();
    } catch (e) {
      toast.error(getApiErrorMessage(e, "Could not send invitation"));
    } finally {
      setSaving(false);
    }
  };

  const addUnit = async () => {
    if (!newUnitName.trim()) return;
    try {
      setSaving(true);
      await createPlatformUnit(orgKey, newUnitName.trim());
      toast.success("Unit created");
      setUnitOpen(false);
      setNewUnitName("");
      await load();
    } catch (e) {
      toast.error(getApiErrorMessage(e, "Could not create unit"));
    } finally {
      setSaving(false);
    }
  };

  const changeMemberRole = async (membershipId: string, roleId: string, scope: "org" | "unit", unitIds: string[]) => {
    try {
      await updatePlatformMember(orgKey, membershipId, { roleId, scope, unitIds });
      toast.success("Member updated");
      await load();
    } catch (e) {
      toast.error(getApiErrorMessage(e, "Could not update member"));
    }
  };

  const removeMember = async (membershipId: string) => {
    if (!confirm("Remove this member from the organization?")) return;
    try {
      await removePlatformMember(orgKey, membershipId);
      toast.success("Member removed");
      await load();
    } catch (e) {
      toast.error(getApiErrorMessage(e, "Could not remove member"));
    }
  };

  if (loading) {
    return <p className="text-center text-gray-500 py-8">Loading members…</p>;
  }

  return (
    <div className="space-y-8">
      <div className="flex flex-wrap gap-2">
        <Button type="button" onClick={() => setInviteOpen(true)}>
          <UserPlus className="mr-2 size-4" />
          Invite member
        </Button>
        <Button type="button" variant="outline" onClick={() => setUnitOpen(true)}>
          Add unit
        </Button>
      </div>

      <section className="space-y-3">
        <h2 className="text-lg font-semibold">Units ({units.length})</h2>
        <div className="flex flex-wrap gap-2">
          {units.map((u) => (
            <span
              key={u._id}
              className="rounded-full border bg-white px-3 py-1 text-sm"
            >
              {u.name}
              {u.isDefault ? " (default)" : ""}
            </span>
          ))}
        </div>
      </section>

      <section className="space-y-3">
        <h2 className="text-lg font-semibold">Members</h2>
        <div className="rounded-md border bg-white">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Name</TableHead>
                <TableHead>Email</TableHead>
                <TableHead>Role & scope</TableHead>
                <TableHead>Status</TableHead>
                <TableHead className="w-[100px]" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {members.map((m) => (
                <TableRow key={m._id}>
                  <TableCell>{memberName(m)}</TableCell>
                  <TableCell>{m.userId.email}</TableCell>
                  <TableCell>
                    <div className="flex flex-col gap-2 sm:flex-row sm:items-center">
                      <span className="text-sm text-gray-600">{roleLabel(m)}</span>
                      <Select
                        value={m.roleAssignments?.[0]?.roleId?._id || ""}
                        onValueChange={(roleId) => {
                          const scope = m.roleAssignments?.[0]?.scope || "org";
                          const unitIds = m.roleAssignments?.[0]?.unitIds?.map(String) || [];
                          changeMemberRole(m._id, roleId, scope, unitIds);
                        }}
                      >
                        <SelectTrigger className="h-8 w-[160px]">
                          <SelectValue placeholder="Change role" />
                        </SelectTrigger>
                        <SelectContent>
                          {roles.map((r) => (
                            <SelectItem key={r._id} value={r._id}>
                              {r.name}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>
                  </TableCell>
                  <TableCell className="capitalize">{m.status}</TableCell>
                  <TableCell>
                    <Button
                      type="button"
                      variant="ghost"
                      size="icon"
                      onClick={() => removeMember(m._id)}
                      aria-label="Remove member"
                    >
                      <Trash2 className="size-4 text-red-600" />
                    </Button>
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </div>
      </section>

      <section className="space-y-3">
        <h2 className="text-lg font-semibold">Pending invitations</h2>
        {invitations.length === 0 ? (
          <p className="text-sm text-gray-500">No pending invitations.</p>
        ) : (
          <div className="rounded-md border bg-white">
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Email</TableHead>
                  <TableHead>Role</TableHead>
                  <TableHead>Scope</TableHead>
                  <TableHead />
                </TableRow>
              </TableHeader>
              <TableBody>
                {invitations.map((inv) => (
                  <TableRow key={inv._id}>
                    <TableCell>{inv.email}</TableCell>
                    <TableCell>{inv.roleId?.name || "—"}</TableCell>
                    <TableCell>{inv.scope === "unit" ? "Specific units" : "Organization"}</TableCell>
                    <TableCell>
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        onClick={async () => {
                          await revokePlatformInvitation(orgKey, inv._id);
                          toast.success("Invitation revoked");
                          await load();
                        }}
                      >
                        Revoke
                      </Button>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </div>
        )}
      </section>

      <Dialog open={inviteOpen} onOpenChange={setInviteOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Invite member</DialogTitle>
          </DialogHeader>
          <div className="grid gap-4 py-2">
            <div className="grid gap-2">
              <Label>Email</Label>
              <Input
                type="email"
                value={inviteEmail}
                onChange={(e) => setInviteEmail(e.target.value)}
                placeholder="colleague@company.com"
              />
            </div>
            <div className="grid gap-2">
              <Label>Role</Label>
              <Select value={inviteRoleId} onValueChange={setInviteRoleId}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {roles.map((r) => (
                    <SelectItem key={r._id} value={r._id}>
                      {r.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="grid gap-2">
              <Label>Access scope</Label>
              <Select
                value={inviteScope}
                onValueChange={(v) => setInviteScope(v as "org" | "unit")}
              >
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="org">Entire organization</SelectItem>
                  <SelectItem value="unit">Specific units only</SelectItem>
                </SelectContent>
              </Select>
            </div>
            {inviteScope === "unit" ? (
              <div className="grid gap-2">
                <Label>Units</Label>
                <div className="flex flex-wrap gap-2">
                  {units.map((u) => {
                    const checked = inviteUnitIds.includes(u._id);
                    return (
                      <button
                        key={u._id}
                        type="button"
                        className={`rounded border px-2 py-1 text-sm ${checked ? "border-primary bg-primary/10" : ""}`}
                        onClick={() =>
                          setInviteUnitIds((ids) =>
                            checked ? ids.filter((id) => id !== u._id) : [...ids, u._id],
                          )
                        }
                      >
                        {u.name}
                      </button>
                    );
                  })}
                </div>
              </div>
            ) : null}
          </div>
          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => setInviteOpen(false)}>
              Cancel
            </Button>
            <Button type="button" onClick={sendInvite} disabled={saving}>
              {saving ? "Sending…" : "Send invitation"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={unitOpen} onOpenChange={setUnitOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Add unit</DialogTitle>
          </DialogHeader>
          <div className="grid gap-2 py-2">
            <Label>Name</Label>
            <Input
              value={newUnitName}
              onChange={(e) => setNewUnitName(e.target.value)}
              placeholder="Plant 2, Branch Lahore, …"
            />
          </div>
          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => setUnitOpen(false)}>
              Cancel
            </Button>
            <Button type="button" onClick={addUnit} disabled={saving}>
              Create
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

export function PendingInvitationsBanner() {
  const [items, setItems] = useState<
    Array<PlatformInvitation & { organizationId?: { name?: string; clientId?: string } }>
  >([]);

  useEffect(() => {
    fetchMyPendingInvitations()
      .then(setItems)
      .catch(() => setItems([]));
  }, []);

  if (!items.length) return null;

  return (
    <div className="mb-4 rounded-md border border-blue-200 bg-blue-50 p-4 text-sm">
      <p className="font-medium text-blue-900">You have pending organization invitations</p>
      <ul className="mt-2 space-y-2">
        {items.map((inv) => (
          <li key={inv._id} className="flex flex-wrap items-center justify-between gap-2">
            <span>
              {inv.organizationId?.name || "Organization"} — {inv.roleId?.name || "Member"}
            </span>
            <AcceptInviteButton tokenHint={inv._id} />
          </li>
        ))}
      </ul>
    </div>
  );
}

function AcceptInviteButton({ tokenHint }: { tokenHint: string }) {
  return (
    <Button
      type="button"
      size="sm"
      variant="secondary"
      onClick={() => toast.info("Open the link in your invitation email to accept.")}
    >
      Accept
    </Button>
  );
}

export { acceptPlatformInvitation };
