import { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import { Link } from 'react-router-dom';
import { motion, AnimatePresence } from 'framer-motion';
import { useQuery } from '@tanstack/react-query';
import { Home, ChevronRight, Book, Plus, Search, ChevronDown } from 'lucide-react';
import { Toast } from '@/components/common';
import { AdminLayout, ConfirmDialog } from '@/components/pc/admin';
import { WordItem, POS_TAGS } from '@/components/pc/admin/schedule';
import { useAdminAuth } from '@/hooks/pc/admin';
import { useToast } from '@/hooks/common';
import * as suggestionsApi from '@/api/admin/suggestions';

// 애니메이션 variants
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.08,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: {
    opacity: 1,
    y: 0,
    transition: { duration: 0.4, ease: 'easeOut' },
  },
};

const cardVariants = {
  hidden: { opacity: 0, scale: 0.95 },
  visible: {
    opacity: 1,
    scale: 1,
    transition: { duration: 0.3, ease: 'easeOut' },
  },
};

function ScheduleDict() {
  const { user, isAuthenticated } = useAdminAuth();
  const { toast, setToast } = useToast();
  const [entries, setEntries] = useState([]); // [{word, pos, isComment, id}]
  const [saving, setSaving] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [filterPos, setFilterPos] = useState('all');
  const [showFilterDropdown, setShowFilterDropdown] = useState(false);

  // 새 단어 입력
  const [newWord, setNewWord] = useState('');
  const [newPos, setNewPos] = useState('NNP');
  const [showNewPosDropdown, setShowNewPosDropdown] = useState(false);

  // 드롭다운 refs
  const newPosDropdownRef = useRef(null);
  const filterDropdownRef = useRef(null);

  // 다이얼로그 상태
  const [addDialogOpen, setAddDialogOpen] = useState(false);
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
  const [wordToDelete, setWordToDelete] = useState(null); // { index, word, id }

  // 외부 클릭 시 드롭다운 닫기
  useEffect(() => {
    const handleClickOutside = (event) => {
      if (newPosDropdownRef.current && !newPosDropdownRef.current.contains(event.target)) {
        setShowNewPosDropdown(false);
      }
      if (filterDropdownRef.current && !filterDropdownRef.current.contains(event.target)) {
        setShowFilterDropdown(false);
      }
    };

    if (showNewPosDropdown || showFilterDropdown) {
      document.addEventListener('mousedown', handleClickOutside);
    }
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [showNewPosDropdown, showFilterDropdown]);

  // 필터링된 항목
  const filteredEntries = useMemo(() => {
    return entries.filter((entry) => {
      if (entry.isComment) return true; // 주석은 항상 포함 (but 표시 안함)

      const matchesSearch =
        !searchQuery || entry.word.toLowerCase().includes(searchQuery.toLowerCase());
      const matchesPos = filterPos === 'all' || entry.pos === filterPos;

      return matchesSearch && matchesPos;
    });
  }, [entries, searchQuery, filterPos]);

  // 실제 단어 항목만 (주석 제외)
  const wordEntries = useMemo(() => {
    return filteredEntries.filter((e) => !e.isComment);
  }, [filteredEntries]);

  // 품사별 통계
  const posStats = useMemo(() => {
    const stats = { total: 0 };
    entries.forEach((e) => {
      if (!e.isComment) {
        stats.total++;
        stats[e.pos] = (stats[e.pos] || 0) + 1;
      }
    });
    return stats;
  }, [entries]);

  // 고유 ID 생성
  const generateId = useCallback(
    () => `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
    []
  );

  // 사전 파일 파싱
  const parseDict = useCallback((content) => {
    const lines = content.split('\n');
    return lines
      .map((line) => {
        const trimmed = line.trim();
        if (!trimmed || trimmed.startsWith('#')) {
          return {
            isComment: true,
            raw: line,
            id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
          };
        }
        const parts = trimmed.split('\t');
        return {
          word: parts[0] || '',
          pos: parts[1] || 'NNP',
          isComment: false,
          id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
        };
      })
      .filter((e) => e.isComment || e.word); // 빈 줄 제거하되 주석은 유지
  }, []);

  // 사전 파일 생성
  const serializeDict = useCallback((entries) => {
    return entries
      .map((e) => {
        if (e.isComment) return e.raw;
        return `${e.word}\t${e.pos}`;
      })
      .join('\n');
  }, []);

  // 사전 내용 조회 (useQuery)
  const {
    data: dictContent,
    isLoading: loading,
    isError,
  } = useQuery({
    queryKey: ['admin', 'dict'],
    queryFn: async () => {
      const data = await suggestionsApi.getDict();
      return data.content || '';
    },
    enabled: isAuthenticated,
  });

  // 사전 데이터 로드 후 파싱
  useEffect(() => {
    if (dictContent !== undefined) {
      const parsed = parseDict(dictContent);
      setEntries(parsed);
    }
  }, [dictContent, parseDict]);

  // 에러 처리
  useEffect(() => {
    if (isError) {
      setToast({ type: 'error', message: '사전을 불러올 수 없습니다.' });
    }
  }, [isError, setToast]);

  // 사전 저장 (entries 배열을 받아서 저장)
  const saveDict = async (newEntries) => {
    try {
      const content = serializeDict(newEntries);
      await suggestionsApi.saveDict(content);
      return true;
    } catch (error) {
      console.error('사전 저장 오류:', error);
      setToast({ type: 'error', message: error.message || '저장 중 오류가 발생했습니다.' });
      return false;
    }
  };

  // 단어 추가 다이얼로그 열기
  const openAddDialog = () => {
    if (!newWord.trim()) return;

    // 중복 확인
    const isDuplicate = entries.some(
      (e) => !e.isComment && e.word.toLowerCase() === newWord.trim().toLowerCase()
    );
    if (isDuplicate) {
      setToast({ type: 'error', message: '이미 존재하는 단어입니다.' });
      return;
    }

    setAddDialogOpen(true);
  };

  // 단어 추가 확인
  const handleAddWord = async () => {
    setSaving(true);
    const wordToAdd = newWord.trim();
    const newEntry = { word: wordToAdd, pos: newPos, isComment: false, id: generateId() };
    const newEntries = [...entries, newEntry];

    const success = await saveDict(newEntries);
    if (success) {
      setEntries(newEntries);
      setNewWord('');
      setToast({ type: 'success', message: `"${wordToAdd}" 단어가 추가되었습니다.` });
    }
    setAddDialogOpen(false);
    setSaving(false);
  };

  // 단어 수정 (id 기반)
  const handleUpdateWord = async (id, word, pos) => {
    const entryIndex = entries.findIndex((e) => e.id === id);
    if (entryIndex === -1) return;

    const newEntries = [...entries];
    newEntries[entryIndex] = { ...newEntries[entryIndex], word, pos };

    const success = await saveDict(newEntries);
    if (success) {
      setEntries(newEntries);
    }
  };

  // 단어 삭제 다이얼로그 열기
  const openDeleteDialog = (id, word) => {
    setWordToDelete({ id, word });
    setDeleteDialogOpen(true);
  };

  // 단어 삭제 확인
  const handleDeleteWord = async () => {
    if (!wordToDelete) return;

    setSaving(true);
    const deletedWord = wordToDelete.word;
    const newEntries = entries.filter((e) => e.id !== wordToDelete.id);

    const success = await saveDict(newEntries);
    if (success) {
      setEntries(newEntries);
      setToast({ type: 'success', message: `"${deletedWord}" 단어가 삭제되었습니다.` });
    }
    setDeleteDialogOpen(false);
    setWordToDelete(null);
    setSaving(false);
  };

  // 엔터키로 추가 다이얼로그 열기
  const handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      openAddDialog();
    }
  };

  return (
    <AdminLayout user={user}>
      <Toast toast={toast} onClose={() => setToast(null)} />

      {/* 단어 추가 확인 다이얼로그 */}
      <ConfirmDialog
        isOpen={addDialogOpen}
        onClose={() => !saving && setAddDialogOpen(false)}
        onConfirm={handleAddWord}
        title="단어 추가"
        message={
          <>
            <p className="text-gray-600 mb-2">다음 단어를 추가하시겠습니까?</p>
            <div className="p-3 bg-gray-50 rounded-lg">
              <p className="font-medium text-gray-900">{newWord}</p>
              <p className="text-sm text-gray-500 mt-1">
                {POS_TAGS.find((t) => t.value === newPos)?.label}
              </p>
            </div>
          </>
        }
        confirmText="추가"
        loadingText="추가 중..."
        loading={saving}
        variant="primary"
        icon={Plus}
      />

      {/* 단어 삭제 확인 다이얼로그 */}
      <ConfirmDialog
        isOpen={deleteDialogOpen}
        onClose={() => {
          if (!saving) {
            setDeleteDialogOpen(false);
            setWordToDelete(null);
          }
        }}
        onConfirm={handleDeleteWord}
        title="단어 삭제"
        message={
          <>
            <p className="text-gray-600 mb-2">다음 단어를 삭제하시겠습니까?</p>
            <p className="font-medium text-gray-900 p-3 bg-gray-50 rounded-lg">{wordToDelete?.word}</p>
          </>
        }
        confirmText="삭제"
        loadingText="삭제 중..."
        loading={saving}
        variant="danger"
      />

      {/* 메인 콘텐츠 */}
      <motion.div
        className="max-w-5xl mx-auto px-6 py-8"
        variants={containerVariants}
        initial="hidden"
        animate="visible"
      >
        {/* 브레드크럼 */}
        <motion.div variants={itemVariants} className="flex items-center gap-2 text-sm text-gray-400 mb-8">
          <Link to="/admin/dashboard" className="hover:text-primary transition-colors">
            <Home size={16} />
          </Link>
          <ChevronRight size={14} />
          <Link to="/admin/schedule" className="hover:text-primary transition-colors">
            일정 관리
          </Link>
          <ChevronRight size={14} />
          <span className="text-gray-700">사전 관리</span>
        </motion.div>

        {/* 타이틀 */}
        <motion.div variants={itemVariants} className="mb-8">
          <h1 className="text-3xl font-bold text-gray-900 mb-2">사전 관리</h1>
          <p className="text-gray-500">형태소 분석기 사용자 사전을 관리합니다</p>
        </motion.div>

        {/* 통계 카드 */}
        <motion.div variants={itemVariants} className="grid grid-cols-4 gap-4 mb-6">
          <motion.div variants={cardVariants} className="bg-white rounded-xl p-4 border border-gray-100">
            <div className="text-2xl font-bold text-gray-900">{posStats.total || 0}</div>
            <div className="text-sm text-gray-500">전체 단어</div>
          </motion.div>
          <motion.div variants={cardVariants} className="bg-white rounded-xl p-4 border border-gray-100">
            <div className="text-2xl font-bold text-blue-500">{posStats.NNP || 0}</div>
            <div className="text-sm text-gray-500">고유명사</div>
          </motion.div>
          <motion.div variants={cardVariants} className="bg-white rounded-xl p-4 border border-gray-100">
            <div className="text-2xl font-bold text-green-500">{posStats.NNG || 0}</div>
            <div className="text-sm text-gray-500">일반명사</div>
          </motion.div>
          <motion.div variants={cardVariants} className="bg-white rounded-xl p-4 border border-gray-100">
            <div className="text-2xl font-bold text-purple-500">{posStats.SL || 0}</div>
            <div className="text-sm text-gray-500">외국어</div>
          </motion.div>
        </motion.div>

        {/* 단어 추가 영역 */}
        <motion.div
          variants={itemVariants}
          className="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 mb-6"
        >
          <h3 className="font-bold text-gray-900 mb-4">단어 추가</h3>
          <div className="flex items-center gap-3">
            <div className="flex-1">
              <input
                type="text"
                value={newWord}
                onChange={(e) => setNewWord(e.target.value)}
                onKeyDown={handleKeyDown}
                placeholder="추가할 단어 입력..."
                className="w-full px-4 py-3 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-colors"
              />
            </div>
            <div className="relative w-48" ref={newPosDropdownRef}>
              <button
                onClick={() => setShowNewPosDropdown(!showNewPosDropdown)}
                className="flex items-center gap-2 px-4 py-3 bg-gray-100 hover:bg-gray-200 rounded-xl text-sm transition-colors w-full justify-between"
              >
                <span>{POS_TAGS.find((t) => t.value === newPos)?.label.split(' ')[0]}</span>
                <ChevronDown
                  size={14}
                  className={`transition-transform ${showNewPosDropdown ? 'rotate-180' : ''}`}
                />
              </button>
              <AnimatePresence>
                {showNewPosDropdown && (
                  <motion.div
                    initial={{ opacity: 0, y: -5 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: -5 }}
                    className="absolute top-full left-0 mt-1 w-64 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-40"
                  >
                    {POS_TAGS.map((tag) => (
                      <button
                        key={tag.value}
                        onClick={() => {
                          setNewPos(tag.value);
                          setShowNewPosDropdown(false);
                        }}
                        className={`w-full px-4 py-2.5 text-left hover:bg-gray-50 transition-colors ${
                          newPos === tag.value ? 'bg-primary/5 text-primary' : ''
                        }`}
                      >
                        <div className="font-medium text-sm">{tag.label}</div>
                        <div className="text-xs text-gray-400">{tag.description}</div>
                        <div className="text-xs text-gray-300 mt-0.5">예: {tag.examples}</div>
                      </button>
                    ))}
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
            <button
              onClick={openAddDialog}
              disabled={!newWord.trim()}
              className="flex items-center gap-2 px-6 py-3 bg-primary text-white rounded-xl hover:bg-primary-dark transition-colors font-medium disabled:opacity-50 disabled:cursor-not-allowed"
            >
              <Plus size={20} />
              추가
            </button>
          </div>
        </motion.div>

        {/* 단어 목록 */}
        <motion.div
          variants={itemVariants}
          className="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden"
        >
          {/* 검색 및 필터 */}
          <div className="p-4 border-b border-gray-100 flex items-center gap-4">
            <div className="flex-1 relative">
              <Search size={18} className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400" />
              <input
                type="text"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                placeholder="단어 검색..."
                className="w-full pl-11 pr-4 py-2.5 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary transition-colors"
              />
            </div>
            <div className="relative" ref={filterDropdownRef}>
              <button
                onClick={() => setShowFilterDropdown(!showFilterDropdown)}
                className="flex items-center gap-2 px-4 py-2.5 bg-gray-100 hover:bg-gray-200 rounded-xl text-sm transition-colors"
              >
                <span>
                  {filterPos === 'all'
                    ? '전체 품사'
                    : POS_TAGS.find((t) => t.value === filterPos)?.label.split(' ')[0]}
                </span>
                <ChevronDown
                  size={14}
                  className={`transition-transform ${showFilterDropdown ? 'rotate-180' : ''}`}
                />
              </button>
              <AnimatePresence>
                {showFilterDropdown && (
                  <motion.div
                    initial={{ opacity: 0, y: -5 }}
                    animate={{ opacity: 1, y: 0 }}
                    exit={{ opacity: 0, y: -5 }}
                    className="absolute top-full right-0 mt-1 w-48 bg-white rounded-xl shadow-lg border border-gray-200 py-1 z-40"
                  >
                    <button
                      onClick={() => {
                        setFilterPos('all');
                        setShowFilterDropdown(false);
                      }}
                      className={`w-full px-4 py-2 text-left hover:bg-gray-50 transition-colors text-sm ${
                        filterPos === 'all' ? 'bg-primary/5 text-primary' : ''
                      }`}
                    >
                      전체 품사
                    </button>
                    {POS_TAGS.map((tag) => (
                      <button
                        key={tag.value}
                        onClick={() => {
                          setFilterPos(tag.value);
                          setShowFilterDropdown(false);
                        }}
                        className={`w-full px-4 py-2 text-left hover:bg-gray-50 transition-colors text-sm ${
                          filterPos === tag.value ? 'bg-primary/5 text-primary' : ''
                        }`}
                      >
                        {tag.label.split(' ')[0]}
                      </button>
                    ))}
                  </motion.div>
                )}
              </AnimatePresence>
            </div>
          </div>

          {/* 테이블 */}
          {loading ? (
            <div className="flex justify-center items-center py-20">
              <div className="animate-spin rounded-full h-10 w-10 border-4 border-primary border-t-transparent"></div>
            </div>
          ) : wordEntries.length === 0 ? (
            <div className="text-center py-20 text-gray-400">
              <Book size={48} className="mx-auto mb-4 opacity-30" />
              <p>{searchQuery || filterPos !== 'all' ? '검색 결과가 없습니다' : '등록된 단어가 없습니다'}</p>
              <p className="text-sm mt-1">위의 입력창에서 단어를 추가하세요</p>
            </div>
          ) : (
            <div className="overflow-x-auto max-h-[500px] overflow-y-auto">
              <table className="w-full">
                <thead className="bg-gray-50 sticky top-0 z-30">
                  <tr>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-16">
                      #
                    </th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                      단어
                    </th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-48">
                      품사
                    </th>
                    <th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider w-20"></th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-gray-100">
                  <AnimatePresence>
                    {wordEntries.map((entry, index) => (
                      <WordItem
                        key={entry.id}
                        id={entry.id}
                        word={entry.word}
                        pos={entry.pos}
                        index={index}
                        onUpdate={handleUpdateWord}
                        onDelete={() => openDeleteDialog(entry.id, entry.word)}
                      />
                    ))}
                  </AnimatePresence>
                </tbody>
              </table>
            </div>
          )}

          {/* 푸터 */}
          {wordEntries.length > 0 && (
            <div className="px-4 py-3 bg-gray-50 border-t border-gray-100 text-sm text-gray-500">
              {searchQuery || filterPos !== 'all' ? (
                <span>
                  {wordEntries.length}개 검색됨 (전체 {posStats.total}개)
                </span>
              ) : (
                <span>총 {posStats.total}개 단어</span>
              )}
            </div>
          )}
        </motion.div>
      </motion.div>
    </AdminLayout>
  );
}

export default ScheduleDict;
