import { useMemo, useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Crown, Mail, MoreHorizontal, Pencil, Search, Shield, ShieldCheck, Trash2, UserCheck, UserPlus, Users, X } from 'lucide-react';
import { toast } from 'sonner';
import {
  Button,
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
  Input,
  Label,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
  cn,
  createEntity,
  deleteEntity,
  updateEntity,
  type CockpitEntity,
  type EntityRow,
} from '@ump/shared';
import { ENTITIES, asStr } from './cockpitConfig';
import { EntityDrawer, StatusBadge } from './CockpitWidgets';

// Status vocabulary (the research_project_members.status values from cockpitConfig).
const STATUS = { active: 'Đang hoạt động', pending: 'Chờ xác nhận', paused: 'Tạm dừng' } as const;
const memberField = (key: string) => ENTITIES.members.fields.find((f) => f.key === key);
const ROLE_OPTIONS = memberField('role')?.options ?? [];
const ACCESS_OPTIONS = memberField('access')?.options ?? [];
const validEmail = (e: string) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);

const AVATAR_COLORS = ['bg-rose-500', 'bg-emerald-500', 'bg-sky-500', 'bg-violet-500', 'bg-amber-500', 'bg-teal-500'];
function avatar(seed: string): { initials: string; color: string } {
  const s = seed.trim() || '?';
  const parts = s.split(/\s+/).filter(Boolean);
  const initials = (parts.length >= 2 ? parts[0][0] + parts[parts.length - 1][0] : s.slice(0, 2)).toUpperCase();
  let h = 0;
  for (let i = 0; i < s.length; i += 1) h = (h * 31 + s.charCodeAt(i)) >>> 0;
  return { initials, color: AVATAR_COLORS[h % AVATAR_COLORS.length] };
}

/** "PI" access (Chủ nhiệm) gets the crown; everyone else a shield. */
const isPiAccess = (access: string) => /Chủ nhiệm|PI/i.test(access);

const TABS: Array<{ key: keyof typeof STATUS; label: string }> = [
  { key: 'active', label: 'Đang hoạt động' },
  { key: 'pending', label: 'Chờ xác nhận' },
  { key: 'paused', label: 'Tạm dừng' },
];

/**
 * Team-management view for a research project (cockpit "Thành viên" tab) — TeamManagement.jsx
 * reskinned to the UMP system. FE-only over the existing research_project_members entity CRUD:
 * invite = a member row with status "Chờ xác nhận"; RBAC = the `access` field; who-can-edit is
 * gated by canEdit (project owner / admin). No schema/backend change.
 */
