import { useEffect, useRef, useState } from 'react'
import {
  deleteReviewItem,
  getReviewItem,
  getReviewPage,
  importReview,
  reviewDownloadUrl,
  updateReviewJudgment,
  type JudgmentRequest,
  type Org,
  type ReviewImportReport,
  type ReviewItem,
} from '../api/client'

const PAGE_SIZE = 30

const REVIEW_MAJOR_OPTIONS = ['만료 저작물', '업무상 저작물', '제3자 권리', '개인정보 포함']

const REVIEW_MINOR_OPTIONS = [
  '1. 원시적 권리 전부 보유',
  '2. 후천적 권리 전부 보유(계약서 확인 필요)',
  '3. 권리 일부(공동) 보유',
  '4. 권리 미보유',
  '초상권 포함',
]

const REVIEW_RESULT_OPTIONS = ['신유형 개방', '계약서 등 재확인', '권리처리 추진', '개방불가']

const JUDGED_KOGL_TYPE_OPTIONS = ['0유형', '1유형', '2유형', '3유형', '4유형', '개방불가']

const REVIEW_RESULT_BADGE_STYLES: Record<string, string> = {
  '신유형 개방': 'bg-emerald-50 text-emerald-700',
  '계약서 등 재확인': 'bg-amber-50 text-amber-700',
  '권리처리 추진': 'bg-blue-50 text-blue-700',
  개방불가: 'bg-red-50 text-red-700',
}

/** 대분류/세부 선택에 따른 처리결과 추천값. 매칭되는 조합이 없으면 null(현재 값 유지). */
function suggestReviewResult(major: string, minor: string): string | null {
  if (major === '만료 저작물' || major === '업무상 저작물') {
    return '신유형 개방'
  }
  if (major === '개인정보 포함') {
    return '개방불가'
  }
  if (major === '제3자 권리') {
    if (minor === '1. 원시적 권리 전부 보유') {
      return '신유형 개방'
    }
    if (minor === '2. 후천적 권리 전부 보유(계약서 확인 필요)') {
      return '계약서 등 재확인'
    }
    if (minor === '3. 권리 일부(공동) 보유' || minor === '4. 권리 미보유' || minor === '초상권 포함') {
      return '권리처리 추진'
    }
  }
  return null
}

function Field({ label, value }: { label: string; value: string | null }) {
  return (
    <div className="flex gap-3 text-sm">
      <span className="w-24 shrink-0 text-gray-400">{label}</span>
      <span className={value ? 'text-gray-900' : 'text-gray-300'}>{value ?? '-'}</span>
    </div>
  )
}

function RadioGroup({
  legend,
  name,
  options,
  value,
  onChange,
  disabled,
}: {
  legend: string
  name: string
  options: string[]
  value: string
  onChange: (value: string) => void
  disabled?: boolean
}) {
  return (
    <fieldset className="flex flex-col gap-1.5">
      <legend className="text-xs text-gray-500">{legend}</legend>
      <div className="flex flex-wrap gap-x-4 gap-y-1">
        {options.map((option) => (
          <label key={option} className="flex items-center gap-1.5 text-sm text-gray-800">
            <input
              type="radio"
              name={name}
              disabled={disabled}
              checked={value === option}
              onChange={() => onChange(option)}
            />
            {option}
          </label>
        ))}
      </div>
    </fieldset>
  )
}

function ReviewResultBadge({ value }: { value: string | null }) {
  if (!value) {
    return (
      <span className="rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-500">미판정</span>
    )
  }
  return (
    <span
      className={`rounded-full px-2 py-0.5 text-xs font-medium ${REVIEW_RESULT_BADGE_STYLES[value] ?? 'bg-gray-100 text-gray-600'}`}
    >
      {value}
    </span>
  )
}

