/*
 * M18 시스템관리 '메시지 관리' (#35 · 소유자 지시 6.6). MessageController 실배선.
 * UI: 분류/로케일 필터 + 검색 → 템플릿 테이블 → 편집 모달(upsert) · 렌더 미리보기 모달({key} 파라미터 치환).
 * 컨벤션: CommonCodeAdminPage 와 동일(kx-adm · react-query · admin-modules.css 재사용, 신규 CSS 없음).
 */
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 {
  MESSAGE_CATEGORIES,
  MESSAGE_LOCALES,
  extractPlaceholders,
  messageApi,
  type SysMessage,
} from './messageAdminApi';
import './admin-modules.css';

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

  const [category, setCategory] = useState('');
  const [locale, setLocale] = useState('');
  const [keyword, setKeyword] = useState('');
  const [editModal, setEditModal] = useState<SysMessage | null | undefined>(undefined);
  const [previewModal, setPreviewModal] = useState<SysMessage | undefined>(undefined);

  const listQ = useQuery({
    queryKey: ['admin-messages', category, locale],
    queryFn: () => messageApi.list({ category: category || undefined, locale: locale || undefined }),
    retry: false,
  });

  const saveM = useMutation({
    mutationFn: (m: SysMessage) => messageApi.save(m),
    onSuccess: () => {
      show(t('msg.saved'));
      setEditModal(undefined);
      qc.invalidateQueries({ queryKey: ['admin-messages'] });
    },
    onError: (e) => show(errMessage(e)),
  });
  const delM = useMutation({
    mutationFn: ({ code, loc }: { code: string; loc: string | null }) =>
      messageApi.remove(code, loc ?? undefined),
    onSuccess: () => {
      show(t('msg.deleted'));
      qc.invalidateQueries({ queryKey: ['admin-messages'] });
    },
    onError: (e) => show(errMessage(e)),
  });

  const rows = listQ.data ?? [];
  const categories = useMemo(() => {
    const merged = new Set<string>(MESSAGE_CATEGORIES);
    rows.forEach((r) => merged.add(r.category));
    return Array.from(merged);
  }, [rows]);

  const filtered = useMemo(() => {
    const kw = keyword.trim().toLowerCase();
    if (!kw) return rows;
    return rows.filter(
      (r) =>
        r.msgCode.toLowerCase().includes(kw) ||
        r.title.toLowerCase().includes(kw) ||
        r.template.toLowerCase().includes(kw),
    );
  }, [rows, keyword]);

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

      <section className="kx-card kx-adm-filter" aria-label={t('msg.filterAria')}>
        <div className="kx-adm-filter__grid">
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.category')}</span>
            <select className="kx-adm-field__select" value={category} onChange={(e) => setCategory(e.target.value)}>
              <option value="">{t('msg.allCategories')}</option>
              {categories.map((c) => (
                <option key={c} value={c}>{c}</option>
              ))}
            </select>
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.locale')}</span>
            <select className="kx-adm-field__select" value={locale} onChange={(e) => setLocale(e.target.value)}>
              <option value="">{t('msg.allLocales')}</option>
              {MESSAGE_LOCALES.map((l) => (
                <option key={l} value={l}>{l}</option>
              ))}
            </select>
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.search')}</span>
            <input
              className="kx-adm-field__input"
              placeholder={t('msg.searchPlaceholder')}
              value={keyword}
              onChange={(e) => setKeyword(e.target.value)}
            />
          </label>
        </div>
      </section>

      {listQ.isLoading && <Skeleton height={320} radius={12} />}
      {listQ.isError && !listQ.isLoading && (
        <ErrorState message={t('msg.loadError')} onRetry={() => listQ.refetch()} />
      )}

      {!listQ.isLoading && !listQ.isError && (
        filtered.length === 0 ? (
          <EmptyState title={t('msg.emptyTitle')} description={t('msg.emptyDesc')} />
        ) : (
          <section className="kx-card" aria-label={t('msg.title')}>
            <div className="kx-table-scroll">
              <table className="kx-table kx-table--zebra kx-adm-tbl">
                <thead>
                  <tr>
                    <th>{t('msg.code')}</th>
                    <th>{t('msg.locale')}</th>
                    <th>{t('msg.category')}</th>
                    <th>{t('msg.msgTitle')}</th>
                    <th>{t('msg.placeholders')}</th>
                    <th>{t('msg.use')}</th>
                    <th style={{ textAlign: 'right' }}>{t('msg.manage')}</th>
                  </tr>
                </thead>
                <tbody>
                  {filtered.map((m) => {
                    const params = extractPlaceholders(m.template);
                    return (
                      <tr key={`${m.msgCode}:${m.locale}`}>
                        <td className="kx-adm-mono">{m.msgCode}</td>
                        <td className="kx-adm-mono">{m.locale ?? 'ko'}</td>
                        <td className="kx-adm-muted">{m.category}</td>
                        <td className="kx-adm-tbl__strong">{m.title}</td>
                        <td className="kx-adm-muted kx-adm-mono">
                          {params.length > 0 ? params.map((p) => `{${p}}`).join(' ') : '—'}
                        </td>
                        <td>
                          <span className={`kx-adm-pill kx-adm-pill--${m.useYn === 'N' ? 'neutral' : 'success'}`}>
                            {m.useYn === 'N' ? t('msg.unused') : t('msg.used')}
                          </span>
                        </td>
                        <td>
                          <div className="kx-adm-tbl__actions">
                            <Button variant="ghost" onClick={() => setPreviewModal(m)}>{t('msg.preview')}</Button>
                            <Button variant="ghost" onClick={() => setEditModal(m)}>{t('msg.edit')}</Button>
                            <Button
                              variant="ghost"
                              className="kx-adm-del"
                              disabled={delM.isPending}
                              onClick={() => {
                                if (window.confirm(t('msg.deleteConfirm', { code: m.msgCode, locale: m.locale ?? 'ko' })))
                                  delM.mutate({ code: m.msgCode, loc: m.locale });
                              }}
                            >
                              {t('msg.delete')}
                            </Button>
                          </div>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </section>
        )
      )}

      {editModal !== undefined && (
        <EditModal
          msg={editModal}
          categories={categories}
          saving={saveM.isPending}
          onClose={() => setEditModal(undefined)}
          onSubmit={(m) => saveM.mutate(m)}
        />
      )}
      {previewModal !== undefined && (
        <PreviewModal msg={previewModal} onClose={() => setPreviewModal(undefined)} />
      )}
      {toast}
    </div>
  );
}

function EditModal({
  msg,
  categories,
  saving,
  onClose,
  onSubmit,
}: {
  msg: SysMessage | null;
  categories: string[];
  saving: boolean;
  onClose: () => void;
  onSubmit: (m: SysMessage) => void;
}) {
  const { t } = useTranslation();
  const isNew = msg === null;
  const [msgCode, setMsgCode] = useState(msg?.msgCode ?? '');
  const [loc, setLoc] = useState(msg?.locale ?? 'ko');
  const [category, setCategory] = useState(msg?.category ?? categories[0] ?? 'ACCOUNT');
  const [title, setTitle] = useState(msg?.title ?? '');
  const [template, setTemplate] = useState(msg?.template ?? '');
  const [useYn, setUseYn] = useState(msg?.useYn ?? 'Y');
  const [error, setError] = useState<string | null>(null);

  const params = extractPlaceholders(template);

  function submit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    if (!msgCode.trim() || !title.trim() || !template.trim()) {
      setError(t('msg.errRequired'));
      return;
    }
    onSubmit({
      msgCode: msgCode.trim().toUpperCase(),
      locale: loc,
      category: category.trim().toUpperCase(),
      title: title.trim(),
      template,
      useYn,
      updatedAt: null,
    });
  }

  return (
    <div className="kx-adm-modal" role="dialog" aria-modal="true" aria-labelledby="msg-modal-title">
      <div className="kx-adm-modal__backdrop" onClick={onClose} />
      <form className="kx-adm-modal__panel" onSubmit={submit}>
        <h2 id="msg-modal-title" className="kx-adm-modal__title">{isNew ? t('msg.add') : t('msg.edit')}</h2>
        <div className="kx-adm-modal__grid">
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.code')}</span>
            <input
              className="kx-adm-field__input kx-adm-mono"
              value={msgCode}
              disabled={!isNew}
              placeholder="AUCTION_INVITE"
              onChange={(e) => setMsgCode(e.target.value)}
            />
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.locale')}</span>
            <select className="kx-adm-field__select" value={loc} disabled={!isNew} onChange={(e) => setLoc(e.target.value)}>
              {MESSAGE_LOCALES.map((l) => (
                <option key={l} value={l}>{l}</option>
              ))}
            </select>
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.category')}</span>
            <input
              className="kx-adm-field__input kx-adm-mono"
              value={category}
              list="msg-category-options"
              onChange={(e) => setCategory(e.target.value)}
            />
            <datalist id="msg-category-options">
              {categories.map((c) => (
                <option key={c} value={c} />
              ))}
            </datalist>
          </label>
          <label className="kx-adm-field">
            <span className="kx-adm-field__label">{t('msg.useYn')}</span>
            <select className="kx-adm-field__select" value={useYn ?? 'Y'} onChange={(e) => setUseYn(e.target.value)}>
              <option value="Y">{t('msg.used')}</option>
              <option value="N">{t('msg.unused')}</option>
            </select>
          </label>
          <label className="kx-adm-field kx-adm-field--full">
            <span className="kx-adm-field__label">{t('msg.msgTitle')}</span>
            <input className="kx-adm-field__input" value={title} onChange={(e) => setTitle(e.target.value)} />
          </label>
          <label className="kx-adm-field kx-adm-field--full">
            <span className="kx-adm-field__label">{t('msg.template')}</span>
            <textarea
              className="kx-adm-field__input"
              rows={5}
              value={template}
              placeholder={t('msg.templatePlaceholder')}
              onChange={(e) => setTemplate(e.target.value)}
            />
          </label>
          {params.length > 0 && (
            <p className="kx-adm-muted kx-adm-field--full">
              {t('msg.detectedParams')}: <span className="kx-adm-mono">{params.map((p) => `{${p}}`).join(' ')}</span>
            </p>
          )}
        </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('msg.cancel')}</Button>
          <Button type="submit" disabled={saving}>{saving ? t('msg.saving') : t('msg.save')}</Button>
        </div>
      </form>
    </div>
  );
}

