/*
 * SCR-A6 시스템설정 (M18 · §5B-1). Stitch scr_a6 이식 + 라이브 백엔드 실배선.
 * 정본: GET/POST /api/admin/settings, DELETE /{key} (SettingController). 백엔드는 범용 key/value 저장소.
 * 보안: secretYn='Y' 값은 백엔드가 ******** 로 마스킹해 도착 → 화면은 마스킹 유지, 신규 입력이 있을 때만 저장 전송(원문 미노출·미상실).
 * Stitch 의 그룹 카드(마감정책·AI게이트·알림·보안)는 개념 매핑 — 실제 렌더는 key 접두어(prefix)로 그룹화한 실데이터.
 * 상태: 로딩 스켈레톤 / 빈 / 에러(재시도).
 */
import { useMemo, 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 { settingApi, type SettingRow, type SettingSaveBody } from './adminModulesApi';
import './admin-modules.css';

const VALUE_TYPES = ['STRING', 'NUMBER', 'BOOLEAN', 'JSON'];
const GENERAL_GROUP = '__general__';

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

  const q = useQuery({ queryKey: ['admin-settings'], queryFn: settingApi.list, retry: false });

  const saveM = useMutation({
    mutationFn: (body: SettingSaveBody) => settingApi.save(body),
    onSuccess: () => {
      show(t('settings.saved'));
      qc.invalidateQueries({ queryKey: ['admin-settings'] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const delM = useMutation({
    mutationFn: (key: string) => settingApi.remove(key),
    onSuccess: () => {
      show(t('settings.deleted'));
      qc.invalidateQueries({ queryKey: ['admin-settings'] });
    },
    onError: (e) => show(errMessage(e)),
  });

  const groups = useMemo(() => groupByPrefix(q.data ?? []), [q.data]);

  return (
    <div className="kx-page kx-adm">
      <header className="kx-adm__head">
        <div>
          <h1 className="kx-adm__title">{t('settings.title')}</h1>
          <p className="kx-adm__subtitle">
            {t('settings.subtitle')}
          </p>
        </div>
      </header>

      {q.isLoading && <SettingsSkeleton />}

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

      {!q.isLoading && !q.isError && (
        <>
          {(q.data ?? []).length === 0 ? (
            <EmptyState
              title={t('settings.emptyTitle')}
              description={t('settings.emptyDesc')}
            />
          ) : (
            <div className="kx-adm-settings">
              {groups.map((g) => (
                <SettingGroupCard
                  key={g.name}
                  name={g.name}
                  rows={g.rows}
                  saving={saveM.isPending}
                  deleting={delM.isPending}
                  onSave={(b) => saveM.mutate(b)}
                  onDelete={(k) => {
                    if (window.confirm(t('settings.deleteConfirm', { key: k }))) delM.mutate(k);
                  }}
                />
              ))}
            </div>
          )}

          <AddSettingCard saving={saveM.isPending} onSave={(b) => saveM.mutate(b)} />
        </>
      )}
      {toast}
    </div>
  );
}

function SettingGroupCard({
  name,
  rows,
  saving,
  deleting,
  onSave,
  onDelete,
}: {
  name: string;
  rows: SettingRow[];
  saving: boolean;
  deleting: boolean;
  onSave: (b: SettingSaveBody) => void;
  onDelete: (key: string) => void;
}) {
  const { t } = useTranslation();
  const displayName = name === GENERAL_GROUP ? t('settings.general') : name;
  return (
    <section className="kx-card kx-adm-group" aria-label={t('settings.groupAria', { name: displayName })}>
      <div className="kx-adm-group__accent" aria-hidden="true" />
      <div className="kx-adm-group__body">
        <h2 className="kx-adm-group__title">{displayName}</h2>
        <ul className="kx-adm-setrows">
          {rows.map((r) => (
            <SettingRowItem
              key={r.settingKey}
              row={r}
              saving={saving}
              deleting={deleting}
              onSave={onSave}
              onDelete={onDelete}
            />
          ))}
        </ul>
      </div>
    </section>
  );
}

function SettingRowItem({
  row,
  saving,
  deleting,
  onSave,
  onDelete,
}: {
  row: SettingRow;
  saving: boolean;
  deleting: boolean;
  onSave: (b: SettingSaveBody) => void;
  onDelete: (key: string) => void;
}) {
  const { t } = useTranslation();
  const isSecret = row.secretYn === 'Y';
  const isBool = (row.valueType ?? '').toUpperCase() === 'BOOLEAN';
  // 시크릿: 입력 비움 상태에서 시작(마스킹 값을 재저장하지 않기 위함). 비-시크릿: 현재값 편집.
  const [val, setVal] = useState<string>(isSecret ? '' : row.settingValue ?? '');
  const [dirty, setDirty] = useState(false);

  const boolChecked = String(row.settingValue ?? '').toLowerCase() === 'true';

  function submit(nextValue: string) {
    onSave({
      settingKey: row.settingKey,
      settingValue: nextValue,
      valueType: row.valueType,
      description: row.description,
      secretYn: row.secretYn,
    });
    setDirty(false);
  }

  return (
    <li className="kx-adm-setrow">
      <div className="kx-adm-setrow__meta">
        <span className="kx-adm-setrow__key">
          {row.settingKey}
          {isSecret && <span className="kx-adm-secret" title={t('settings.secretTitle')}>{t('settings.secret')}</span>}
          {row.valueType && <span className="kx-adm-typechip">{row.valueType}</span>}
        </span>
        {row.description && <span className="kx-adm-setrow__desc">{row.description}</span>}
      </div>

      <div className="kx-adm-setrow__control">
        {isBool ? (
          <label className="kx-adm-switch">
            <input
              type="checkbox"
              checked={boolChecked}
              disabled={saving}
              onChange={(e) => submit(e.target.checked ? 'true' : 'false')}
            />
            <span className="kx-adm-switch__track" aria-hidden="true" />
            <span className="kx-adm-switch__label">{boolChecked ? t('settings.on') : t('settings.off')}</span>
          </label>
        ) : (
          <>
            <input
              className="kx-adm-field__input kx-adm-setrow__input"
              type={isSecret ? 'password' : 'text'}
              value={val}
              placeholder={isSecret ? t('settings.secretPh') : ''}
              autoComplete={isSecret ? 'new-password' : 'off'}
              onChange={(e) => {
                setVal(e.target.value);
                setDirty(true);
              }}
            />
            <Button
              variant="secondary"
              disabled={saving || !dirty || (isSecret && val.trim() === '')}
              onClick={() => submit(val)}
            >
              {t('settings.save')}
            </Button>
          </>
        )}
        <Button
          variant="ghost"
          className="kx-adm-del"
          disabled={deleting}
          onClick={() => onDelete(row.settingKey)}
          aria-label={t('settings.deleteKey', { key: row.settingKey })}
        >
          {t('settings.delete')}
        </Button>
      </div>
      {isSecret && (
        <p className="kx-adm-setrow__hint">
          {t('settings.secretHint')}
        </p>
      )}
    </li>
  );
}

function AddSettingCard({
  saving,
  onSave,
}: {
  saving: boolean;
  onSave: (b: SettingSaveBody) => void;
}) {
  const { t } = useTranslation();
  const [key, setKey] = useState('');
  const [value, setValue] = useState('');
  const [type, setType] = useState('STRING');
  const [desc, setDesc] = useState('');
  const [secret, setSecret] = useState(false);

  const canSave = key.trim() !== '';

  function submit() {
    if (!canSave) return;
    onSave({
      settingKey: key.trim(),
      settingValue: value,
      valueType: type,
      description: desc || null,
      secretYn: secret ? 'Y' : 'N',
    });
    setKey('');
    setValue('');
    setDesc('');
    setSecret(false);
    setType('STRING');
  }

  return (
    <section className="kx-card kx-adm-add" aria-label={t('settings.addAria')}>
      <h2 className="kx-adm-add__title">{t('settings.addTitle')}</h2>
      <div className="kx-adm-add__grid">
        <label className="kx-adm-field">
          <span className="kx-adm-field__label">{t('settings.settingKey')}</span>
          <input
            className="kx-adm-field__input"
            placeholder={t('settings.settingKeyPh')}
            value={key}
            onChange={(e) => setKey(e.target.value)}
          />
        </label>
        <label className="kx-adm-field">
          <span className="kx-adm-field__label">{t('settings.value')}</span>
          <input
            className="kx-adm-field__input"
            type={secret ? 'password' : 'text'}
            value={value}
            onChange={(e) => setValue(e.target.value)}
          />
        </label>
        <label className="kx-adm-field">
          <span className="kx-adm-field__label">{t('settings.type')}</span>
          <select className="kx-select" value={type} onChange={(e) => setType(e.target.value)}>
            {VALUE_TYPES.map((vt) => (
              <option key={vt} value={vt}>
                {vt}
              </option>
            ))}
          </select>
        </label>
        <label className="kx-adm-field kx-adm-add__desc">
          <span className="kx-adm-field__label">{t('settings.description')}</span>
          <input
            className="kx-adm-field__input"
            value={desc}
            onChange={(e) => setDesc(e.target.value)}
          />
        </label>
        <label className="kx-adm-check">
          <input type="checkbox" checked={secret} onChange={(e) => setSecret(e.target.checked)} />
          {t('settings.secretCheck')}
        </label>
        <div className="kx-adm-add__actions">
          <Button leadingIcon={<IconPlus size={16} />} disabled={saving || !canSave} onClick={submit}>
            {t('settings.save')}
          </Button>
        </div>
      </div>
    </section>
  );
}

function SettingsSkeleton() {
  return (
    <div aria-hidden="true" style={{ display: 'grid', gap: 16 }}>
      {[0, 1].map((i) => (
        <Skeleton key={i} height={160} radius={8} />
      ))}
    </div>
  );
}

/** settingKey 의 '.' 앞 접두어로 그룹화. 접두어 없으면 '일반'. */
function groupByPrefix(rows: SettingRow[]): { name: string; rows: SettingRow[] }[] {
  const map = new Map<string, SettingRow[]>();
  for (const r of rows) {
    const dot = r.settingKey.indexOf('.');
    const name = dot > 0 ? r.settingKey.slice(0, dot) : GENERAL_GROUP;
    const arr = map.get(name) ?? [];
    arr.push(r);
    map.set(name, arr);
  }
  return [...map.entries()]
    .map(([name, rs]) => ({ name, rows: rs.sort((a, b) => a.settingKey.localeCompare(b.settingKey)) }))
    .sort((a, b) => a.name.localeCompare(b.name));
}
