import { useEffect, useState } from 'react'
import {
  provisionChannels,
  updateContact,
  type Contact,
  type Org,
  type ProvisionResult,
} from '../api/client'
import ConfirmDialog from './ConfirmDialog'
import StatusBadge from './StatusBadge'

const APPLICANT_FIELDS: { key: keyof Contact; label: string }[] = [
  { key: 'deptName', label: '부서명' },
  { key: 'managerName', label: '담당자명' },
  { key: 'managerTitle', label: '직급/직함' },
  { key: 'managerPhone', label: '연락처' },
  { key: 'managerEmail', label: '이메일' },
]

const MJ_FIELDS: { key: keyof Contact; label: string; type?: string }[] = [
  { key: 'mjDeptName', label: '부서명' },
  { key: 'mjManagerName', label: '담당자명' },
  { key: 'mjManagerPhone', label: '연락처' },
  { key: 'mjManagerEmail', label: '이메일' },
]

const LAWYER_FIELDS: { key: keyof Contact; label: string; type?: string }[] = [
  { key: 'lawyerName', label: '성명' },
  { key: 'lawyerPhone', label: '연락처' },
  { key: 'lawyerEmail', label: '이메일' },
  { key: 'lawyerAssignedDate', label: '배정일', type: 'date' },
]

function emptyContact(org: Org): Contact {
  return {
    deptName: org.deptName ?? '',
    managerName: org.managerName ?? '',
    managerTitle: org.managerTitle ?? '',
    managerPhone: org.managerPhone ?? '',
    managerEmail: org.managerEmail ?? '',
    mjDeptName: org.mjDeptName ?? '',
    mjManagerName: org.mjManagerName ?? '',
    mjManagerPhone: org.mjManagerPhone ?? '',
    mjManagerEmail: org.mjManagerEmail ?? '',
    lawyerName: org.lawyerName ?? '',
    lawyerPhone: org.lawyerPhone ?? '',
    lawyerEmail: org.lawyerEmail ?? '',
    lawyerAssignedDate: org.lawyerAssignedDate ?? '',
  }
}

const REQUIRED_FIELDS: (keyof Contact)[] = [
  'deptName',
  'managerName',
  'managerPhone',
  'managerEmail',
]

function ContactFieldGroup({
  title,
  fields,
  contact,
  onChange,
}: {
  title: string
  fields: { key: keyof Contact; label: string; type?: string }[]
  contact: Contact
  onChange: (key: keyof Contact, value: string) => void
}) {
  return (
    <div className="rounded-lg border border-gray-200 p-4">
      <h3 className="text-sm font-medium text-gray-700">{title}</h3>
      <div className="mt-3 space-y-3">
        {fields.map((field) => (
          <div key={field.key} className="flex items-center gap-3">
            <label htmlFor={field.key} className="w-20 shrink-0 text-sm text-gray-500">
              {field.label}
            </label>
            <input
              id={field.key}
              type={field.type ?? 'text'}
              className="flex-1 rounded-md border border-gray-300 px-3 py-2 text-sm"
              value={contact[field.key]}
              onChange={(e) => onChange(field.key, e.target.value)}
            />
          </div>
        ))}
      </div>
    </div>
  )
}

