/*
 * M18 사용자 관리 (SCR-A1 · §5B). SysUserController 실배선.
 * 정본: GET /api/admin/users?keyword&status&roleCode&page&size → PageResponse<SysUser> · POST/PUT · PATCH status · POST password/otp reset.
 * 보안: 비밀번호는 생성 시에만 입력·전송하고 목록/응답에는 노출되지 않는다(SysUserDto 미포함). 재설정은 서버 정책 위임(값 미표시).
 * 상태 3종: 로딩 스켈레톤 / 빈 / 에러(재시도). 검색·페이지네이션·생성/수정 모달.
 */
import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Trans, useTranslation } from 'react-i18next';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { Button } from '../../components/ui/Button';
import { IconPlus, IconSearch } from '../../components/ui/icons';
import { errMessage, fmtDateTime, useToast } from '../work/workShared';
import {
  sysUserApi,
  USER_ROLE_CODES,
  USER_STATUSES,
  type SysUser,
  type UserSaveBody,
  type UserSearchParams,
} from './adminCrudApi';
import './admin-modules.css';

const PAGE_SIZE = 20;

export function SysUserAdminPage() {
  const { t } = useTranslation();
  const qc = useQueryClient();
  const { show, node: toast } = useToast();

  const [keyword, setKeyword] = useState('');
  const [status, setStatus] = useState('');
  const [roleCode, setRoleCode] = useState('');
  const [page, setPage] = useState(0);
  const [applied, setApplied] = useState<UserSearchParams>({});
  const [editing, setEditing] = useState<SysUser | null | undefined>(undefined); // undefined=닫힘, null=신규

  const q = useQuery({
    queryKey: ['admin-users', applied, page],
    queryFn: () => sysUserApi.list({ ...applied, page, size: PAGE_SIZE }),
    retry: false,
  });

  const saveM = useMutation({
    mutationFn: ({ userId, body }: { userId: string | null; body: UserSaveBody }) =>
      userId ? sysUserApi.update(userId, body) : sysUserApi.create(body),
    onSuccess: () => {
      show(t('sysuser.saved'));
      setEditing(undefined);
      qc.invalidateQueries({ queryKey: ['admin-users'] });
    },
    onError: (e) => show(errMessage(e)),
  });

  const statusM = useMutation({
    mutationFn: ({ userId, value }: { userId: string; value: string }) =>
      sysUserApi.changeStatus(userId, value),
    onSuccess: () => {
      show(t('sysuser.statusChanged'));
      qc.invalidateQueries({ queryKey: ['admin-users'] });
    },
    onError: (e) => show(errMessage(e)),
  });

  const otpM = useMutation({
    mutationFn: (userId: string) => sysUserApi.resetOtp(userId),
    onSuccess: () => show(t('sysuser.otpReset')),
    onError: (e) => show(errMessage(e)),
  });

  const rows = q.data?.items ?? [];
  const total = q.data?.total ?? 0;
  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));

  function applyFilters() {
    setPage(0);
    setApplied({
      keyword: keyword.trim() || undefined,
      status: status || undefined,
      roleCode: roleCode || undefined,
    });
  }
  function resetFilters() {
    setKeyword('');
    setStatus('');
    setRoleCode('');
    setPage(0);
    setApplied({});
  }

  return (
    <div className="kx-page kx-adm">
      <header className="kx-adm__head">
        <div>
          <h1 className="kx-adm__title">{t('sysuser.title')}</h1>
          <p className="kx-adm__subtitle">
            {t('sysuser.subtitle')}
          </p>
        </div>
        <Button leadingIcon={<IconPlus size={16} />} onClick={() => setEditing(null)}>
          {t('sysuser.addUser')}
        </Button>
      </header>

      {/* 검색 툴바 */}
      <section className="kx-card kx-adm-filter" aria-label={t('sysuser.searchAria')}>
        <div className="kx-adm-toolbar">
          <div className="kx-adm-toolbar__filters">
            <label className="kx-adm-field">
              <span className="kx-adm-field__label">{t('sysuser.keyword')}</span>
              <input
                className="kx-adm-field__input"
                placeholder={t('sysuser.keywordPh')}
                value={keyword}
                onChange={(e) => setKeyword(e.target.value)}
                onKeyDown={(e) => e.key === 'Enter' && applyFilters()}
              />
            </label>
            <label className="kx-adm-field">
              <span className="kx-adm-field__label">{t('sysuser.role')}</span>
              <select className="kx-adm-field__select" value={roleCode} onChange={(e) => setRoleCode(e.target.value)}>
                <option value="">{t('sysuser.all')}</option>
                {USER_ROLE_CODES.map((r) => (
                  <option key={r} value={r}>{r}</option>
                ))}
              </select>
            </label>
            <label className="kx-adm-field">
              <span className="kx-adm-field__label">{t('sysuser.status')}</span>
              <select className="kx-adm-field__select" value={status} onChange={(e) => setStatus(e.target.value)}>
                <option value="">{t('sysuser.all')}</option>
                {USER_STATUSES.map((s) => (
                  <option key={s} value={s}>{s}</option>
                ))}
              </select>
            </label>
          </div>
          <div className="kx-adm-toolbar__actions">
            <Button variant="ghost" onClick={resetFilters}>{t('sysuser.reset')}</Button>
            <Button leadingIcon={<IconSearch size={16} />} onClick={applyFilters}>{t('sysuser.search')}</Button>
          </div>
        </div>
      </section>

      {q.isLoading && <TableSkeleton />}
      {q.isError && !q.isLoading && (
        <ErrorState message={t('sysuser.loadError')} onRetry={() => q.refetch()} />
      )}

      {!q.isLoading && !q.isError && (
        <section className="kx-card kx-adm-table-card" aria-label={t('sysuser.listAria')}>
          {rows.length === 0 ? (
            <EmptyState title={t('sysuser.emptyTitle')} description={t('sysuser.emptyDesc')} />
          ) : (
            <>
              <div className="kx-table-scroll">
                <table className="kx-table kx-table--zebra kx-adm-tbl">
                  <thead>
                    <tr>
                      <th>{t('sysuser.colUser')}</th>
                      <th>{t('sysuser.colEmail')}</th>
                      <th>{t('sysuser.colRole')}</th>
                      <th>{t('sysuser.colDept')}</th>
                      <th>{t('sysuser.colStatus')}</th>
                      <th>OTP</th>
                      <th>{t('sysuser.colLastLogin')}</th>
                      <th style={{ textAlign: 'right' }}>{t('sysuser.colManage')}</th>
                    </tr>
                  </thead>
                  <tbody>
                    {rows.map((u) => (
                      <tr key={u.userId}>
                        <td>
                          <span className="kx-adm-tbl__strong">{u.displayName ?? '—'}</span>
                          {u.hallManager && (
                            <span className="kx-adm-typechip" style={{ marginLeft: 6 }}>{t('sysuser.hallManagerTag')}</span>
                          )}
                        </td>
                        <td className="kx-adm-muted">{u.email ?? '—'}</td>
                        <td><RoleChip value={u.roleCode} /></td>
                        <td className="kx-adm-muted">{u.deptId ?? '—'}</td>
                        <td><StatusCell status={u.status} /></td>
                        <td>
                          <span className={`kx-adm-pill kx-adm-pill--${u.otpEnabled ? 'success' : 'neutral'}`}>
                            {u.otpEnabled ? t('sysuser.otpSet') : t('sysuser.otpUnset')}
                          </span>
                        </td>
                        <td className="kx-adm-mono">{u.lastLoginAt ? fmtDateTime(u.lastLoginAt) : '—'}</td>
                        <td>
                          <div className="kx-adm-tbl__actions">
                            <Button variant="ghost" onClick={() => setEditing(u)}>{t('sysuser.edit')}</Button>
                            {u.status !== 'LOCKED' ? (
                              <Button
                                variant="ghost"
                                disabled={statusM.isPending}
                                onClick={() => statusM.mutate({ userId: u.userId, value: 'LOCKED' })}
                              >
                                {t('sysuser.lock')}
                              </Button>
                            ) : (
                              <Button
                                variant="ghost"
                                disabled={statusM.isPending}
                                onClick={() => statusM.mutate({ userId: u.userId, value: 'ACTIVE' })}
                              >
                                {t('sysuser.unlock')}
                              </Button>
                            )}
                            {u.otpEnabled && (
                              <Button
                                variant="ghost"
                                disabled={otpM.isPending}
                                onClick={() => {
                                  if (window.confirm(t('sysuser.otpResetConfirm', { name: u.displayName ?? u.userId })))
                                    otpM.mutate(u.userId);
                                }}
                              >
                                {t('sysuser.otpResetBtn')}
                              </Button>
                            )}
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <Pager page={page} totalPages={totalPages} total={total} onPage={setPage} />
            </>
          )}
        </section>
      )}

      {editing !== undefined && (
        <UserModal
          user={editing}
          saving={saveM.isPending}
          onClose={() => setEditing(undefined)}
          onSubmit={(body) => saveM.mutate({ userId: editing?.userId ?? null, body })}
        />
      )}
      {toast}
    </div>
  );
}

function RoleChip({ value }: { value: string | null }) {
  const v = (value ?? 'USER').toUpperCase();
  const cls = v === 'ADMIN' ? 'admin' : v === 'MANAGER' ? 'manager' : 'user';
  return <span className={`kx-adm-rolechip kx-adm-rolechip--${cls}`}>{v}</span>;
}

function StatusCell({ status }: { status: string | null }) {
  const { t } = useTranslation();
  const v = (status ?? 'ACTIVE').toUpperCase();
  const tone = v === 'ACTIVE' ? 'success' : v === 'LOCKED' ? 'error' : 'neutral';
  const label = v === 'ACTIVE' ? t('sysuser.active') : v === 'LOCKED' ? t('sysuser.locked') : v === 'DISABLED' ? t('sysuser.disabled') : v;
  return <span className={`kx-adm-pill kx-adm-pill--${tone}`}>{label}</span>;
}

function UserModal({
  user,
  saving,
  onClose,
  onSubmit,
}: {
  user: SysUser | null;
  saving: boolean;
  onClose: () => void;
  onSubmit: (body: UserSaveBody) => void;
}) {
  const { t } = useTranslation();
  const isNew = user === null;
  const [email, setEmail] = useState(user?.email ?? '');
  const [displayName, setDisplayName] = useState(user?.displayName ?? '');
  const [password, setPassword] = useState('');
  const [roleCode, setRoleCode] = useState(user?.roleCode ?? 'USER');
  const [deptId, setDeptId] = useState(user?.deptId ?? '');
  const [hallManager, setHallManager] = useState(user?.hallManager ?? false);
  const [error, setError] = useState<string | null>(null);

  function submit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    if (!email.trim() || !displayName.trim()) {
      setError(t('sysuser.errRequired'));
      return;
    }
    if (isNew && password.trim() === '') {
      setError(t('sysuser.errPassword'));
      return;
    }
    const body: UserSaveBody = {
      email: email.trim(),
      displayName: displayName.trim(),
      roleCode,
      deptId: deptId.trim() || null,
      hallManager,
    };
    if (isNew) body.password = password;
    onSubmit(body);
  }

  return (
    <div className="kx-adm-modal" role="dialog" aria-modal="true" aria-labelledby="user-modal-title">
      <div className="kx-adm-modal__backdrop" onClick={onClose} />
      <form className="kx-adm-modal__panel" onSubmit={submit}>
        <h2 id="user-modal-title" className="kx-adm-modal__title">{isNew ? t('sysuser.addUser') : t('sysuser.editUser')}</h2>
        <p className="kx-adm-modal__desc">
          {isNew ? t('sysuser.newDesc') : t('sysuser.editDesc')}
        </p>
        <div className="kx-adm-modal__grid">
          <label className="kx-adm-field kx-adm-field--full">
            <span className="kx-adm-field__label">{t('sysuser.email')}</span>
            <input
              className="kx-adm-field__input"
              type="email"
              value={email}
              disabled={!isNew}
              autoComplete="off"
              onChange={(e) => setEmail(e.target.value)}
            />
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('sysuser.displayName')}</span>
            <input className="kx-adm-field__input" value={displayName} onChange={(e) => setDisplayName(e.target.value)} />
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('sysuser.dept')}</span>
            <input className="kx-adm-field__input" value={deptId} onChange={(e) => setDeptId(e.target.value)} />
          </label>
          {isNew && (
            <label className="kx-adm-field kx-adm-field--full">
              <span className="kx-adm-field__label">{t('sysuser.initPassword')}</span>
              <input
                className="kx-adm-field__input"
                type="password"
                value={password}
                autoComplete="new-password"
                onChange={(e) => setPassword(e.target.value)}
              />
            </label>
          )}
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('sysuser.role')}</span>
            <select className="kx-adm-field__select" value={roleCode ?? 'USER'} onChange={(e) => setRoleCode(e.target.value)}>
              {USER_ROLE_CODES.map((r) => (
                <option key={r} value={r}>{r}</option>
              ))}
            </select>
          </label>
          <label className="kx-adm-check" style={{ alignSelf: 'end', paddingBottom: 8 }}>
            <input type="checkbox" checked={hallManager} onChange={(e) => setHallManager(e.target.checked)} />
            {t('sysuser.hallManagerCheck')}
          </label>
        </div>
        {error && <p className="kx-adm-modal__error" role="alert">{error}</p>}
        <div className="kx-adm-modal__actions">
          <Button variant="ghost" type="button" onClick={onClose}>{t('sysuser.cancel')}</Button>
          <Button type="submit" disabled={saving}>{saving ? t('sysuser.saving') : t('sysuser.save')}</Button>
        </div>
      </form>
    </div>
  );
}

function Pager({
  page,
  totalPages,
  total,
  onPage,
}: {
  page: number;
  totalPages: number;
  total: number;
  onPage: (p: number) => void;
}) {
  const { t } = useTranslation();
  return (
    <div className="kx-adm-pager">
      <p className="kx-adm-pager__info"><Trans i18nKey="sysuser.totalUsers" values={{ total: total.toLocaleString() }} components={[<strong className="tnum" key="a" />]} /></p>
      <div className="kx-adm-pager__nav">
        <Button variant="ghost" onClick={() => onPage(Math.max(0, page - 1))} disabled={page === 0}>{t('sysuser.prev')}</Button>
        <span className="kx-adm-pager__page tnum">{page + 1} / {totalPages}</span>
        <Button variant="ghost" onClick={() => onPage(Math.min(totalPages - 1, page + 1))} disabled={page >= totalPages - 1}>{t('sysuser.next')}</Button>
      </div>
    </div>
  );
}

function TableSkeleton() {
  return (
    <div className="kx-card" aria-hidden="true" style={{ display: 'grid', gap: 12 }}>
      {[0, 1, 2, 3, 4, 5].map((i) => (
        <Skeleton key={i} height={44} radius={6} />
      ))}
    </div>
  );
}
