"use client";

import * as React from "react";
import { toast } from "sonner";
import { useSession } from "next-auth/react";
import {
  Loader2,
  Plus,
  UserPlus,
  Shield,
  Trash2,
  Mail,
  RotateCw,
  Clock,
  AlertTriangle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { isAdminRole } from "@/lib/permissions";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  CardDescription,
} from "@/components/ui/card";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";

type Member = {
  id: string;
  role: string;
  user: { id: string; email: string; displayName: string | null };
};

type Invitation = {
  id: string;
  email: string;
  role: string;
  expiresAt: string;
  acceptedAt: string | null;
};

const ROLES = [
  { value: "viewer", label: "Viewer" },
  { value: "reviewer", label: "Reviewer" },
  { value: "editor", label: "Editor" },
  { value: "admin", label: "Admin" },
];

export default function UsersSettingsPage() {
  const { data: session } = useSession();
  const [members, setMembers] = React.useState<Member[]>([]);
  const [invitations, setInvitations] = React.useState<Invitation[]>([]);
  const [loading, setLoading] = React.useState(true);
  const [inviteEmail, setInviteEmail] = React.useState("");
  const [inviteRole, setInviteRole] = React.useState("viewer");
  const [sending, setSending] = React.useState(false);
  const [updatingRole, setUpdatingRole] = React.useState<string | null>(null);
  const [removingId, setRemovingId] = React.useState<string | null>(null);
  const [resendingId, setResendingId] = React.useState<string | null>(null);
  const [revokingId, setRevokingId] = React.useState<string | null>(null);

  const fetchData = React.useCallback(async () => {
    try {
      const [membersRes, invitesRes] = await Promise.all([
        fetch("/api/org/members"),
        fetch("/api/org/invitations"),
      ]);
      if (membersRes.ok) {
        const data = await membersRes.json();
        setMembers(data.members || []);
      }
      if (invitesRes.ok) {
        const data = await invitesRes.json();
        setInvitations(data.invitations || []);
      }
    } catch {} finally {
      setLoading(false);
    }
  }, []);

  React.useEffect(() => {
    fetchData();
  }, [fetchData]);

  const myMembership = members.find((m) => m.user.id === session?.user?.id);
  const isAdmin = isAdminRole(myMembership?.role);

  const handleInvite = async (e: React.FormEvent) => {
    e.preventDefault();
    setSending(true);
    try {
      const res = await fetch("/api/org/invitations", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: inviteEmail, role: inviteRole }),
      });
      if (res.ok) {
        toast.success(`Invitation sent to ${inviteEmail}`);
        setInviteEmail("");
        fetchData();
      } else {
        const data = await res.json();
        toast.error(data.error || "Failed to send invitation");
      }
    } catch {
      toast.error("Failed to send invitation");
    } finally {
      setSending(false);
    }
  };

  const handleRoleChange = async (memberId: string, newRole: string) => {
    setUpdatingRole(memberId);
    try {
      const res = await fetch(`/api/org/members/${memberId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ role: newRole }),
      });
      if (res.ok) {
        setMembers((prev) =>
          prev.map((m) => (m.id === memberId ? { ...m, role: newRole } : m))
        );
        toast.success("Role updated");
      } else {
        const data = await res.json();
        toast.error(data.error || "Failed to update role");
      }
    } catch {
      toast.error("Failed to update role");
    } finally {
      setUpdatingRole(null);
    }
  };

  const handleRemoveMember = async (member: Member) => {
    setRemovingId(member.id);
    try {
      const res = await fetch(`/api/org/members/${member.id}`, {
        method: "DELETE",
      });
      if (res.ok) {
        setMembers((prev) => prev.filter((m) => m.id !== member.id));
        toast.success(`${member.user.displayName || member.user.email} removed`);
      } else {
        const data = await res.json();
        toast.error(data.error || "Failed to remove member");
      }
    } catch {
      toast.error("Failed to remove member");
    } finally {
      setRemovingId(null);
    }
  };

  const handleResendInvite = async (invite: Invitation) => {
    setResendingId(invite.id);
    try {
      const res = await fetch(`/api/org/invitations/${invite.id}`, {
        method: "POST",
      });
      if (res.ok) {
        toast.success(`Invitation resent to ${invite.email}`);
        fetchData();
      } else {
        const data = await res.json();
        toast.error(data.error || "Failed to resend invitation");
      }
    } catch {
      toast.error("Failed to resend invitation");
    } finally {
      setResendingId(null);
    }
  };

  const handleRevokeInvite = async (invite: Invitation) => {
    setRevokingId(invite.id);
    try {
      const res = await fetch(`/api/org/invitations/${invite.id}`, {
        method: "DELETE",
      });
      if (res.ok) {
        setInvitations((prev) => prev.filter((i) => i.id !== invite.id));
        toast.success("Invitation revoked");
      } else {
        const data = await res.json();
        toast.error(data.error || "Failed to revoke invitation");
      }
    } catch {
      toast.error("Failed to revoke invitation");
    } finally {
      setRevokingId(null);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 className="size-6 animate-spin text-muted-foreground" />
      </div>
    );
  }

  const pendingInvitations = invitations.filter((i) => !i.acceptedAt);

  return (
    <div className="space-y-6">
      {/* Invite */}
      {isAdmin && (
        <Card className="glass-card">
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <UserPlus className="size-4" />
              Invite Team Member
            </CardTitle>
          </CardHeader>
          <CardContent>
            <form onSubmit={handleInvite} className="flex flex-wrap items-end gap-3">
              <div className="min-w-[200px] flex-1 space-y-1.5">
                <Label className="text-xs">Email</Label>
                <Input
                  type="email"
                  value={inviteEmail}
                  onChange={(e) => setInviteEmail(e.target.value)}
                  placeholder="colleague@church.org"
                  required
                />
              </div>
              <div className="w-36 space-y-1.5">
                <Label className="text-xs">Role</Label>
                <Select value={inviteRole} onValueChange={(v) => v && setInviteRole(v)}>
                  <SelectTrigger>
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {ROLES.map((r) => (
                      <SelectItem key={r.value} value={r.value}>
                        {r.label}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </div>
              <Button type="submit" disabled={sending}>
                {sending ? (
                  <Loader2 className="mr-1.5 size-3.5 animate-spin" />
                ) : (
                  <Plus className="mr-1.5 size-3.5" />
                )}
                Send Invite
              </Button>
            </form>
          </CardContent>
        </Card>
      )}

      {/* Current Members */}
      <Card className="glass-card">
        <CardHeader>
          <CardTitle className="flex items-center gap-2 text-base">
            <Shield className="size-4" />
            Team Members
          </CardTitle>
          <CardDescription>
            {members.length} member{members.length !== 1 && "s"}
          </CardDescription>
        </CardHeader>
        <CardContent>
          <div className="space-y-2">
            {members.map((m) => {
              const isMe = m.user.id === session?.user?.id;
              const isOwner = m.role === "owner";
              const canEdit = isAdmin && !isMe && !isOwner;

              return (
                <div
                  key={m.id}
                  className="flex items-center justify-between gap-3 rounded-lg border border-border/50 px-4 py-3"
                >
                  <div className="min-w-0 flex-1">
                    <p className="truncate text-sm font-medium">
                      {m.user.displayName || m.user.email}
                    </p>
                    <p className="truncate text-xs text-muted-foreground">
                      {m.user.email}
                    </p>
                  </div>

                  <div className="flex shrink-0 items-center gap-2">
                    {canEdit ? (
                      <Select
                        value={m.role}
                        onValueChange={(v) => v && handleRoleChange(m.id, v)}
                        disabled={updatingRole === m.id}
                      >
                        <SelectTrigger className="w-28">
                          <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                          {ROLES.map((r) => (
                            <SelectItem key={r.value} value={r.value}>
                              {r.label}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    ) : (
                      <Badge variant="outline" className="text-xs capitalize">
                        {m.role}
                      </Badge>
                    )}

                    {isMe && (
                      <Badge variant="secondary" className="text-xs">
                        You
                      </Badge>
                    )}

                    {canEdit && (
                      <Button
                        variant="ghost"
                        size="icon-sm"
                        className="text-muted-foreground hover:text-destructive"
                        onClick={() => handleRemoveMember(m)}
                        disabled={removingId === m.id}
                        aria-label={`Remove ${m.user.displayName || m.user.email}`}
                      >
                        {removingId === m.id ? (
                          <Loader2 className="size-3.5 animate-spin" />
                        ) : (
                          <Trash2 className="size-3.5" />
                        )}
                      </Button>
                    )}
                  </div>
                </div>
              );
            })}
            {members.length === 0 && (
              <p className="py-4 text-center text-sm text-muted-foreground">
                No team members yet — send an invitation above.
              </p>
            )}
          </div>
        </CardContent>
      </Card>

      {/* Pending Invitations */}
      {pendingInvitations.length > 0 && (
        <Card className="glass-card">
          <CardHeader>
            <CardTitle className="flex items-center gap-2 text-base">
              <Mail className="size-4" />
              Pending Invitations
            </CardTitle>
            <CardDescription>
              {pendingInvitations.length} pending
            </CardDescription>
          </CardHeader>
          <CardContent>
            <div className="space-y-2">
              {pendingInvitations.map((i) => {
                const isExpired = new Date(i.expiresAt) < new Date();

                return (
                  <div
                    key={i.id}
                    className="flex items-center justify-between gap-3 rounded-lg border border-border/50 px-4 py-3"
                  >
                    <div className="min-w-0 flex-1">
                      <p className="truncate text-sm font-medium">{i.email}</p>
                      <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
                        {isExpired ? (
                          <>
                            <AlertTriangle className="size-3 text-amber-500" />
                            <span className="text-amber-600 dark:text-amber-400">Expired</span>
                          </>
                        ) : (
                          <>
                            <Clock className="size-3" />
                            <span>
                              Expires{" "}
                              {new Date(i.expiresAt).toLocaleDateString()}
                            </span>
                          </>
                        )}
                      </div>
                    </div>

                    <div className="flex shrink-0 items-center gap-2">
                      <Badge variant="outline" className="text-xs capitalize">
                        {i.role}
                      </Badge>

                      {isAdmin && (
                        <>
                          <Button
                            variant="ghost"
                            size="icon-sm"
                            className="text-muted-foreground hover:text-primary"
                            onClick={() => handleResendInvite(i)}
                            disabled={resendingId === i.id}
                            aria-label={`Resend invitation to ${i.email}`}
                          >
                            {resendingId === i.id ? (
                              <Loader2 className="size-3.5 animate-spin" />
                            ) : (
                              <RotateCw className="size-3.5" />
                            )}
                          </Button>
                          <Button
                            variant="ghost"
                            size="icon-sm"
                            className="text-muted-foreground hover:text-destructive"
                            onClick={() => handleRevokeInvite(i)}
                            disabled={revokingId === i.id}
                            aria-label={`Revoke invitation for ${i.email}`}
                          >
                            {revokingId === i.id ? (
                              <Loader2 className="size-3.5 animate-spin" />
                            ) : (
                              <Trash2 className="size-3.5" />
                            )}
                          </Button>
                        </>
                      )}
                    </div>
                  </div>
                );
              })}
            </div>
          </CardContent>
        </Card>
      )}
    </div>
  );
}
