/*
 * M18 역할/권한(RBAC) 관리 (SCR-A2 · §5B). RoleController 실배선.
 * 정본: GET /api/admin/roles → Role[] · GET /api/admin/roles/permissions → Permission[] · POST 저장 · DELETE /{roleCode}.
 * UI: 좌 역할 목록(선택), 우 권한 매트릭스(역할 × 권한 체크). 역할 저장 시 permissions[] 갱신.
 * 상태 3종: 로딩 스켈레톤 / 빈 / 에러(재시도).
 */
import { useEffect, useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { EmptyState, ErrorState, Skeleton } from '../../components/ui/States';
import { Button } from '../../components/ui/Button';
import { IconPlus } from '../../components/ui/icons';
import { errMessage, useToast } from '../work/workShared';
import { roleApi, type Role } from './adminCrudApi';
import './admin-modules.css';

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

  const rolesQ = useQuery({ queryKey: ['admin-roles'], queryFn: roleApi.list, retry: false });
  const permsQ = useQuery({ queryKey: ['admin-permissions'], queryFn: roleApi.permissions, retry: false });

  const [selected, setSelected] = useState<string | null>(null);
  const [editing, setEditing] = useState<Role | null | undefined>(undefined);

  const roles = rolesQ.data ?? [];
  const perms = permsQ.data ?? [];

  useEffect(() => {
    if (!selected && roles.length > 0) setSelected(roles[0].roleCode);
  }, [roles, selected]);

  const activeRole = roles.find((r) => r.roleCode === selected) ?? null;

  const saveM = useMutation({
    mutationFn: (role: Role) => roleApi.save(role),
    onSuccess: () => {
      show(t('role.saved'));
      setEditing(undefined);
      qc.invalidateQueries({ queryKey: ['admin-roles'] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const delM = useMutation({
    mutationFn: (roleCode: string) => roleApi.remove(roleCode),
    onSuccess: () => {
      show(t('role.deleted'));
      setSelected(null);
      qc.invalidateQueries({ queryKey: ['admin-roles'] });
    },
    onError: (e) => show(errMessage(e)),
  });

  function togglePerm(permCode: string, on: boolean) {
    if (!activeRole) return;
    const next = on
      ? [...new Set([...activeRole.permissions, permCode])]
      : activeRole.permissions.filter((p) => p !== permCode);
    saveM.mutate({ ...activeRole, permissions: next });
  }

  const loading = rolesQ.isLoading || permsQ.isLoading;
  const errored = rolesQ.isError || permsQ.isError;

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

      {loading && <Skeleton height={320} radius={12} />}
      {errored && !loading && (
        <ErrorState
          message={t('role.loadError')}
          onRetry={() => {
            rolesQ.refetch();
            permsQ.refetch();
          }}
        />
      )}

      {!loading && !errored && (
        roles.length === 0 ? (
          <EmptyState title={t('role.noRolesTitle')} description={t('role.noRolesDesc')} />
        ) : (
          <div className="kx-adm-matrix">
            {/* 좌: 역할 목록 */}
            <section className="kx-card kx-adm-matrix__roles" aria-label={t('role.roleList')}>
              <div className="kx-adm-codes__head">
                <h2>{t('role.role')}</h2>
              </div>
              <ul className="kx-adm-glist">
                {roles.map((r) => (
                  <li key={r.roleCode}>
                    <button
                      type="button"
                      className={`kx-adm-gitem ${r.roleCode === selected ? 'is-active' : ''}`}
                      onClick={() => setSelected(r.roleCode)}
                    >
                      <span className="kx-adm-gitem__name">{r.roleName}</span>
                      <span className="kx-adm-gitem__code">
                        {t('role.codePerm', { code: r.roleCode, n: r.permissions.length })}
                        {r.useYn === 'N' ? ` · ${t('role.unused')}` : ''}
                      </span>
                    </button>
                  </li>
                ))}
              </ul>
            </section>

            {/* 우: 권한 매트릭스 */}
            <section className="kx-card kx-adm-matrix__perms" aria-label={t('role.permMatrix')}>
              {activeRole ? (
                <>
                  <div className="kx-adm-codes__head" style={{ padding: 0, border: 'none', marginBottom: 8 }}>
                    <div>
                      <h2>{t('role.rolePerm', { name: activeRole.roleName })}</h2>
                      <p className="kx-adm-muted">{activeRole.description ?? activeRole.roleCode}</p>
                    </div>
                    <div className="kx-adm-tbl__actions">
                      <Button variant="ghost" onClick={() => setEditing(activeRole)}>{t('role.roleInfo')}</Button>
                      <Button
                        variant="ghost"
                        className="kx-adm-del"
                        disabled={delM.isPending}
                        onClick={() => {
                          if (window.confirm(t('role.deleteConfirm', { name: activeRole.roleName })))
                            delM.mutate(activeRole.roleCode);
                        }}
                      >
                        {t('role.delete')}
                      </Button>
                    </div>
                  </div>

                  {perms.length === 0 ? (
                    <EmptyState title={t('role.noPerms')} />
                  ) : (
                    <div className="kx-adm-permgrid">
                      {perms.map((p) => {
                        const on = activeRole.permissions.includes(p.permCode);
                        return (
                          <label key={p.permCode} className="kx-adm-permcheck">
                            <input
                              type="checkbox"
                              checked={on}
                              disabled={saveM.isPending}
                              onChange={(e) => togglePerm(p.permCode, e.target.checked)}
                            />
                            <span className="kx-adm-permcheck__body">
                              <span className="kx-adm-permcheck__name">{p.permName}</span>
                              <span className="kx-adm-permcheck__code">{p.permCode}</span>
                              {p.description && (
                                <span className="kx-adm-permcheck__desc">{p.description}</span>
                              )}
                            </span>
                          </label>
                        );
                      })}
                    </div>
                  )}
                </>
              ) : (
                <EmptyState title={t('role.selectRole')} />
              )}
            </section>
          </div>
        )
      )}

      {editing !== undefined && (
        <RoleModal
          role={editing}
          existingCodes={roles.map((r) => r.roleCode)}
          saving={saveM.isPending}
          onClose={() => setEditing(undefined)}
          onSubmit={(role) => saveM.mutate(role)}
        />
      )}
      {toast}
    </div>
  );
}

function RoleModal({
  role,
  existingCodes,
  saving,
  onClose,
  onSubmit,
}: {
  role: Role | null;
  existingCodes: string[];
  saving: boolean;
  onClose: () => void;
  onSubmit: (role: Role) => void;
}) {
  const { t } = useTranslation();
  const isNew = role === null;
  const [roleCode, setRoleCode] = useState(role?.roleCode ?? '');
  const [roleName, setRoleName] = useState(role?.roleName ?? '');
  const [description, setDescription] = useState(role?.description ?? '');
  const [useYn, setUseYn] = useState(role?.useYn ?? 'Y');
  const [error, setError] = useState<string | null>(null);

  function submit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    if (!roleCode.trim() || !roleName.trim()) {
      setError(t('role.errRequired'));
      return;
    }
    if (isNew && existingCodes.includes(roleCode.trim().toUpperCase())) {
      setError(t('role.errDupCode'));
      return;
    }
    onSubmit({
      roleCode: roleCode.trim().toUpperCase(),
      roleName: roleName.trim(),
      description: description.trim() || null,
      useYn,
      permissions: role?.permissions ?? [],
    });
  }

  return (
    <div className="kx-adm-modal" role="dialog" aria-modal="true" aria-labelledby="role-modal-title">
      <div className="kx-adm-modal__backdrop" onClick={onClose} />
      <form className="kx-adm-modal__panel" onSubmit={submit}>
        <h2 id="role-modal-title" className="kx-adm-modal__title">{isNew ? t('role.addRole') : t('role.editRole')}</h2>
        <p className="kx-adm-modal__desc">{t('role.modalDesc')}</p>
        <div className="kx-adm-modal__grid">
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('role.roleCode')}</span>
            <input
              className="kx-adm-field__input kx-adm-mono"
              value={roleCode}
              disabled={!isNew}
              placeholder={t('role.roleCodePh')}
              onChange={(e) => setRoleCode(e.target.value)}
            />
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('role.roleName')}</span>
            <input className="kx-adm-field__input" value={roleName} onChange={(e) => setRoleName(e.target.value)} />
          </label>
          <label className="kx-adm-field kx-adm-field--full">
            <span className="kx-adm-field__label">{t('role.description')}</span>
            <input className="kx-adm-field__input" value={description} onChange={(e) => setDescription(e.target.value)} />
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('role.useYn')}</span>
            <select className="kx-adm-field__select" value={useYn} onChange={(e) => setUseYn(e.target.value)}>
              <option value="Y">{t('role.use')}</option>
              <option value="N">{t('role.noUse')}</option>
            </select>
          </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('role.cancel')}</Button>
          <Button type="submit" disabled={saving}>{saving ? t('role.saving') : t('role.save')}</Button>
        </div>
      </form>
    </div>
  );
}