/** 기관관리 상세의 권리확인 탭. 목록↔상세 두 화면을 이 컴포넌트 하나에서 전환한다. */
export default function ReviewBoard({ org }: { org: Org }) {
  const [mode, setMode] = useState<'list' | number>('list')

  const [items, setItems] = useState<ReviewItem[]>([])
  const [total, setTotal] = useState(0)
  const [done, setDone] = useState(0)
  const [page, setPage] = useState(0)
  const [keywordInput, setKeywordInput] = useState('')
  const [appliedKeyword, setAppliedKeyword] = useState('')
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [reloadKey, setReloadKey] = useState(0)

  const importInputRef = useRef<HTMLInputElement>(null)
  const [importBusy, setImportBusy] = useState(false)
  const [importReport, setImportReport] = useState<ReviewImportReport | null>(null)
  const [importError, setImportError] = useState<string | null>(null)

  useEffect(() => {
    if (mode !== 'list') {
      return
    }
    let cancelled = false
    setLoading(true)
    setError(null)

    getReviewPage(org.id, { keyword: appliedKeyword || undefined, page, size: PAGE_SIZE })
      .then((data) => {
        if (cancelled) {
          return
        }
        setItems(data.items)
        setTotal(data.total)
        setDone(data.done)
      })
      .catch((e: Error) => {
        if (!cancelled) {
          setError(e.message)
        }
      })
      .finally(() => {
        if (!cancelled) {
          setLoading(false)
        }
      })

    return () => {
      cancelled = true
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [mode, org.id, appliedKeyword, page, reloadKey])

  function handleSearch() {
    setPage(0)
    setAppliedKeyword(keywordInput.trim())
  }

  function handleResetSearch() {
    setKeywordInput('')
    setPage(0)
    setAppliedKeyword('')
  }

  async function handleImportFile(file: File) {
    setImportBusy(true)
    setImportError(null)
    try {
      const report = await importReview(org.id, file)
      setImportReport(report)
      setReloadKey((k) => k + 1)
    } catch (e) {
      setImportError(e instanceof Error ? e.message : '엑셀 업로드에 실패했습니다.')
    } finally {
      setImportBusy(false)
    }
  }

  async function handleDelete(item: ReviewItem) {
    if (!window.confirm(`"${item.postTitle ?? item.seq}" 게시물을 삭제할까요?`)) {
      return
    }
    try {
      await deleteReviewItem(org.id, item.id)
      setReloadKey((k) => k + 1)
    } catch (e) {
      setError(e instanceof Error ? e.message : '삭제에 실패했습니다.')
    }
  }

  if (mode !== 'list') {
    return (
      <ReviewDetail
        org={org}
        itemId={mode}
        onBack={() => setMode('list')}
        onSaved={() => {
          setMode('list')
          setReloadKey((k) => k + 1)
        }}
      />
    )
  }

  const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE))

  return (
    <div className="p-4">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div className="flex items-center gap-2">
          <input
            type="text"
            aria-label="검색어"
            value={keywordInput}
            onChange={(e) => setKeywordInput(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') {
                handleSearch()
              }
            }}
            placeholder="사이트명·게시판명·제목 검색"
            className="w-64 rounded-md border border-gray-300 px-2 py-1.5 text-sm"
          />
          <button
            type="button"
            onClick={handleSearch}
            className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
          >
            검색
          </button>
          <button
            type="button"
            onClick={handleResetSearch}
            className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
          >
            초기화
          </button>
        </div>

        <div className="flex items-center gap-2">
          <input
            ref={importInputRef}
            type="file"
            accept=".xlsx,.xlsm"
            className="hidden"
            onChange={(e) => {
              const file = e.target.files?.[0]
              if (file) {
                void handleImportFile(file)
              }
              e.target.value = ''
            }}
          />
          <button
            type="button"
            disabled={importBusy}
            onClick={() => importInputRef.current?.click()}
            className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50 disabled:opacity-50"
          >
            {importBusy ? '업로드 중…' : '엑셀 업로드'}
          </button>
          <a
            href={reviewDownloadUrl(org.id)}
            className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50"
          >
            엑셀 다운로드
          </a>
        </div>
      </div>

      {importReport && (
        <p className="mt-3 text-sm text-gray-600">
          {`신규 ${importReport.created} · 갱신 ${importReport.updated} · 전체 ${importReport.total}`}
        </p>
      )}
      {importError && <p className="mt-3 text-sm text-red-600">{importError}</p>}

      <p className="mt-4 text-sm font-medium text-gray-700">
        {`총 ${total}건 · 처리 ${done}건`}
      </p>

      {error && <p className="mt-2 text-sm text-red-600">{error}</p>}

      <div className="mt-3 overflow-x-auto rounded-lg border border-gray-200">
        <table className="w-full min-w-[1100px] text-left text-sm">
          <thead>
            <tr className="border-b border-gray-200 bg-gray-50 text-xs text-gray-500">
              <th className="whitespace-nowrap px-3 py-2 font-medium">No</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">사이트/게시판</th>
              <th className="px-3 py-2 font-medium">범주/제목</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">제작/공표일</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">첨부파일</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">기존 공공누리</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">권리확인</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">처리결과</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">공공누리유형(판정)</th>
              <th className="whitespace-nowrap px-3 py-2 font-medium">관리</th>
            </tr>
          </thead>
          <tbody>
            {loading ? (
              <tr>
                <td colSpan={10} className="py-8 text-center text-sm text-gray-400">
                  불러오는 중…
                </td>
              </tr>
            ) : items.length === 0 ? (
              <tr>
                <td colSpan={10} className="py-10 text-center text-sm text-gray-300">
                  업로드된 권리확인 자료가 없습니다. 엑셀 업로드로 시작하세요.
                </td>
              </tr>
            ) : (
              items.map((item) => (
                <tr key={item.id} className="border-b border-gray-100 align-top last:border-b-0">
                  <td className="px-3 py-2 text-gray-500">{item.seq}</td>
                  <td className="px-3 py-2">
                    <div className="text-gray-900">{item.siteName ?? '-'}</div>
                    <div className="text-xs text-gray-400">{item.boardName ?? '-'}</div>
                  </td>
                  <td className="px-3 py-2">
                    <div className="text-gray-500">{item.category ?? '-'}</div>
                    <div className="flex items-center gap-1 text-gray-900">
                      <span>{item.postTitle ?? '-'}</span>
                      {item.url && (
                        <a
                          href={item.url}
                          target="_blank"
                          rel="noreferrer"
                          title="원문 보기"
                          aria-label="원문 보기"
                          className="text-blue-500 hover:underline"
                        >
                          🔗
                        </a>
                      )}
                    </div>
                  </td>
                  <td className="px-3 py-2 text-gray-600">
                    <div>{item.producedDate ?? '-'}</div>
                    <div className="text-xs text-gray-400">{item.publishedDate ?? '-'}</div>
                  </td>
                  <td className="px-3 py-2 text-gray-600">{item.hasAttachment ?? '-'}</td>
                  <td className="px-3 py-2 text-gray-600">
                    <div>
                      {item.koglAttached ?? '-'} / {item.koglType ?? '-'}
                    </div>
                    <div className="text-xs text-gray-400">{item.aiType ? 'AI' : ''}</div>
                  </td>
                  <td className="px-3 py-2 text-gray-600">
                    <div>{item.reviewMajor ?? '-'}</div>
                    <div className="text-xs text-gray-400">{item.reviewMinor ?? ''}</div>
                  </td>
                  <td className="px-3 py-2">
                    <ReviewResultBadge value={item.reviewResult} />
                  </td>
                  <td className="px-3 py-2 text-gray-600">
                    <div>{item.judgedKoglType ?? '-'}</div>
                    <div className="text-xs text-gray-400">{item.judgedAiType === 'Y' ? 'AI' : ''}</div>
                  </td>
                  <td className="px-3 py-2">
                    <div className="flex gap-2">
                      <button
                        type="button"
                        onClick={() => setMode(item.id)}
                        className="rounded-md border border-gray-200 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-50"
                      >
                        수정
                      </button>
                      <button
                        type="button"
                        onClick={() => void handleDelete(item)}
                        className="rounded-md border border-gray-200 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-50"
                      >
                        삭제
                      </button>
                    </div>
                  </td>
                </tr>
              ))
            )}
          </tbody>
        </table>
      </div>

      {items.length > 0 && (
        <div className="mt-3 flex items-center justify-center gap-3 text-sm text-gray-600">
          <button
            type="button"
            disabled={page <= 0}
            onClick={() => setPage((p) => Math.max(0, p - 1))}
            className="rounded-md border border-gray-300 px-2 py-1 disabled:opacity-40"
          >
            ‹
          </button>
          <span>{`${page + 1} / ${totalPages} Page`}</span>
          <button
            type="button"
            disabled={page + 1 >= totalPages}
            onClick={() => setPage((p) => p + 1)}
            className="rounded-md border border-gray-300 px-2 py-1 disabled:opacity-40"
          >
            ›
          </button>
        </div>
      )}
    </div>
  )
}