export default function OrgDetail({ org, onChanged }: { org: Org; onChanged: () => void }) {
  const [contact, setContact] = useState<Contact>(emptyContact(org))
  const [confirming, setConfirming] = useState(false)
  const [result, setResult] = useState<ProvisionResult | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)

  // org.id로만 키를 잡는다(org 객체 전체가 아니라) - App.reload()가 채널 생성 뒤에
  // 새 배열/새 객체를 만들어 넘기더라도, 같은 기관을 계속 보고 있는 한 방금 받은
  // result/error를 이 effect가 지워버리면 안 되기 때문이다(같은 이유로 입력 중이던
  // contact 값도 다른 기관으로 전환할 때만 초기화한다).
  useEffect(() => {
    setContact(emptyContact(org))
    setResult(null)
    setError(null)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [org.id])

  const displayMj = `${org.orgNo}_${org.orgName} (문정원)`
  const displayLaw = `${org.orgNo}_${org.orgName} (법률검토)`
  const canProvision = org.status !== 'INFO_PENDING'
  const requiredFilled = REQUIRED_FIELDS.every((key) => contact[key].trim() !== '')

  function setField(key: keyof Contact, value: string) {
    setContact((prev) => ({ ...prev, [key]: value }))
  }

  async function save() {
    setError(null)
    setBusy(true)
    try {
      await updateContact(org.id, contact)
      onChanged()
    } catch (e) {
      setError((e as Error).message)
    } finally {
      setBusy(false)
    }
  }

  async function provision() {
    setError(null)
    setBusy(true)
    try {
      const provisionResult = await provisionChannels(org.id)
      setResult(provisionResult)
      onChanged()
    } catch (e) {
      setError((e as Error).message)
    } finally {
      setBusy(false)
      setConfirming(false)
    }
  }

  return (
    <div className="p-8">
      <div className="flex items-center gap-3">
        <h1 className="text-lg font-semibold">
          {org.orgNo} {org.orgName}
        </h1>
        <StatusBadge status={org.status} />
      </div>

      <section className="mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3">
        <ContactFieldGroup
          title="신청기관 담당자"
          fields={APPLICANT_FIELDS}
          contact={contact}
          onChange={setField}
        />
        <ContactFieldGroup
          title="문정원 담당자"
          fields={MJ_FIELDS}
          contact={contact}
          onChange={setField}
        />
        <ContactFieldGroup
          title="담당 변호사"
          fields={LAWYER_FIELDS}
          contact={contact}
          onChange={setField}
        />
      </section>

      <div className="mt-5 flex gap-2">
        <button
          type="button"
          disabled={busy || !requiredFilled}
          onClick={() => void save()}
          className="rounded-md border border-gray-300 px-3 py-1.5 text-sm disabled:opacity-50"
        >
          정보 저장
        </button>
        <button
          type="button"
          disabled={busy || !canProvision}
          onClick={() => setConfirming(true)}
          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-4 text-sm text-red-600">{error}</p>}

      {result && (
        <div className="mt-4 max-w-xl rounded-lg border border-gray-200 p-4 text-sm">
          <p>문정원 채널: {outcomeLabel(result.mj)}</p>
          <p>법률검토 채널: {outcomeLabel(result.law)}</p>

          {result.mj === 'FAILED' && result.law === 'FAILED' ? (
            <p className="mt-2 text-amber-700">
              문정원 채널과 법률검토 채널 모두 생성에 실패했습니다. 아직 만들어진 채널이 없으니 [채널 생성]을 다시 눌러도 안전합니다.
            </p>
          ) : (
            <>
              {result.law === 'FAILED' && (
                <p className="mt-2 text-amber-700">
                  법률검토 채널 생성에 실패했습니다. 문정원 채널은 그대로 남아 있으니
                  [채널 생성]을 다시 눌러도 안전합니다. 없는 채널만 다시 만듭니다.
                </p>
              )}
              {result.mj === 'FAILED' && (
                <p className="mt-2 text-amber-700">
                  문정원 채널 생성에 실패했습니다. 법률검토 채널은 그대로 남아 있으니
                  [채널 생성]을 다시 눌러도 안전합니다. 없는 채널만 다시 만듭니다.
                </p>
              )}
            </>
          )}
          {result.message && (
            <pre className="mt-2 whitespace-pre-wrap text-xs text-gray-500">{result.message}</pre>
          )}
        </div>
      )}

      {confirming && (
        <ConfirmDialog
          title="아래 채널 2개를 Mattermost에 생성합니다."
          lines={[displayMj, displayLaw]}
          confirmLabel="생성"
          busy={busy}
          onConfirm={() => void provision()}
          onCancel={() => setConfirming(false)}
        />
      )}
    </div>
  )
}

function outcomeLabel(outcome: ProvisionResult['mj']): string {
  switch (outcome) {
    case 'CACHED':
      return '이미 있음 (변경 없음)'
    case 'RECOVERED':
      return '기존 채널 연결됨'
    case 'CREATED':
      return '새로 생성됨'
    case 'FAILED':
      return '실패'
  }
}
