import { useEffect, useRef, useState } from 'react'
import {
  addSharedFile,
  deleteSharedFile,
  getSharedFiles,
  sharedFileDownloadUrl,
  updateSharedFileDescription,
  type SharedFile,
} from '../api/client'

/**
 * 자료실 — 공용 양식 보관소(요구사항 [26]).
 *
 * 기관에 딸리지 않는 서식을 여기 올려 두고, 어느 기관 일을 하든 내려받아 씁니다.
 * 기관별 자료는 기관관리 > 자료 탭에 그대로 있습니다.
 */
function formatSize(bytes: number): string {
  if (bytes < 1024) {
    return `${bytes} B`
  }
  if (bytes < 1024 * 1024) {
    return `${(bytes / 1024).toFixed(1)} KB`
  }
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`
}

function formatDate(ms: number): string {
  const d = new Date(ms)
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
}

export default function SharedFiles() {
  const [files, setFiles] = useState<SharedFile[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [description, setDescription] = useState('')
  const [editingId, setEditingId] = useState<number | null>(null)
  const [editingText, setEditingText] = useState('')
  const inputRef = useRef<HTMLInputElement>(null)

  async function load() {
    setLoading(true)
    try {
      setFiles(await getSharedFiles())
      setError(null)
    } catch (e) {
      setError((e as Error).message)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    void load()
  }, [])

  async function handleUpload(file: File) {
    setBusy(true)
    setError(null)
    try {
      setFiles(await addSharedFile(file, description.trim()))
      setDescription('')
    } catch (e) {
      setError((e as Error).message)
    } finally {
      setBusy(false)
    }
  }

  async function handleDelete(file: SharedFile) {
    if (!window.confirm(`「${file.fileName}」을(를) 지울까요?`)) {
      return
    }
    setBusy(true)
    try {
      await deleteSharedFile(file.id)
      await load()
    } finally {
      setBusy(false)
    }
  }

  async function saveDescription(file: SharedFile) {
    setBusy(true)
    try {
      setFiles(await updateSharedFileDescription(file.id, editingText.trim()))
      setEditingId(null)
    } catch (e) {
      setError((e as Error).message)
    } finally {
      setBusy(false)
    }
  }

  return (
    <div className="p-8">
      <h2 className="text-sm font-semibold">자료실</h2>
      <p className="mt-1 text-xs text-gray-500">
        기관에 딸리지 않는 공용 서식을 올려 둡니다. 기관별 자료는 기관관리 &gt; 자료 탭에 있습니다.
      </p>

      <div className="mt-4 flex flex-wrap items-center gap-2 rounded-lg border border-gray-200 p-3">
        <input
          type="text"
          aria-label="자료 설명"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          placeholder="설명(선택)"
          className="w-72 rounded-md border border-gray-300 px-2 py-1.5 text-sm"
        />
        <input
          ref={inputRef}
          type="file"
          className="hidden"
          onChange={(e) => {
            const file = e.target.files?.[0]
            if (file) void handleUpload(file)
            e.target.value = ''
          }}
        />
        <button
          type="button"
          disabled={busy}
          onClick={() => inputRef.current?.click()}
          className="rounded-md bg-blue-600 px-3 py-1.5 text-sm text-white disabled:bg-gray-300"
        >
          자료 올리기
        </button>
      </div>

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

      {loading ? (
        <p className="mt-4 text-sm text-gray-500">불러오는 중…</p>
      ) : files.length === 0 ? (
        <p className="mt-6 text-sm text-gray-500">올려둔 자료가 없습니다.</p>
      ) : (
        <table data-testid="shared-file-table" className="mt-4 w-full text-sm">
          <thead className="border-b border-gray-200 text-left text-xs text-gray-500">
            <tr>
              <th className="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="px-3 py-2" />
            </tr>
          </thead>
          <tbody>
            {files.map((file) => (
              <tr key={file.id} className="border-b border-gray-100 last:border-b-0">
                <td className="px-3 py-2">
                  <a
                    href={sharedFileDownloadUrl(file.id)}
                    className="font-medium text-blue-700 hover:underline"
                  >
                    {file.fileName}
                  </a>
                </td>
                <td className="px-3 py-2 text-gray-600">
                  {editingId === file.id ? (
                    <div className="flex items-center gap-1.5">
                      <input
                        aria-label="설명 수정"
                        value={editingText}
                        onChange={(e) => setEditingText(e.target.value)}
                        className="w-56 rounded-md border border-gray-300 px-2 py-1 text-sm"
                      />
                      <button
                        type="button"
                        disabled={busy}
                        onClick={() => void saveDescription(file)}
                        className="rounded-md border border-gray-300 px-2 py-0.5 text-xs"
                      >
                        저장
                      </button>
                    </div>
                  ) : (
                    <button
                      type="button"
                      onClick={() => {
                        setEditingId(file.id)
                        setEditingText(file.description ?? '')
                      }}
                      className="text-left hover:underline"
                    >
                      {file.description ?? <span className="text-gray-300">설명 없음</span>}
                    </button>
                  )}
                </td>
                <td className="whitespace-nowrap px-3 py-2 text-gray-500">{formatSize(file.byteSize)}</td>
                <td className="whitespace-nowrap px-3 py-2 text-gray-500">{file.uploadedBy}</td>
                <td className="whitespace-nowrap px-3 py-2 text-gray-500">{formatDate(file.uploadedAt)}</td>
                <td className="px-3 py-2 text-right">
                  <button
                    type="button"
                    disabled={busy}
                    onClick={() => void handleDelete(file)}
                    className="rounded-md border border-gray-300 px-2 py-0.5 text-xs text-red-600 hover:bg-red-50"
                  >
                    삭제
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  )
}