export function TeamManagementView({
  members,
  projectId,
  canEdit,
}: {
  members: EntityRow[];
  projectId: string;
  canEdit: boolean;
}) {
  const qc = useQueryClient();
  const [tab, setTab] = useState<keyof typeof STATUS>('active');
  const [query, setQuery] = useState('');
  const [inviteOpen, setInviteOpen] = useState(false);
  const [editing, setEditing] = useState<EntityRow | null>(null);
  const [draft, setDraft] = useState<Record<string, string>>({});

  const invalidate = () => qc.invalidateQueries({ queryKey: ['cockpit', projectId] });
  const saveMut = useMutation({
    mutationFn: (vars: { id?: string; data: Record<string, string> }) =>
      vars.id
        ? updateEntity(projectId, 'members' as CockpitEntity, vars.id, vars.data)
        : createEntity(projectId, 'members' as CockpitEntity, vars.data),
    onSuccess: () => invalidate(),
    onError: (e: unknown) => toast.error((e as { message?: string })?.message || 'Lưu thất bại'),
  });
  const delMut = useMutation({
    mutationFn: (itemId: string) => deleteEntity(projectId, 'members' as CockpitEntity, itemId),
    onSuccess: () => invalidate(),
    onError: () => toast.error('Xóa thất bại'),
  });
  const patch = (id: string, data: Record<string, string>) => saveMut.mutate({ id, data });

  const counts = useMemo(() => {
    const c = { active: 0, pending: 0, paused: 0 } as Record<keyof typeof STATUS, number>;
    for (const m of members) {
      const s = asStr(m.status);
      if (s === STATUS.active) c.active += 1;
      else if (s === STATUS.pending) c.pending += 1;
      else if (s === STATUS.paused) c.paused += 1;
    }
    return c;
  }, [members]);

  const q = query.trim().toLowerCase();
  const visible = useMemo(
    () =>
      members
        .filter((m) => asStr(m.status) === STATUS[tab])
        .filter(
          (m) =>
            !q ||
            asStr(m.name).toLowerCase().includes(q) ||
            asStr(m.email).toLowerCase().includes(q) ||
            asStr(m.role).toLowerCase().includes(q),
        ),
    [members, tab, q],
  );

  const openEdit = (m: EntityRow) => {
    setDraft(Object.fromEntries(ENTITIES.members.fields.map((f) => [f.key, asStr(m[f.key])])));
    setEditing(m);
  };

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div className="flex items-center gap-2">
          <Users className="h-5 w-5 text-primary" />
          <div>
            <h2 className="font-serif text-lg font-semibold text-foreground">Thành viên nhóm</h2>
            <p className="text-sm text-muted-foreground">Quản lý thành viên, vai trò và quyền truy cập của đề tài.</p>
          </div>
        </div>
        <Button onClick={() => setInviteOpen(true)} disabled={!canEdit} title={canEdit ? '' : 'Chỉ chủ nhiệm / quản trị mới mời được'}>
          <UserPlus className="mr-1.5 h-4 w-4" /> Mời thành viên
        </Button>
      </div>

      {/* Tabs + search */}
      <div className="flex flex-wrap items-center justify-between gap-2 border-b border-border pb-2">
        <div className="flex gap-1">
          {TABS.map((tb) => (
            <button
              key={tb.key}
              type="button"
              onClick={() => setTab(tb.key)}
              className={cn(
                'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium transition',
                tab === tb.key ? 'bg-foreground text-background' : 'text-muted-foreground hover:bg-muted',
              )}
            >
              {tb.label}
              <span className={cn('rounded-full px-1.5 text-xs', tab === tb.key ? 'bg-background/20' : 'bg-muted text-muted-foreground')}>
                {counts[tb.key]}
              </span>
            </button>
          ))}
        </div>
        <div className="relative">
          <Search className="absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
          <Input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Tìm tên, email, vai trò" className="h-9 w-60 pl-8" />
        </div>
      </div>

      {/* Table */}
      {visible.length === 0 ? (
        <div className="flex flex-col items-center justify-center rounded-xl border border-dashed border-border py-14 text-center">
          <Users className="mb-2 h-8 w-8 text-muted-foreground" />
          <p className="text-sm font-medium text-foreground">{query ? 'Không tìm thấy' : `Chưa có ${TABS.find((t) => t.key === tab)?.label.toLowerCase()}`}</p>
          {!query && tab === 'pending' && canEdit && (
            <Button variant="outline" size="sm" className="mt-3" onClick={() => setInviteOpen(true)}>
              <UserPlus className="mr-1.5 h-4 w-4" /> Mời thành viên
            </Button>
          )}
        </div>
      ) : (
        <div className="overflow-x-auto rounded-xl border border-border">
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Thành viên</TableHead>
                <TableHead>Vai trò</TableHead>
                <TableHead>Quyền truy cập (RBAC)</TableHead>
                <TableHead>Trạng thái</TableHead>
                <TableHead>Nhiệm vụ</TableHead>
                <TableHead className="text-right" />
              </TableRow>
            </TableHeader>
            <TableBody>
              {visible.map((m) => {
                const name = asStr(m.name) || asStr(m.email) || '(chưa đặt tên)';
                const email = asStr(m.email);
                const role = asStr(m.role);
                const access = asStr(m.access);
                const status = asStr(m.status);
                const av = avatar(name);
                return (
                  <TableRow key={m.id}>
                    <TableCell>
                      <div className="flex items-center gap-2.5">
                        <span className={cn('inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-[11px] font-semibold text-white', av.color)}>
                          {av.initials}
                        </span>
                        <div className="min-w-0">
                          <div className="truncate font-medium text-foreground">{name}</div>
                          {email && <div className="truncate text-xs text-muted-foreground">{email}</div>}
                        </div>
                      </div>
                    </TableCell>
                    {/* Role — inline editable when permitted */}
                    <TableCell>
                      {canEdit ? (
                        <InlineSelect value={role} options={ROLE_OPTIONS} onChange={(v) => patch(m.id, { role: v })} placeholder="Vai trò" />
                      ) : (
                        <span className="text-sm text-foreground">{role || '—'}</span>
                      )}
                    </TableCell>
                    {/* Access (RBAC) — the headline assignment */}
                    <TableCell>
                      {canEdit ? (
                        <InlineSelect value={access} options={ACCESS_OPTIONS} onChange={(v) => patch(m.id, { access: v })} placeholder="Quyền" icon />
                      ) : (
                        <span className="inline-flex items-center gap-1 rounded-md border border-violet-200 bg-violet-50 px-2 py-0.5 text-xs text-violet-700">
                          {isPiAccess(access) ? <Crown size={12} /> : <ShieldCheck size={12} />} {access || '—'}
                        </span>
                      )}
                    </TableCell>
                    <TableCell>
                      <StatusBadge value={status} />
                    </TableCell>
                    <TableCell className="max-w-[220px]">
                      <span className="line-clamp-2 text-sm text-muted-foreground" title={asStr(m.tasks)}>
                        {asStr(m.tasks) || '—'}
                      </span>
                    </TableCell>
                    <TableCell className="text-right">
                      {canEdit && (
                        <DropdownMenu>
                          <DropdownMenuTrigger asChild>
                            <Button variant="ghost" size="icon" className="h-8 w-8">
                              <MoreHorizontal className="h-4 w-4" />
                            </Button>
                          </DropdownMenuTrigger>
                          <DropdownMenuContent align="end" className="w-48">
                            {status !== STATUS.active && (
                              <DropdownMenuItem onClick={() => patch(m.id, { status: STATUS.active })}>
                                <UserCheck className="mr-2 h-4 w-4" /> {status === STATUS.pending ? 'Xác nhận tham gia' : 'Kích hoạt lại'}
                              </DropdownMenuItem>
                            )}
                            {status === STATUS.active && (
                              <DropdownMenuItem onClick={() => patch(m.id, { status: STATUS.paused })}>
                                <X className="mr-2 h-4 w-4" /> Tạm dừng
                              </DropdownMenuItem>
                            )}
                            <DropdownMenuItem onClick={() => openEdit(m)}>
                              <Pencil className="mr-2 h-4 w-4" /> Sửa đầy đủ
                            </DropdownMenuItem>
                            <DropdownMenuSeparator />
                            <DropdownMenuItem className="text-destructive focus:text-destructive" onClick={() => delMut.mutate(m.id)}>
                              <Trash2 className="mr-2 h-4 w-4" /> {status === STATUS.pending ? 'Hủy lời mời' : 'Xóa khỏi nhóm'}
                            </DropdownMenuItem>
                          </DropdownMenuContent>
                        </DropdownMenu>
                      )}
                    </TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </div>
      )}

      {!canEdit && (
        <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <Shield className="h-3.5 w-3.5" /> Chỉ chủ nhiệm đề tài hoặc quản trị viên mới chỉnh sửa được nhóm.
        </p>
      )}

      <InviteDialog
        open={inviteOpen}
        saving={saveMut.isPending}
        existingEmails={members.map((m) => asStr(m.email).toLowerCase()).filter(Boolean)}
        onClose={() => setInviteOpen(false)}
        onSend={(data) => {
          saveMut.mutate(
            { data: { ...data, status: STATUS.pending } },
            {
              onSuccess: () => {
                toast.success(`Đã mời ${data.email}`);
                setInviteOpen(false);
                setTab('pending');
              },
            },
          );
        }}
      />

      {editing && (
        <EntityDrawer
          open
          isNew={false}
          config={ENTITIES.members}
          draft={draft}
          saving={saveMut.isPending}
          onChange={(key, value) => setDraft((d) => ({ ...d, [key]: value }))}
          onClose={() => setEditing(null)}
          onSave={() =>
            saveMut.mutate({ id: editing.id, data: draft }, { onSuccess: () => { toast.success('Đã lưu'); setEditing(null); } })
          }
        />
      )}
    </div>
  );
}

/** A compact inline select for editing a row's role / access in place. */
function InlineSelect({
  value,
  options,
  onChange,
  placeholder,
  icon,
}: {
  value: string;
  options: string[];
  onChange: (v: string) => void;
  placeholder: string;
  icon?: boolean;
}) {
  const opts = value && !options.includes(value) ? [value, ...options] : options;
  return (
    <Select value={value || undefined} onValueChange={onChange}>
      <SelectTrigger className="h-8 w-44 gap-1.5">
        {icon && (isPiAccess(value) ? <Crown className="h-3.5 w-3.5 text-violet-600" /> : <ShieldCheck className="h-3.5 w-3.5 text-violet-600" />)}
        <SelectValue placeholder={placeholder} />
      </SelectTrigger>
      <SelectContent>
        {opts.map((o) => (
          <SelectItem key={o} value={o}>
            {o}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}

/** Invite-a-member modal — name + email + role + access; creates a "Chờ xác nhận" member row. */
function InviteDialog({
  open,
  saving,
  existingEmails,
  onClose,
  onSend,
}: {
  open: boolean;
  saving: boolean;
  existingEmails: string[];
  onClose: () => void;
  onSend: (data: { name: string; email: string; role: string; access: string }) => void;
}) {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [role, setRole] = useState(ROLE_OPTIONS[2] ?? ROLE_OPTIONS[0] ?? '');
  const [access, setAccess] = useState(ACCESS_OPTIONS[ACCESS_OPTIONS.length - 1] ?? '');
  const [err, setErr] = useState('');

  const submit = () => {
    const e = email.trim().toLowerCase();
    if (!name.trim()) return setErr('Vui lòng nhập họ tên.');
    if (!validEmail(e)) return setErr('Email không hợp lệ.');
    if (existingEmails.includes(e)) return setErr('Email này đã có trong nhóm hoặc đang chờ xác nhận.');
    onSend({ name: name.trim(), email: e, role, access });
  };

  return (
    <Dialog
      open={open}
      onOpenChange={(o) => {
        if (!o) onClose();
        else {
          setName('');
          setEmail('');
          setRole(ROLE_OPTIONS[2] ?? ROLE_OPTIONS[0] ?? '');
          setAccess(ACCESS_OPTIONS[ACCESS_OPTIONS.length - 1] ?? '');
          setErr('');
        }
      }}
    >
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle className="font-serif">Mời thành viên</DialogTitle>
        </DialogHeader>
        <div className="space-y-3.5 py-1">
          <div>
            <Label className="mb-1 block text-xs font-semibold text-muted-foreground">Họ và tên</Label>
            <Input value={name} onChange={(e) => { setName(e.target.value); setErr(''); }} placeholder="VD: TS. Nguyễn Văn A" />
          </div>
          <div>
            <Label className="mb-1 block text-xs font-semibold text-muted-foreground">Email</Label>
            <div className="flex items-center gap-2 rounded-md border border-input px-2.5">
              <Mail className="h-4 w-4 text-muted-foreground" />
              <Input
                value={email}
                onChange={(e) => { setEmail(e.target.value); setErr(''); }}
                onKeyDown={(e) => e.key === 'Enter' && submit()}
                placeholder="name@ump.edu.vn"
                className="border-0 px-0 shadow-none focus-visible:ring-0"
              />
            </div>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <Label className="mb-1 block text-xs font-semibold text-muted-foreground">Vai trò</Label>
              <Select value={role} onValueChange={setRole}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>{ROLE_OPTIONS.map((o) => <SelectItem key={o} value={o}>{o}</SelectItem>)}</SelectContent>
              </Select>
            </div>
            <div>
              <Label className="mb-1 block text-xs font-semibold text-muted-foreground">Quyền truy cập</Label>
              <Select value={access} onValueChange={setAccess}>
                <SelectTrigger><SelectValue /></SelectTrigger>
                <SelectContent>{ACCESS_OPTIONS.map((o) => <SelectItem key={o} value={o}>{o}</SelectItem>)}</SelectContent>
              </Select>
            </div>
          </div>
          {err && <p className="rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive">{err}</p>}
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={onClose} disabled={saving}>Hủy</Button>
          <Button onClick={submit} disabled={saving}>
            <UserPlus className="mr-1.5 h-4 w-4" /> Gửi lời mời
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

export default TeamManagementView;
