"use client";

import { useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api, type InstanceUser, type Role } from "@/lib/api";
import { useAuth } from "@/components/AuthProvider";
import { Badge, Button, Modal, Table, Tbody, Td, Th, Thead, Tr } from "@/components/ui";
import { Field, inputClass } from "./Field";
import { SectionCard } from "./SectionCard";

const ROLES: Role[] = ["owner", "admin", "member"];

function UsersIcon() {
    return (
        <svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
            <path
                strokeLinecap="round"
                strokeLinejoin="round"
                d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z"
            />
        </svg>
    );
}

function roleVariant(role: Role) {
    if (role === "owner") return "accent" as const;
    if (role === "admin") return "warning" as const;
    return "neutral" as const;
}

export function MembersCard() {
    const queryClient = useQueryClient();
    const { user } = useAuth();
    const [addOpen, setAddOpen] = useState(false);
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [role, setRole] = useState<Role>("member");

    const { data: users, isLoading, error } = useQuery({ queryKey: ["instance-users"], queryFn: api.listInstanceUsers });

    const invalidate = () => queryClient.invalidateQueries({ queryKey: ["instance-users"] });

    const {
        mutate: createUser,
        isPending: creating,
        error: createError,
    } = useMutation({
        mutationFn: () => api.createInstanceUser({ email, password, role }),
        onSuccess: () => {
            invalidate();
            setAddOpen(false);
            setEmail("");
            setPassword("");
            setRole("member");
        },
    });

    const { mutate: changeRole, error: roleError } = useMutation({
        mutationFn: ({ userId, next }: { userId: string; next: Role }) => api.updateInstanceUserRole(userId, next),
        onSuccess: invalidate,
        // Refetch on failure too, so a rejected change does not leave the select
        // showing a role the server never accepted.
        onError: invalidate,
    });

    const { mutate: removeUser, error: removeError } = useMutation({
        mutationFn: (userId: string) => api.deleteInstanceUser(userId),
        onSuccess: invalidate,
    });

    const actionError = (roleError ?? removeError) as Error | null;

    const isOwner = user?.role === "owner";
    const assignableRoles = isOwner ? ROLES : ROLES.filter((r) => r !== "owner");
    const hqUrl = process.env.NEXT_PUBLIC_HQ_URL ?? "";

    return (
        <SectionCard
            title="Members"
            description="People with access to this instance. Owners and admins can manage settings."
            icon={<UsersIcon />}
            actions={
                <Button variant="primary" size="sm" onClick={() => setAddOpen(true)}>
                    Add member
                </Button>
            }
        >
            {actionError && <div className="mb-4 rounded border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{actionError.message}</div>}

            {isLoading ? (
                <div className="flex justify-center py-8">
                    <div className="h-6 w-6 animate-spin rounded-full border-2 border-border border-t-accent" />
                </div>
            ) : error ? (
                <p className="py-6 text-sm text-danger">{(error as Error).message}</p>
            ) : !users || users.length === 0 ? (
                <p className="py-6 text-sm text-text-secondary">No members yet.</p>
            ) : (
                <Table>
                    <Thead>
                        <Tr>
                            <Th>Email</Th>
                            <Th>Role</Th>
                            <Th>Sign-in</Th>
                            <Th>Last login</Th>
                            <Th className="text-right">Actions</Th>
                        </Tr>
                    </Thead>
                    <Tbody>
                        {users.map((u: InstanceUser) => {
                            const isSelf = u.user_id === user?.user_id;
                            const managedByHQ = u.auth_source === "hq";
                            // Locked here is a courtesy: the API returns 409 for an hq-sourced
                            // role change or deletion whether or not this select is rendered.
                            const locked = isSelf || managedByHQ || (u.role === "owner" && !isOwner);
                            return (
                                <Tr key={u.user_id}>
                                    <Td label="Email">
                                        <span className="font-medium">{u.email}</span>
                                        {isSelf && <span className="ml-2 text-xs text-text-tertiary">(you)</span>}
                                    </Td>
                                    <Td label="Role">
                                        {locked ? (
                                            <Badge variant={roleVariant(u.role)}>{u.role}</Badge>
                                        ) : (
                                            <select
                                                value={u.role}
                                                onChange={(e) => changeRole({ userId: u.user_id, next: e.target.value as Role })}
                                                className="rounded border border-border bg-surface-2 px-2 py-1 text-sm text-text-primary focus:border-accent/50 focus:outline-none"
                                            >
                                                {assignableRoles.map((r) => (
                                                    <option key={r} value={r}>
                                                        {r}
                                                    </option>
                                                ))}
                                            </select>
                                        )}
                                    </Td>
                                    <Td label="Sign-in">
                                        <Badge variant="neutral">{u.auth_source === "oidc" ? "SSO" : u.auth_source === "hq" ? "Vantage HQ" : "Password"}</Badge>
                                    </Td>
                                    <Td label="Last login" className="text-text-secondary">{u.last_login ? new Date(u.last_login).toLocaleString() : "Never"}</Td>
                                    <Td label="Actions" className="text-right">
                                        {managedByHQ ? (
                                            hqUrl ? (
                                                <a href={hqUrl} target="_blank" rel="noreferrer" className="text-xs text-text-secondary underline">
                                                    Managed in Vantage HQ
                                                </a>
                                            ) : (
                                                <span className="text-xs text-text-tertiary">Managed in Vantage HQ</span>
                                            )
                                        ) : (
                                            !locked && (
                                                <Button
                                                    variant="ghost"
                                                    size="sm"
                                                    onClick={() => {
                                                        if (confirm(`Remove ${u.email} from this instance?`)) removeUser(u.user_id);
                                                    }}
                                                >
                                                    Remove
                                                </Button>
                                            )
                                        )}
                                    </Td>
                                </Tr>
                            );
                        })}
                    </Tbody>
                </Table>
            )}

            <Modal open={addOpen} title="Add member" onClose={() => setAddOpen(false)}>
                <form
                    onSubmit={(e) => {
                        e.preventDefault();
                        createUser();
                    }}
                    className="space-y-4"
                >
                    <Field label="Email">
                        <input type="email" required value={email} onChange={(e) => setEmail(e.target.value)} className={inputClass} />
                    </Field>

                    <Field label="Password" hint="Leave blank if this member will sign in through SSO instead.">
                        <input type="password" autoComplete="new-password" value={password} onChange={(e) => setPassword(e.target.value)} className={inputClass} />
                    </Field>

                    <Field label="Role">
                        <select value={role} onChange={(e) => setRole(e.target.value as Role)} className={inputClass}>
                            {assignableRoles.map((r) => (
                                <option key={r} value={r}>
                                    {r}
                                </option>
                            ))}
                        </select>
                    </Field>

                    {createError && <div className="rounded border border-danger/30 bg-danger/10 px-3 py-2 text-sm text-danger">{(createError as Error).message}</div>}

                    <div className="flex justify-end gap-2">
                        <Button type="button" variant="ghost" onClick={() => setAddOpen(false)}>
                            Cancel
                        </Button>
                        <Button type="submit" variant="primary" loading={creating}>
                            Add member
                        </Button>
                    </div>
                </form>
            </Modal>
        </SectionCard>
    );
}
