import { useEffect, useState } from 'react'
import {
  provisionChannels,
  updateAssignments,
  type AssignmentInput,
  type Contact,
  type ContactCategory,
  type Org,
  type ProvisionResult,
} from '../api/client'
import HelpButton from '../help/HelpButton'
import ConfirmDialog from './ConfirmDialog'
import ContactPickerModal from './ContactPickerModal'
import StatusBadge from './StatusBadge'

// 채널관리 상세. 담당자 정보는 여기서 입력하지 않는다(담당자관리에서만 입력) - 이 화면은
// 이미 등록된 담당자를 ContactPickerModal로 골라 신청기관/문정원/아이티앤/변호사 역할에 배정만 한다.

interface RoleConfig {
  key: 'applicant' | 'mj' | 'itn' | 'lawyer'
  category: ContactCategory
  label: string
  pickerTitle: string
  field: keyof AssignmentInput
}

const ROLES: RoleConfig[] = [
  {
    key: 'applicant',
    category: 'APPLICANT',
    label: '신청기관 담당자',
    pickerTitle: '신청기관 담당자 선택',
    field: 'applicantContactId',
  },
  {
    key: 'mj',
    category: 'MJ',
    label: '문정원 담당자',
    pickerTitle: '문정원 담당자 선택',
    field: 'mjContactId',
  },
  {
    key: 'itn',
    category: 'ITN',
    label: '아이티앤 담당자',
    pickerTitle: '아이티앤 담당자 선택',
    field: 'itnContactId',
  },
  {
    key: 'lawyer',
    category: 'LAWYER',
    label: '담당 변호사',
    pickerTitle: '담당 변호사 선택',
    field: 'lawyerContactId',
  },
]

function contactOf(org: Org, role: RoleConfig): Contact | null {
  switch (role.key) {
    case 'applicant':
      return org.applicant
    case 'mj':
      return org.mj
    case 'itn':
      return org.itn
    case 'lawyer':
      return org.lawyer
  }
}

/** 배정된 담당자의 한 줄 요약: 이름 · 부서(또는 소속) · 연락처. 값이 없는 항목은 건너뛴다. */
function contactSummary(contact: Contact): string {
  const parts = [contact.name, contact.deptName ?? contact.affiliation ?? null, contact.phone]
  return parts.filter((p): p is string => Boolean(p)).join(' · ')
}

export default function OrgDetail({ org, onChanged }: { org: Org; onChanged: () => void }) {
  const [confirming, setConfirming] = useState(false)
  const [result, setResult] = useState<ProvisionResult | null>(null)
  const [error, setError] = useState<string | null>(null)
  const [busy, setBusy] = useState(false)
  const [pickerRole, setPickerRole] = useState<RoleConfig | null>(null)
  const [lawyerDate, setLawyerDate] = useState(org.lawyerAssignedDate ?? '')

  // org.id로만 키를 잡는다(org 객체 전체가 아니라) - App.reload()가 채널 생성/배정 뒤에
  // 새 배열/새 객체를 만들어 넘기더라도, 같은 기관을 계속 보고 있는 한 방금 받은
  // result/error를 이 effect가 지워버리면 안 되기 때문이다.
  useEffect(() => {
    setResult(null)
    setError(null)
    setLawyerDate(org.lawyerAssignedDate ?? '')
    // 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'

  function currentAssignment(): AssignmentInput {
    return {
      applicantContactId: org.applicant?.id ?? null,
      mjContactId: org.mj?.id ?? null,
      itnContactId: org.itn?.id ?? null,
      lawyerContactId: org.lawyer?.id ?? null,
      lawyerAssignedDate: org.lawyerAssignedDate ?? null,
    }
  }

  /** 매 호출이 네 배정값 + 배정일을 통째로 다시 보낸다(부분 갱신이 아니다). */
  async function persistAssignments(overrides: Partial<AssignmentInput>) {
    setError(null)
    setBusy(true)
    try {
      await updateAssignments(org.id, { ...currentAssignment(), ...overrides })
      onChanged()
    } catch (e) {
      setError(e instanceof Error ? e.message : '저장에 실패했습니다.')
    } finally {
      setBusy(false)
    }
  }

  async function handleSelect(role: RoleConfig, contact: Contact) {
    setPickerRole(null)
    await persistAssignments({ [role.field]: contact.id })
  }

  async function handleClear(role: RoleConfig) {
    await persistAssignments({ [role.field]: null })
  }

  async function handleLawyerDateChange(value: string) {
    setLawyerDate(value)
    await persistAssignments({ lawyerAssignedDate: value === '' ? null : value })
  }

  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 space-y-3">
        {ROLES.map((role) => {
          const contact = contactOf(org, role)
          return (
            <div
              key={role.key}
              className="flex flex-wrap items-center justify-between gap-3 rounded-lg border border-gray-200 bg-white p-4"
            >
              <div className="flex flex-col gap-1">
                <span className="text-xs text-gray-500">{role.label}</span>
                {contact ? (
                  <span className="text-sm font-medium text-gray-900">{contactSummary(contact)}</span>
                ) : (
                  <span className="text-sm text-gray-300">미지정</span>
                )}
              </div>

              <div className="flex items-end gap-2">
                {role.key === 'lawyer' && (
                  <div className="flex flex-col gap-1">
                    <label htmlFor="lawyer-assigned-date" className="text-xs text-gray-500">
                      배정일
                    </label>
                    <input
                      id="lawyer-assigned-date"
                      type="date"
                      disabled={busy}
                      value={lawyerDate}
                      onChange={(e) => void handleLawyerDateChange(e.target.value)}
                      className="rounded-md border border-gray-300 px-2 py-1 text-sm"
                    />
                  </div>
                )}
                <button
                  type="button"
                  disabled={busy}
                  aria-label={`${role.label} 선택`}
                  onClick={() => setPickerRole(role)}
                  className="rounded-md border border-gray-300 px-3 py-1.5 text-sm disabled:opacity-50"
                >
                  선택
                </button>
                {contact && (
                  <button
                    type="button"
                    disabled={busy}
                    aria-label={`${role.label} 해제`}
                    onClick={() => void handleClear(role)}
                    className="rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-500 disabled:opacity-50"
                  >
                    해제
                  </button>
                )}
              </div>
            </div>
          )
        })}
        <p className="flex items-center gap-1.5 text-xs text-gray-400">
          신청기관 담당자를 지정해야 채널을 만들 수 있습니다.
          <HelpButton topic="channel.assign" />
        </p>
      </section>

      <div className="mt-5 flex gap-2">
        <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>
        <span className="flex items-center">
          <HelpButton topic="channel.provision" />
        </span>
      </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)}
        />
      )}

      {pickerRole && (
        <ContactPickerModal
          category={pickerRole.category}
          title={pickerRole.pickerTitle}
          onSelect={(contact) => void handleSelect(pickerRole, contact)}
          onClose={() => setPickerRole(null)}
        />
      )}
    </div>
  )
}

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