function PreviewModal({ msg, onClose }: { msg: SysMessage; onClose: () => void }) {
  const { t } = useTranslation();
  const params = extractPlaceholders(msg.template);
  const [values, setValues] = useState<Record<string, string>>({});
  const renderM = useMutation({
    mutationFn: () => messageApi.render(msg.msgCode, msg.locale, values),
  });

  return (
    <div className="kx-adm-modal" role="dialog" aria-modal="true" aria-labelledby="msg-preview-title">
      <div className="kx-adm-modal__backdrop" onClick={onClose} />
      <div className="kx-adm-modal__panel">
        <h2 id="msg-preview-title" className="kx-adm-modal__title">{t('msg.preview')}</h2>
        <p className="kx-adm-modal__desc">
          <span className="kx-adm-mono">{msg.msgCode}</span> · {msg.locale ?? 'ko'} · {msg.category}
        </p>
        <div className="kx-adm-modal__grid">
          <label className="kx-adm-field kx-adm-field--full">
            <span className="kx-adm-field__label">{t('msg.template')}</span>
            <textarea className="kx-adm-field__input kx-adm-mono" rows={4} value={msg.template} readOnly />
          </label>
          {params.map((p) => (
            <label key={p} className="kx-adm-field">
              <span className="kx-adm-field__label kx-adm-mono">{`{${p}}`}</span>
              <input
                className="kx-adm-field__input"
                value={values[p] ?? ''}
                onChange={(e) => setValues((v) => ({ ...v, [p]: e.target.value }))}
              />
            </label>
          ))}
          {params.length === 0 && <p className="kx-adm-muted kx-adm-field--full">{t('msg.noParams')}</p>}
          {renderM.data && (
            <div className="kx-adm-field--full">
              <span className="kx-adm-field__label">{t('msg.renderResult')}</span>
              <p className="kx-card" style={{ padding: 12, whiteSpace: 'pre-wrap' }}>{renderM.data.text}</p>
            </div>
          )}
          {renderM.isError && (
            <p className="kx-adm-modal__error kx-adm-field--full" role="alert">{errMessage(renderM.error)}</p>
          )}
        </div>
        <div className="kx-adm-modal__actions">
          <Button variant="ghost" type="button" onClick={onClose}>{t('msg.close')}</Button>
          <Button type="button" disabled={renderM.isPending} onClick={() => renderM.mutate()}>
            {renderM.isPending ? t('msg.rendering') : t('msg.render')}
          </Button>
        </div>
      </div>
    </div>
  );
}