/** 권리확인 상세(변호사 판정 입력) 화면. */
function ReviewDetail({
  org,
  itemId,
  onBack,
  onSaved,
}: {
  org: Org
  itemId: number
  onBack: () => void
  onSaved: () => void
}) {
  const [item, setItem] = useState<ReviewItem | null>(null)
  const [loading, setLoading] = useState(true)
  const [loadError, setLoadError] = useState<string | null>(null)

  const [reviewMajor, setReviewMajor] = useState('')
  const [reviewMinor, setReviewMinor] = useState('')
  const [reviewResult, setReviewResult] = useState('')
  const [resultManuallySet, setResultManuallySet] = useState(false)
  const [judgedKoglType, setJudgedKoglType] = useState('')
  const [judgedAiType, setJudgedAiType] = useState(false)
  const [needsProcessing, setNeedsProcessing] = useState(false)
  const [opinion, setOpinion] = useState('')
  const [lawyerNote, setLawyerNote] = useState('')

  const [busy, setBusy] = useState(false)
  const [saveError, setSaveError] = useState<string | null>(null)

  useEffect(() => {
    let cancelled = false
    setLoading(true)
    setLoadError(null)

    getReviewItem(org.id, itemId)
      .then((data) => {
        if (cancelled) {
          return
        }
        setItem(data)
        setReviewMajor(data.reviewMajor ?? '')
        setReviewMinor(data.reviewMinor ?? '')
        setReviewResult(data.reviewResult ?? '')
        setResultManuallySet(false)
        setJudgedKoglType(data.judgedKoglType ?? '')
        setJudgedAiType(data.judgedAiType === 'Y')
        setNeedsProcessing(data.needsProcessing === 'Y')
        setOpinion(data.opinion ?? '')
        setLawyerNote(data.lawyerNote ?? '')
      })
      .catch((e: Error) => {
        if (!cancelled) {
          setLoadError(e.message)
        }
      })
      .finally(() => {
        if (!cancelled) {
          setLoading(false)
        }
      })

    return () => {
      cancelled = true
    }
  }, [org.id, itemId])

  function applySuggestion(major: string, minor: string) {
    if (resultManuallySet) {
      return
    }
    const suggestion = suggestReviewResult(major, minor)
    if (suggestion) {
      setReviewResult(suggestion)
    }
  }

  function pickMajor(major: string) {
    setReviewMajor(major)
    const minor = major === '제3자 권리' ? reviewMinor : ''
    setReviewMinor(minor)
    applySuggestion(major, minor)
  }

  function pickMinor(minor: string) {
    setReviewMinor(minor)
    applySuggestion(reviewMajor, minor)
  }

  function pickResult(result: string) {
    setReviewResult(result)
    setResultManuallySet(true)
  }

  async function handleSave() {
    setBusy(true)
    setSaveError(null)
    try {
      const body: JudgmentRequest = {
        // 개방가능여부는 별도 입력칸 없이 처리결과에서 파생한다("신유형 개방"일 때만 개방 가능).
        openable: reviewResult === '신유형 개방' ? 'Y' : reviewResult ? 'N' : null,
        reviewMajor: reviewMajor || null,
        reviewMinor: reviewMinor || null,
        reviewResult: reviewResult || null,
        judgedKoglType: judgedKoglType || null,
        judgedAiType: judgedAiType ? 'Y' : null,
        opinion: opinion || null,
        lawyerNote: lawyerNote || null,
        needsProcessing: needsProcessing ? 'Y' : null,
      }
      await updateReviewJudgment(org.id, itemId, body)
      onSaved()
    } catch (e) {
      setSaveError(e instanceof Error ? e.message : '저장에 실패했습니다.')
    } finally {
      setBusy(false)
    }
  }

  if (loading) {
    return <p className="p-4 py-10 text-center text-sm text-gray-400">불러오는 중…</p>
  }
  if (loadError || !item) {
    return <p className="p-4 py-10 text-center text-sm text-red-600">{loadError ?? '게시물을 찾을 수 없습니다.'}</p>
  }

  return (
    <div className="p-4">
      <section className="rounded-lg border border-gray-200 p-4">
        <h2 className="text-sm font-semibold">게시물 정보 (조사원)</h2>
        <div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2">
          <Field label="기관명" value={org.orgName} />
          <Field label="사이트명" value={item.siteName} />
          <Field label="범주" value={item.category} />
          <Field label="게시판명" value={item.boardName} />
          <Field label="게시물제목" value={item.postTitle} />
          <div className="flex gap-3 text-sm">
            <span className="w-24 shrink-0 text-gray-400">URL</span>
            {item.url ? (
              <a href={item.url} target="_blank" rel="noreferrer" className="break-all text-blue-600 hover:underline">
                {item.url}
              </a>
            ) : (
              <span className="text-gray-300">-</span>
            )}
          </div>
          <Field label="제작일" value={item.producedDate} />
          <Field label="공표일" value={item.publishedDate} />
          <Field label="첨부파일 여부" value={item.hasAttachment} />
          <Field label="기존 공공누리 부착" value={item.koglAttached} />
          <Field label="기존 공공누리유형" value={item.koglType} />
          <Field label="기존 AI유형" value={item.aiType} />
        </div>
      </section>

      <section className="mt-4 rounded-lg border border-gray-200 p-4">
        <h2 className="text-sm font-semibold">권리확인 (변호사)</h2>

        <div className="mt-3 flex flex-col gap-4">
          <RadioGroup
            legend="권리확인(대분류)"
            name="review-major"
            options={REVIEW_MAJOR_OPTIONS}
            value={reviewMajor}
            onChange={pickMajor}
          />

          {reviewMajor === '제3자 권리' && (
            <RadioGroup
              legend="권리확인(세부)"
              name="review-minor"
              options={REVIEW_MINOR_OPTIONS}
              value={reviewMinor}
              onChange={pickMinor}
            />
          )}

          <RadioGroup
            legend="처리결과"
            name="review-result"
            options={REVIEW_RESULT_OPTIONS}
            value={reviewResult}
            onChange={pickResult}
          />

          <RadioGroup
            legend="공공누리유형(판정)"
            name="judged-kogl-type"
            options={JUDGED_KOGL_TYPE_OPTIONS}
            value={judgedKoglType}
            onChange={setJudgedKoglType}
          />

          <label className="flex items-center gap-2 text-sm text-gray-800">
            <input
              type="checkbox"
              checked={judgedAiType}
              onChange={(e) => setJudgedAiType(e.target.checked)}
            />
            AI유형
          </label>

          <label className="flex items-center gap-2 text-sm text-gray-800">
            <input
              type="checkbox"
              checked={needsProcessing}
              onChange={(e) => setNeedsProcessing(e.target.checked)}
            />
            권리처리필요
          </label>

          <div className="flex flex-col gap-1 text-sm">
            <label htmlFor="review-opinion" className="text-xs text-gray-500">
              의견
            </label>
            <textarea
              id="review-opinion"
              rows={3}
              value={opinion}
              onChange={(e) => setOpinion(e.target.value)}
              className="rounded-md border border-gray-300 px-2 py-1.5"
            />
          </div>

          <div className="flex flex-col gap-1 text-sm">
            <label htmlFor="review-lawyer-note" className="text-xs text-gray-500">
              비고
            </label>
            <textarea
              id="review-lawyer-note"
              rows={3}
              value={lawyerNote}
              onChange={(e) => setLawyerNote(e.target.value)}
              className="rounded-md border border-gray-300 px-2 py-1.5"
            />
          </div>
        </div>

        {saveError && <p className="mt-3 text-sm text-red-600">{saveError}</p>}

        <div className="mt-4 flex justify-end gap-2">
          <button
            type="button"
            disabled={busy}
            onClick={onBack}
            className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50 disabled:opacity-50"
          >
            목록
          </button>
          <button
            type="button"
            disabled={busy}
            onClick={() => void handleSave()}
            className="rounded-md bg-blue-600 px-4 py-1.5 text-sm font-semibold text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300"
          >
            수정
          </button>
        </div>
      </section>
    </div>
  )
}
