import { useEffect, useState, useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { api } from '@common/services/api';

interface LayerAdminItem {
  layerCd: string;
  upLayerCd: string | null;
  layerFullNm: string;
  layerNm: string;
  layerLevel: number;
  wmsLayerNm: string | null;
  useYn: string;
  sortOrd: number;
  regDtm: string | null;
  parentUseYn: string | null;
}

interface LayerListResponse {
  items: LayerAdminItem[];
  total: number;
  page: number;
  totalPages: number;
}

interface LayerOption {
  layerCd: string;
  layerNm: string;
  layerFullNm: string;
  layerLevel: number;
}

interface LayerFormData {
  layerCd: string;
  upLayerCd: string;
  layerFullNm: string;
  layerNm: string;
  layerLevel: number;
  wmsLayerNm: string;
  useYn: string;
  sortOrd: number;
}

const PAGE_SIZE = 10;

async function fetchLayers(
  page: number,
  search: string,
  useYn: string,
): Promise<LayerListResponse> {
  const params = new URLSearchParams({ page: String(page), limit: String(PAGE_SIZE) });
  if (search) params.set('search', search);
  if (useYn) params.set('useYn', useYn);
  const res = await api.get<LayerListResponse>(`/layers/admin/list?${params}`);
  return res.data;
}

async function fetchLayerOptions(): Promise<LayerOption[]> {
  const res = await api.get<LayerOption[]>('/layers/admin/options');
  return res.data;
}

async function toggleLayerUse(layerCd: string): Promise<{ layerCd: string; useYn: string }> {
  const res = await api.post<{ layerCd: string; useYn: string }>('/layers/admin/toggle-use', {
    layerCd,
  });
  return res.data;
}

async function createLayer(body: LayerFormData): Promise<void> {
  await api.post('/layers/admin/create', body);
}

async function updateLayer(body: LayerFormData): Promise<void> {
  await api.post('/layers/admin/update', body);
}

async function deleteLayer(layerCd: string): Promise<void> {
  await api.post('/layers/admin/delete', { layerCd });
}

async function fetchNextLayerCode(upLayerCd: string): Promise<string> {
  const params = new URLSearchParams({ upLayerCd });
  const res = await api.get<{ nextCode: string }>(`/layers/admin/next-code?${params}`);
  return res.data.nextCode;
}

// ---------- LayerFormModal ----------

interface LayerFormModalProps {
  mode: 'create' | 'edit';
  initialData?: LayerAdminItem;
  onClose: () => void;
  onSaved: () => void;
}

const LayerFormModal = ({ mode, initialData, onClose, onSaved }: LayerFormModalProps) => {
  const [form, setForm] = useState<LayerFormData>({
    layerCd: initialData?.layerCd ?? '',
    upLayerCd: initialData?.upLayerCd ?? '',
    layerFullNm: initialData?.layerFullNm ?? '',
    layerNm: initialData?.layerNm ?? '',
    layerLevel: initialData?.layerLevel ?? 1,
    wmsLayerNm: initialData?.wmsLayerNm ?? '',
    useYn: initialData?.useYn ?? 'Y',
    sortOrd: initialData?.sortOrd ?? 0,
  });
  const [options, setOptions] = useState<LayerOption[]>([]);
  const [saving, setSaving] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);
  const [parentInfo, setParentInfo] = useState<{ fullNm: string; level: number } | null>(null);

  useEffect(() => {
    fetchLayerOptions()
      .then(setOptions)
      .catch(() => {});
  }, []);

  const handleField = <K extends keyof LayerFormData>(key: K, value: LayerFormData[K]) => {
    setForm((prev) => ({ ...prev, [key]: value }));
  };

  const handleParentChange = async (upLayerCd: string) => {
    if (!upLayerCd) {
      setParentInfo(null);
      setForm((prev) => ({ ...prev, upLayerCd: '' }));
      return;
    }
    const parent = options.find((o) => o.layerCd === upLayerCd);
    if (parent) {
      setParentInfo({ fullNm: parent.layerFullNm, level: parent.layerLevel });
      setForm((prev) => ({
        ...prev,
        upLayerCd,
        layerLevel: parent.layerLevel + 1,
        layerFullNm: prev.layerNm ? `${parent.layerFullNm} ${prev.layerNm}` : parent.layerFullNm,
      }));
    }
    try {
      const nextCode = await fetchNextLayerCode(upLayerCd);
      setForm((prev) => ({ ...prev, layerCd: nextCode }));
    } catch {
      /* 실패 시 사용자 수동 입력 */
    }
  };

  const handleLayerNmChange = (value: string) => {
    setForm((prev) => ({
      ...prev,
      layerNm: value,
      ...(parentInfo && {
        layerFullNm: value ? `${parentInfo.fullNm} ${value}` : parentInfo.fullNm,
      }),
    }));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!form.layerCd.trim()) {
      setFormError('레이어코드는 필수입니다.');
      return;
    }
    if (!form.layerNm.trim()) {
      setFormError('레이어명은 필수입니다.');
      return;
    }
    if (!form.layerFullNm.trim()) {
      setFormError('레이어전체명은 필수입니다.');
      return;
    }
    setSaving(true);
    setFormError(null);
    try {
      if (mode === 'create') {
        await createLayer(form);
      } else {
        await updateLayer(form);
      }
      onSaved();
      onClose();
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error;
      setFormError(msg ?? (mode === 'create' ? '등록에 실패했습니다.' : '수정에 실패했습니다.'));
    } finally {
      setSaving(false);
    }
  };

  const inputCls =
    'w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none';
  const labelCls = 'block text-label-2 font-semibold text-fg-sub font-korean mb-1.5';

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
      <div className="bg-bg-surface border border-stroke rounded-lg shadow-lg w-[480px] max-h-[90vh] flex flex-col">
        {/* 헤더 */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-stroke shrink-0">
          <h2 className="text-body-2 font-bold text-fg font-korean">
            {mode === 'create' ? '레이어 등록' : '레이어 수정'}
          </h2>
          <button onClick={onClose} className="text-fg-disabled hover:text-fg transition-colors">
            ✕
          </button>
        </div>
        {/* 폼 */}
        <form onSubmit={handleSubmit} className="flex-1 overflow-y-auto">
          <div className="px-6 py-4 space-y-4">
            {/* 상위 레이어코드 */}
            <div>
              <label className={labelCls}>상위 레이어코드</label>
              <select
                value={form.upLayerCd}
                onChange={(e) =>
                  mode === 'create'
                    ? handleParentChange(e.target.value)
                    : handleField('upLayerCd', e.target.value)
                }
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none"
              >
                <option value="">(없음)</option>
                {options
                  .filter((o) => o.layerCd !== form.layerCd)
                  .map((o) => (
                    <option key={o.layerCd} value={o.layerCd}>
                      {o.layerCd} — {o.layerNm}
                    </option>
                  ))}
              </select>
            </div>
            {/* 레이어코드 */}
            <div>
              <label className={labelCls}>
                레이어코드 <span className="text-red-400">*</span>
              </label>
              <input
                type="text"
                value={form.layerCd}
                onChange={(e) => handleField('layerCd', e.target.value)}
                readOnly={mode === 'edit'}
                placeholder="예: LAYER_001"
                className={`${inputCls} font-mono${mode === 'edit' ? ' bg-bg-base text-fg-disabled cursor-not-allowed' : ''}`}
              />
            </div>
            {/* 레이어명 */}
            <div>
              <label className={labelCls}>
                레이어명 <span className="text-red-400">*</span>
              </label>
              <input
                type="text"
                value={form.layerNm}
                onChange={(e) =>
                  mode === 'create'
                    ? handleLayerNmChange(e.target.value)
                    : handleField('layerNm', e.target.value)
                }
                maxLength={100}
                placeholder="레이어 이름"
                className={inputCls}
              />
            </div>
            {/* 레이어전체명 */}
            <div>
              <label className={labelCls}>
                레이어전체명 <span className="text-red-400">*</span>
              </label>
              <input
                type="text"
                value={form.layerFullNm}
                onChange={(e) => handleField('layerFullNm', e.target.value)}
                maxLength={200}
                placeholder="레이어 전체 경로명"
                className={inputCls}
              />
            </div>
            {/* 레벨 */}
            <div>
              <label className={labelCls}>레벨</label>
              <input
                type="number"
                value={form.layerLevel}
                onChange={(e) => handleField('layerLevel', Number(e.target.value))}
                min={1}
                max={10}
                className={inputCls}
              />
            </div>
            {/* WMS레이어명 */}
            <div>
              <label className={labelCls}>WMS레이어명</label>
              <input
                type="text"
                value={form.wmsLayerNm}
                onChange={(e) => handleField('wmsLayerNm', e.target.value)}
                placeholder="WMS 레이어명 (선택)"
                className={`${inputCls} font-mono`}
              />
            </div>
            {/* 정렬순서 */}
            <div>
              <label className={labelCls}>정렬순서</label>
              <input
                type="number"
                value={form.sortOrd}
                onChange={(e) => handleField('sortOrd', Number(e.target.value))}
                className={inputCls}
              />
            </div>
            {/* 사용여부 */}
            <div>
              <label className={labelCls}>사용여부</label>
              <select
                value={form.useYn}
                onChange={(e) => handleField('useYn', e.target.value)}
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none"
              >
                <option value="Y">사용</option>
                <option value="N">미사용</option>
              </select>
            </div>
          </div>
          {/* 에러 */}
          {formError && (
            <div className="px-6 pb-2">
              <p className="text-label-2 text-red-400 font-korean">{formError}</p>
            </div>
          )}
          {/* 버튼 */}
          <div className="flex items-center justify-end gap-2 px-6 py-4 border-t border-stroke shrink-0">
            <button
              type="button"
              onClick={onClose}
              className="px-3 py-1.5 text-caption border border-stroke text-fg-disabled rounded hover:bg-[rgba(255,255,255,0.04)] transition-all font-korean"
            >
              취소
            </button>
            <button
              type="submit"
              disabled={saving}
              className="px-3 py-1.5 text-caption bg-color-accent text-bg-0 rounded hover:opacity-90 disabled:opacity-50 transition-all font-korean"
            >
              {saving ? '저장 중...' : mode === 'create' ? '등록' : '저장'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
};

// ---------- LayerPanel ----------

const LayerPanel = () => {
  const queryClient = useQueryClient();
  const [items, setItems] = useState<LayerAdminItem[]>([]);
  const [total, setTotal] = useState(0);
  const [totalPages, setTotalPages] = useState(1);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [toggling, setToggling] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  // 검색
  const [searchInput, setSearchInput] = useState('');
  const [appliedSearch, setAppliedSearch] = useState('');
  const [filterUseYn, setFilterUseYn] = useState('');

  // 모달
  const [modal, setModal] = useState<{ mode: 'create' | 'edit'; data?: LayerAdminItem } | null>(
    null,
  );

  const load = useCallback(async (p: number, search: string, useYn: string) => {
    setLoading(true);
    setError(null);
    try {
      const res = await fetchLayers(p, search, useYn);
      setItems(res.items);
      setTotal(res.total);
      setTotalPages(res.totalPages);
    } catch {
      setError('레이어 목록을 불러오지 못했습니다.');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    load(page, appliedSearch, filterUseYn);
  }, [load, page, appliedSearch, filterUseYn]);

  const handleSearch = () => {
    setAppliedSearch(searchInput);
    setPage(1);
  };

  const handleToggle = async (layerCd: string) => {
    if (toggling) return;
    setToggling(layerCd);
    try {
      const result = await toggleLayerUse(layerCd);
      setItems((prev) =>
        prev.map((item) => {
          if (item.layerCd === result.layerCd) return { ...item, useYn: result.useYn };
          // 직접 자식의 parentUseYn도 즉시 동기화
          if (item.upLayerCd === result.layerCd) return { ...item, parentUseYn: result.useYn };
          return item;
        }),
      );
      // 레이어 캐시 무효화 → 예측 탭 등 useLayerTree 구독자가 최신 데이터 수신
      queryClient.invalidateQueries({ queryKey: ['layers'] });
    } catch {
      setError('사용여부 변경에 실패했습니다.');
    } finally {
      setToggling(null);
    }
  };

  const handleDelete = async (layerCd: string) => {
    if (!confirm(`레이어 [${layerCd}]를 삭제하시겠습니까?`)) return;
    try {
      await deleteLayer(layerCd);
      load(page, appliedSearch, filterUseYn);
    } catch (err: unknown) {
      const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error;
      setError(msg ?? '레이어 삭제에 실패했습니다.');
    }
  };

  const buildPageButtons = () => {
    const buttons: (number | 'ellipsis')[] = [];
    const delta = 2;
    const left = page - delta;
    const right = page + delta;

    for (let i = 1; i <= totalPages; i++) {
      if (i === 1 || i === totalPages || (i >= left && i <= right)) {
        buttons.push(i);
      } else if (buttons[buttons.length - 1] !== 'ellipsis') {
        buttons.push('ellipsis');
      }
    }
    return buttons;
  };

  return (
    <div className="flex flex-col h-full overflow-hidden">
      {/* 헤더 */}
      <div className="px-6 py-4 border-b border-stroke shrink-0">
        <div className="flex items-center justify-between mb-3">
          <div>
            <h1 className="text-lg font-bold text-fg font-korean">레이어 관리</h1>
            <p className="text-caption text-fg-disabled mt-1 font-korean">총 {total}개</p>
          </div>
          <button
            onClick={() => setModal({ mode: 'create' })}
            className="px-3 py-1.5 text-caption font-semibold bg-color-accent text-bg-0 rounded hover:opacity-90 transition-opacity font-korean"
          >
            신규 등록
          </button>
        </div>
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
            placeholder="레이어코드 / 레이어명 검색"
            className="flex-1 px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean"
          />
          <select
            value={filterUseYn}
            onChange={(e) => setFilterUseYn(e.target.value)}
            className="px-2 py-1.5 text-caption bg-bg-elevated border border-stroke rounded text-fg focus:border-color-accent focus:outline-none font-korean"
          >
            <option value="">전체</option>
            <option value="Y">사용</option>
            <option value="N">미사용</option>
          </select>
          <button
            onClick={handleSearch}
            className="px-3 py-1.5 text-caption border border-stroke text-fg-sub rounded hover:bg-[rgba(255,255,255,0.04)] transition-all font-korean"
          >
            검색
          </button>
        </div>
      </div>

      {/* 오류 메시지 */}
      {error && (
        <div className="px-6 py-2 text-caption text-red-400 bg-[rgba(239,68,68,0.05)] border-b border-stroke shrink-0 font-korean">
          {error}
        </div>
      )}

      {/* 테이블 영역 */}
      <div className="flex-1 overflow-auto">
        {loading ? (
          <div className="flex items-center justify-center h-full text-fg-disabled text-body-2 font-korean">
            불러오는 중...
          </div>
        ) : (
          <table className="w-full">
            <thead>
              <tr className="border-b border-stroke bg-bg-surface sticky top-0 z-10">
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean w-10 whitespace-nowrap">
                  번호
                </th>
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-mono">
                  레이어코드
                </th>
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                  레이어명
                </th>
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                  레이어전체명
                </th>
                <th className="px-4 py-3 text-center text-label-2 font-semibold text-fg-disabled font-korean w-12 whitespace-nowrap">
                  레벨
                </th>
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-mono">
                  WMS레이어명
                </th>
                <th className="px-4 py-3 text-center text-label-2 font-semibold text-fg-disabled font-korean w-16">
                  정렬
                </th>
                <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean w-28">
                  등록일시
                </th>
                <th className="px-4 py-3 text-center text-label-2 font-semibold text-fg-disabled font-korean w-20">
                  사용여부
                </th>
                <th className="px-4 py-3 text-center text-label-2 font-semibold text-fg-disabled font-korean w-28 whitespace-nowrap">
                  액션
                </th>
              </tr>
            </thead>
            <tbody>
              {items.length === 0 ? (
                <tr>
                  <td
                    colSpan={10}
                    className="px-4 py-12 text-center text-fg-disabled text-body-2 font-korean"
                  >
                    데이터가 없습니다.
                  </td>
                </tr>
              ) : (
                items.map((item, idx) => (
                  <tr
                    key={item.layerCd}
                    className="border-b border-stroke hover:bg-[rgba(255,255,255,0.02)] transition-colors"
                  >
                    {/* 번호 */}
                    <td className="px-4 py-3 text-caption text-fg-disabled font-mono">
                      {(page - 1) * PAGE_SIZE + idx + 1}
                    </td>
                    {/* 레이어코드 */}
                    <td className="px-4 py-3 text-label-2 text-fg-sub font-mono">{item.layerCd}</td>
                    {/* 레이어명 */}
                    <td className="px-4 py-3 text-caption text-fg font-korean">{item.layerNm}</td>
                    {/* 레이어전체명 */}
                    <td className="px-4 py-3 text-caption text-fg-sub font-korean max-w-[200px]">
                      <span className="block truncate" title={item.layerFullNm}>
                        {item.layerFullNm}
                      </span>
                    </td>
                    {/* 레벨 */}
                    <td className="px-4 py-3 text-center">
                      <span className="inline-flex items-center justify-center w-5 h-5 rounded text-caption font-semibold bg-[rgba(6,182,212,0.1)] text-color-accent border border-[rgba(6,182,212,0.3)]">
                        {item.layerLevel}
                      </span>
                    </td>
                    {/* WMS레이어명 */}
                    <td className="px-4 py-3 text-label-2 text-fg-sub font-mono">
                      {item.wmsLayerNm ?? <span className="text-fg-disabled">-</span>}
                    </td>
                    {/* 정렬순서 */}
                    <td className="px-4 py-3 text-caption text-fg-disabled text-center font-mono">
                      {item.sortOrd}
                    </td>
                    {/* 등록일시 */}
                    <td className="px-4 py-3 text-label-2 text-fg-disabled font-mono">
                      {item.regDtm ?? '-'}
                    </td>
                    {/* 사용여부 토글 */}
                    <td className="px-4 py-3 text-center">
                      <button
                        onClick={() => handleToggle(item.layerCd)}
                        disabled={toggling === item.layerCd || item.parentUseYn === 'N'}
                        title={
                          item.parentUseYn === 'N'
                            ? '상위 레이어가 비활성화되어 있어 적용되지 않습니다'
                            : item.useYn === 'Y'
                              ? '사용 중 (클릭하여 비활성화)'
                              : '미사용 (클릭하여 활성화)'
                        }
                        className={`relative inline-flex h-5 w-9 items-center rounded-full transition-colors disabled:opacity-40 ${
                          item.useYn === 'Y' && item.parentUseYn !== 'N'
                            ? 'bg-color-accent'
                            : item.useYn === 'Y' && item.parentUseYn === 'N'
                              ? 'bg-[rgba(6,182,212,0.4)]'
                              : 'bg-[rgba(255,255,255,0.08)] border border-stroke'
                        }`}
                      >
                        <span
                          className={`inline-block h-3.5 w-3.5 transform rounded-full bg-white shadow transition-transform ${
                            item.useYn === 'Y' ? 'translate-x-[18px]' : 'translate-x-0.5'
                          }`}
                        />
                      </button>
                    </td>
                    {/* 액션 */}
                    <td className="px-4 py-3 text-center">
                      <div className="flex items-center justify-center gap-1.5 flex-nowrap">
                        <button
                          onClick={() => setModal({ mode: 'edit', data: item })}
                          className="px-3 py-1 text-caption rounded bg-[rgba(6,182,212,0.15)] text-color-accent hover:bg-[rgba(6,182,212,0.25)] font-korean whitespace-nowrap"
                        >
                          수정
                        </button>
                        <button
                          onClick={() => handleDelete(item.layerCd)}
                          className="px-3 py-1 text-caption rounded bg-red-500/20 text-red-400 hover:bg-red-500/30 font-korean whitespace-nowrap"
                        >
                          삭제
                        </button>
                      </div>
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        )}
      </div>

      {/* 페이지네이션 */}
      {!loading && totalPages > 1 && (
        <div className="flex items-center justify-between px-6 py-3 border-t border-stroke bg-bg-surface shrink-0">
          <span className="text-label-2 text-fg-disabled font-korean">
            {(page - 1) * PAGE_SIZE + 1}–{Math.min(page * PAGE_SIZE, total)} / {total}개
          </span>
          <div className="flex items-center gap-1">
            <button
              onClick={() => setPage((p) => Math.max(1, p - 1))}
              disabled={page === 1}
              className="px-2.5 py-1 text-label-2 border border-stroke text-fg-disabled rounded hover:bg-[rgba(255,255,255,0.04)] disabled:opacity-40 transition-all font-korean"
            >
              이전
            </button>
            {buildPageButtons().map((btn, i) =>
              btn === 'ellipsis' ? (
                <span key={`e${i}`} className="px-1.5 text-label-2 text-fg-disabled">
                  …
                </span>
              ) : (
                <button
                  key={btn}
                  onClick={() => setPage(btn)}
                  className={`px-2.5 py-1 text-label-2 rounded transition-all ${
                    page === btn
                      ? 'bg-color-accent text-bg-0 font-semibold shadow-[0_0_8px_rgba(6,182,212,0.25)]'
                      : 'border border-stroke text-fg-disabled hover:bg-[rgba(255,255,255,0.04)]'
                  }`}
                >
                  {btn}
                </button>
              ),
            )}
            <button
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
              disabled={page === totalPages}
              className="px-2.5 py-1 text-label-2 border border-stroke text-fg-disabled rounded hover:bg-[rgba(255,255,255,0.04)] disabled:opacity-40 transition-all font-korean"
            >
              다음
            </button>
          </div>
        </div>
      )}

      {/* 모달 */}
      {modal && (
        <LayerFormModal
          mode={modal.mode}
          initialData={modal.data}
          onClose={() => setModal(null)}
          onSaved={() => load(page, appliedSearch, filterUseYn)}
        />
      )}
    </div>
  );
};

export default LayerPanel;
