import { Fragment, useState, type FormEvent } from 'react';
import { extractApiError } from '@/api/client';
import type { Role, User } from '@/api/types';
import { useAuth } from '@/hooks/useAuth';
import {
  useCreateUser,
  useDeleteUser,
  usePatchUser,
  useUsersList,
} from '@/hooks/useUsers';
import { useToast } from '@/hooks/useToast';
import { FormField, Select, TextInput } from '@/components/FormField';
import { LoadingState } from '@/components/LoadingState';
import { ErrorState } from '@/components/ErrorState';
import { EmptyState } from '@/components/EmptyState';

const ROLE_OPTIONS: { value: Role; label: string }[] = [
  { value: 'admin', label: 'Admin' },
  { value: 'redteam', label: 'Red Team' },
  { value: 'soc', label: 'SOC' },
];

interface CreateFormState {
  username: string;
  password: string;
  role: Role;
}

const EMPTY_CREATE: CreateFormState = { username: '', password: '', role: 'redteam' };

export function UsersAdminPage(): JSX.Element {
  const { user: currentUser } = useAuth();
  const { push } = useToast();
  const list = useUsersList();
  const createMutation = useCreateUser();
  const patchMutation = usePatchUser();
  const deleteMutation = useDeleteUser();

  const [createForm, setCreateForm] = useState<CreateFormState>(EMPTY_CREATE);
  const [createError, setCreateError] = useState<string | null>(null);

  // Per-row password reset state. Only one row open at a time.
  const [resetOpen, setResetOpen] = useState<number | null>(null);
  const [resetPassword, setResetPassword] = useState('');

  const onCreate = async (e: FormEvent) => {
    e.preventDefault();
    setCreateError(null);
    if (createForm.password.length < 8) {
      setCreateError('Password must be at least 8 characters');
      return;
    }
    try {
      await createMutation.mutateAsync(createForm);
      setCreateForm(EMPTY_CREATE);
      push('User created', 'success');
    } catch (err) {
      setCreateError(extractApiError(err, 'Could not create user'));
    }
  };

  const onRoleChange = async (u: User, role: Role) => {
    if (u.role === role) return;
    try {
      await patchMutation.mutateAsync({ id: u.id, input: { role } });
      push(`Role updated for ${u.username}`, 'success');
    } catch (err) {
      push(extractApiError(err, 'Could not update role'), 'error');
    }
  };

  const onResetPassword = async (u: User, e: FormEvent) => {
    e.preventDefault();
    if (resetPassword.length < 8) {
      push('Password must be at least 8 characters', 'error');
      return;
    }
    try {
      await patchMutation.mutateAsync({ id: u.id, input: { password: resetPassword } });
      push(`Password reset for ${u.username}`, 'success');
      setResetOpen(null);
      setResetPassword('');
    } catch (err) {
      push(extractApiError(err, 'Could not reset password'), 'error');
    }
  };

  const onDelete = async (u: User) => {
    if (currentUser?.id === u.id) {
      push('You cannot delete your own account', 'error');
      return;
    }
    if (!window.confirm(`Delete user "${u.username}"?`)) return;
    try {
      await deleteMutation.mutateAsync(u.id);
      push('User deleted', 'success');
    } catch (err) {
      push(extractApiError(err, 'Could not delete user'), 'error');
    }
  };

  return (
    <div className="flex flex-col gap-xl">
      <header>
        <h1 className="text-[32px] font-medium leading-none">User accounts</h1>
        <p className="text-charcoal text-[16px] mt-sm">
          Manage local accounts. Admins can create new red team or SOC analysts.
        </p>
      </header>

      <section className="card-product flex flex-col gap-md">
        <h2 className="text-[20px] font-medium">Create account</h2>
        {/*
          Option A structural fix (AC-17.3): labels / inputs / hints in 3 explicit grid rows
          so the browser can never misalign them by collapsing different-height cells.
          grid-rows-[auto_auto_auto] ensures row 1 = labels, row 2 = inputs, row 3 = hints.
        */}
        <form
          onSubmit={onCreate}
          className="grid grid-cols-1 md:grid-cols-4 md:grid-rows-[auto_auto_auto] gap-x-md gap-y-xs"
        >
          {/* Row 1 — labels */}
          <label htmlFor="new-username" className="text-[14px] font-medium text-ink">
            Username <span className="text-bloom-deep">*</span>
          </label>
          <label htmlFor="new-password" className="text-[14px] font-medium text-ink">
            Password <span className="text-bloom-deep">*</span>
          </label>
          <label htmlFor="new-role" className="text-[14px] font-medium text-ink">
            Role <span className="text-bloom-deep">*</span>
          </label>
          <div aria-hidden="true" />

          {/* Row 2 — inputs + button (all same height = h-11) */}
          <TextInput
            id="new-username"
            value={createForm.username}
            onChange={(e) => setCreateForm({ ...createForm, username: e.target.value })}
            required
          />
          <TextInput
            id="new-password"
            type="password"
            value={createForm.password}
            onChange={(e) => setCreateForm({ ...createForm, password: e.target.value })}
            required
            minLength={8}
          />
          <Select
            id="new-role"
            value={createForm.role}
            onChange={(e) => setCreateForm({ ...createForm, role: e.target.value as Role })}
            options={ROLE_OPTIONS}
          />
          <button type="submit" className="btn-primary w-full" disabled={createMutation.isPending}>
            {createMutation.isPending ? 'Creating…' : 'Create'}
          </button>

          {/* Row 3 — hints */}
          <div aria-hidden="true" />
          <span className="text-[12px] text-graphite">≥ 8 characters</span>
          <div aria-hidden="true" />
          <div aria-hidden="true" />
        </form>
        {createError ? (
          <div role="alert" className="text-[14px] text-bloom-deep">
            {createError}
          </div>
        ) : null}
      </section>

      <section className="flex flex-col gap-md">
        <h2 className="text-[20px] font-medium">All accounts</h2>

        {list.isLoading ? <LoadingState label="Loading users…" /> : null}
        {list.isError ? (
          <ErrorState
            message={extractApiError(list.error, 'Could not load users')}
            onRetry={() => list.refetch()}
          />
        ) : null}
        {!list.isLoading && !list.isError && list.data && list.data.length === 0 ? (
          <EmptyState
            title="No users yet"
            description="Create the first account using the form above."
          />
        ) : null}

        {!list.isLoading && !list.isError && list.data && list.data.length > 0 ? (
          <div className="card-product overflow-hidden p-0">
            <table className="table-compact w-full text-left">
              <thead className="bg-cloud border-b border-hairline">
                <tr>
                  <th>Username</th>
                  <th>Role</th>
                  <th>Created</th>
                  <th className="text-right">Actions</th>
                </tr>
              </thead>
              <tbody>
                {list.data.map((u) => {
                  const isSelf = currentUser?.id === u.id;
                  return (
                    // Fragment must carry the key — `<>` cannot, which broke
                    // per-row reconciliation (reset-password state leaked across rows).
                    <Fragment key={u.id}>
                      <tr>
                        <td className="text-ink">
                          <span className="font-mono font-medium">{u.username}</span>
                          {isSelf ? (
                            <span className="ml-sm font-sans text-[12px] text-graphite">
                              (you)
                            </span>
                          ) : null}
                        </td>
                        <td>
                          <Select
                            value={u.role}
                            onChange={(e) => onRoleChange(u, e.target.value as Role)}
                            options={ROLE_OPTIONS}
                            aria-label={`Change role for ${u.username}`}
                            disabled={patchMutation.isPending}
                          />
                        </td>
                        <td className="text-charcoal font-mono">{u.created_at}</td>
                        <td className="text-right">
                          <div className="inline-flex gap-sm">
                            <button
                              type="button"
                              className="btn-text-link"
                              onClick={() => {
                                setResetOpen(resetOpen === u.id ? null : u.id);
                                setResetPassword('');
                              }}
                            >
                              Reset password
                            </button>
                            <button
                              type="button"
                              className="btn-text-link text-bloom-deep disabled:text-steel"
                              disabled={isSelf || deleteMutation.isPending}
                              onClick={() => onDelete(u)}
                            >
                              Delete
                            </button>
                          </div>
                        </td>
                      </tr>
                      {resetOpen === u.id ? (
                        <tr className="border-b border-hairline last:border-0 bg-cloud">
                          {/* Aerated row — inline form needs room; compact-density tradeoff intentional */}
                          <td colSpan={4} className="px-xl py-md">
                            <form
                              onSubmit={(e) => onResetPassword(u, e)}
                              className="flex items-end gap-md"
                            >
                              <FormField
                                label={`New password for ${u.username}`}
                                htmlFor={`reset-${u.id}`}
                                hint="≥ 8 characters"
                              >
                                <TextInput
                                  id={`reset-${u.id}`}
                                  type="password"
                                  value={resetPassword}
                                  onChange={(e) => setResetPassword(e.target.value)}
                                  minLength={8}
                                  required
                                />
                              </FormField>
                              <button type="submit" className="btn-primary">
                                Save password
                              </button>
                              <button
                                type="button"
                                className="btn-outline-ink"
                                onClick={() => {
                                  setResetOpen(null);
                                  setResetPassword('');
                                }}
                              >
                                Cancel
                              </button>
                            </form>
                          </td>
                        </tr>
                      ) : null}
                    </Fragment>
                  );
                })}
              </tbody>
            </table>
          </div>
        ) : null}
      </section>
    </div>
  );
}
