import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { HelpText } from './HelpText';

/**
 * Settings → System → Organizations (admin).
 *
 * Local organizations give local accounts a provider-agnostic 'org' visibility
 * scope (Gitea orgs come from Gitea instead). Uses /api/admin/orgs directly —
 * no config.yaml, no Save bar. See docs/superpowers/plans/2026-06-09-local-orgs.md.
 */
interface OrgMember { userId: string; role: string }
interface LocalOrg { id: string; name: string; createdBy: string | null; createdAt: string; members: OrgMember[] }
interface UserLite { id: string; email: string; name: string | null }

async function jget<T>(url: string): Promise<T> {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`${res.status}`);
  return res.json() as Promise<T>;
}

export function OrgsForm() {
  const { t } = useTranslation('settings');
  const qc = useQueryClient();
  const orgsQ = useQuery<LocalOrg[]>({
    queryKey: ['admin', 'orgs'],
    queryFn: async () => {
      const res = await fetch('/api/admin/orgs');
      if (res.status === 401 || res.status === 403) return [];
      if (!res.ok) throw new Error('failed');
      return res.json();
    },
  });
  const usersQ = useQuery<UserLite[]>({
    queryKey: ['admin', 'users'],
    queryFn: () => jget<UserLite[]>('/api/admin/users'),
  });

  const invalidate = () => qc.invalidateQueries({ queryKey: ['admin', 'orgs'] });
  const [newName, setNewName] = useState('');

  const createMut = useMutation({
    mutationFn: async (name: string) => {
      const res = await fetch('/api/admin/orgs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) });
      if (!res.ok) throw new Error('create failed');
    },
    onSuccess: () => { setNewName(''); invalidate(); },
  });
  const deleteMut = useMutation({
    mutationFn: async (id: string) => { await fetch(`/api/admin/orgs/${encodeURIComponent(id)}`, { method: 'DELETE' }); },
    onSuccess: invalidate,
  });
  const renameMut = useMutation({
    mutationFn: async ({ id, name }: { id: string; name: string }) => {
      await fetch(`/api/admin/orgs/${encodeURIComponent(id)}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) });
    },
    onSuccess: invalidate,
  });
  const addMemberMut = useMutation({
    mutationFn: async ({ id, userId }: { id: string; userId: string }) => {
      await fetch(`/api/admin/orgs/${encodeURIComponent(id)}/members`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ userId }) });
    },
    onSuccess: invalidate,
  });
  const removeMemberMut = useMutation({
    mutationFn: async ({ id, userId }: { id: string; userId: string }) => {
      await fetch(`/api/admin/orgs/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`, { method: 'DELETE' });
    },
    onSuccess: invalidate,
  });

  const orgs = orgsQ.data ?? [];
  const users = usersQ.data ?? [];
  const userLabel = (id: string) => {
    const u = users.find(x => x.id === id);
    return u ? (u.name || u.email) : id;
  };

  return (
    <div className="max-w-2xl space-y-4">
      <div>
        <h2 className="text-base font-semibold text-slate-800 mb-1">Organizations</h2>
        <p className="text-xs text-slate-500">
          {t('orgs.intro')}
        </p>
      </div>

      <form
        className="flex items-center gap-2"
        onSubmit={e => { e.preventDefault(); if (newName.trim()) createMut.mutate(newName.trim()); }}
      >
        <input
          value={newName}
          onChange={e => setNewName(e.target.value)}
          placeholder={t('orgs.newNamePlaceholder')}
          className="flex-1 h-9 px-2.5 text-[13px] border border-hairline rounded-md focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none bg-canvas"
        />
        <button type="submit" disabled={!newName.trim() || createMut.isPending} className="px-3 h-9 rounded-md text-xs font-semibold bg-accent text-white disabled:opacity-50 hover:opacity-90 whitespace-nowrap">
          {t('orgs.create')}
        </button>
      </form>

      {orgsQ.isLoading && <div className="text-xs text-slate-500">{t('orgs.loading')}</div>}
      {!orgsQ.isLoading && orgs.length === 0 && (
        <div className="text-xs text-slate-400 border border-dashed border-slate-200 rounded p-4 text-center">
          {t('orgs.empty')}
        </div>
      )}

      <div className="space-y-3">
        {orgs.map(org => (
          <OrgCard
            key={org.id}
            org={org}
            users={users}
            userLabel={userLabel}
            onRename={(name) => renameMut.mutate({ id: org.id, name })}
            onDelete={() => { if (confirm(t('orgs.confirmDelete', { name: org.name }))) deleteMut.mutate(org.id); }}
            onAddMember={(userId) => addMemberMut.mutate({ id: org.id, userId })}
            onRemoveMember={(userId) => removeMemberMut.mutate({ id: org.id, userId })}
          />
        ))}
      </div>
      <HelpText>{t('orgs.memberHint')}</HelpText>
    </div>
  );
}

function OrgCard({ org, users, userLabel, onRename, onDelete, onAddMember, onRemoveMember }: {
  org: LocalOrg;
  users: UserLite[];
  userLabel: (id: string) => string;
  onRename: (name: string) => void;
  onDelete: () => void;
  onAddMember: (userId: string) => void;
  onRemoveMember: (userId: string) => void;
}) {
  const { t } = useTranslation('settings');
  const [name, setName] = useState(org.name);
  const memberIds = new Set(org.members.map(m => m.userId));
  const addable = users.filter(u => !memberIds.has(u.id));
  const [pick, setPick] = useState('');

  return (
    <div className="border border-hairline rounded-lg p-4 bg-canvas">
      <div className="flex items-center gap-2 mb-3">
        <input
          value={name}
          onChange={e => setName(e.target.value)}
          onBlur={() => { if (name.trim() && name.trim() !== org.name) onRename(name.trim()); }}
          className="flex-1 h-8 px-2 text-[13px] font-medium border border-hairline rounded-md focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none bg-canvas"
        />
        <button type="button" onClick={onDelete} className="px-2.5 h-8 rounded-md text-xs font-medium border border-red-200 text-red-700 dark:text-red-300 hover:bg-red-50 dark:hover:bg-red-500/15 whitespace-nowrap">
          {t('orgs.delete')}
        </button>
      </div>

      <div className="text-2xs text-slate-500 mb-1.5">{t('orgs.membersCount', { count: org.members.length })}</div>
      <div className="flex flex-wrap gap-1.5 mb-2.5">
        {org.members.length === 0 && <span className="text-2xs text-slate-400">{t('orgs.noMembers')}</span>}
        {org.members.map(m => (
          <span key={m.userId} className="inline-flex items-center gap-1.5 pl-2 pr-1 h-6 rounded border border-hairline bg-surface text-slate-700 text-2xs">
            {userLabel(m.userId)}
            {m.role === 'owner' && <span className="text-[9px] text-blue-600">owner</span>}
            <button type="button" onClick={() => onRemoveMember(m.userId)} title={t('orgs.removeMemberTitle')} className="text-slate-400 hover:text-red-500 leading-none px-0.5">×</button>
          </span>
        ))}
      </div>

      <div className="flex items-center gap-2">
        <select value={pick} onChange={e => setPick(e.target.value)} className="flex-1 h-8 px-2 text-xs border border-hairline rounded-md bg-canvas">
          <option value="">{t('orgs.addMemberPlaceholder')}</option>
          {addable.map(u => <option key={u.id} value={u.id}>{u.name || u.email}</option>)}
        </select>
        <button
          type="button"
          disabled={!pick}
          onClick={() => { if (pick) { onAddMember(pick); setPick(''); } }}
          className="px-3 h-8 rounded-md text-xs font-medium border border-accent/60 text-accent hover:bg-accent-soft disabled:opacity-40 whitespace-nowrap"
        >
          {t('orgs.add')}
        </button>
      </div>
    </div>
  );
}
