"use client";

import {
  useDeferredValue,
  useRef,
  useState,
  type ChangeEvent,
} from "react";
import { useRouter } from "next/navigation";
import { BottomToast } from "@/components/bottom-toast";
import type {
  DkimReminderTemplate,
  DkimReminderType,
  KavenixDkimReminderRow,
} from "@/lib/dkim-reminders";

const PLACEHOLDERS = [
  "{업체명}",
  "{도메인}",
  "{대표메일}",
  "{보조메일}",
  "{도메인연결링크}",
] as const;

const inputClassName =
  "w-full rounded-[10px] border border-[#dbe5f7] bg-white px-3 text-[13px] text-[#1a2943] outline-none placeholder:text-[#97a7c2] focus:border-[#9dbbfb] focus:ring-2 focus:ring-[#edf4ff]";

type ReminderResult = {
  domainId: number;
  error: string | null;
  sentAt: string | null;
  status: "failed" | "sent" | "skipped";
};

type ReminderRowOverride = Pick<
  KavenixDkimReminderRow,
  "lastReminderAt" | "lastReminderError" | "lastReminderStatus" | "reminderCount"
>;

function formatDateTime(value: string | null) {
  if (!value) return "-";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "-";

  return new Intl.DateTimeFormat("ko-KR", {
    dateStyle: "short",
    timeStyle: "short",
  }).format(date);
}

function reminderTypeLabel(type: DkimReminderType) {
  return type === "dkim_rotation" ? "신규 DKIM 재인증" : "최초 DNS 연결";
}

function replacePreviewTokens(
  template: string,
  row: KavenixDkimReminderRow,
  domainConnectionUrl: string,
) {
  const replacements: Record<string, string> = {
    "{업체명}": row.companyName || "고객",
    "{도메인}": row.domain,
    "{대표메일}": row.ownerEmail,
    "{보조메일}": row.recoveryEmail ?? "",
    "{도메인연결링크}": domainConnectionUrl,
  };

  return Object.entries(replacements).reduce(
    (result, [token, value]) => result.replaceAll(token, value),
    template,
  );
}

export function KavenixDkimReminderDashboard({
  domainConnectionUrl,
  initialRows,
  initialTemplates,
}: {
  domainConnectionUrl: string;
  initialRows: KavenixDkimReminderRow[];
  initialTemplates: Record<DkimReminderType, DkimReminderTemplate>;
}) {
  const router = useRouter();
  const [rowOverrides, setRowOverrides] = useState<Record<number, ReminderRowOverride>>({});
  const [reminderType, setReminderType] = useState<DkimReminderType>(
    initialRows.some((row) => row.reminderType === "dkim_rotation")
      ? "dkim_rotation"
      : "initial_dns",
  );
  const [templates, setTemplates] = useState(initialTemplates);
  const [query, setQuery] = useState("");
  const deferredQuery = useDeferredValue(query.trim().toLowerCase());
  const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set());
  const [focusTarget, setFocusTarget] = useState<"body" | "subject">("body");
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [sending, setSending] = useState(false);
  const [progress, setProgress] = useState({ done: 0, total: 0 });
  const [toast, setToast] = useState<{
    message: string;
    tone: "error" | "success";
  } | null>(null);
  const subjectRef = useRef<HTMLInputElement>(null);
  const bodyRef = useRef<HTMLTextAreaElement>(null);

  const rows = initialRows.map((row) => ({
    ...row,
    ...rowOverrides[row.domainId],
  }));

  const activeTemplate = templates[reminderType];
  const typeRows = rows.filter((row) => row.reminderType === reminderType);
  const visibleRows = typeRows.filter((row) => {
    if (!deferredQuery) return true;
    return [row.companyName, row.domain, row.ownerEmail, row.recoveryEmail ?? ""]
      .join(" ")
      .toLowerCase()
      .includes(deferredQuery);
  });
  const selectableVisibleRows = visibleRows.filter((row) => row.contactable);
  const selectedRows = rows.filter(
    (row) => row.reminderType === reminderType && selectedIds.has(row.domainId),
  );
  const previewRow = selectedRows[0] ?? visibleRows[0] ?? null;
  const allVisibleSelected =
    selectableVisibleRows.length > 0 &&
    selectableVisibleRows.every((row) => selectedIds.has(row.domainId));
  const rotationCount = rows.filter((row) => row.reminderType === "dkim_rotation").length;
  const initialCount = rows.filter((row) => row.reminderType === "initial_dns").length;
  const unavailableCount = rows.filter((row) => !row.contactable).length;

  const changeType = (nextType: DkimReminderType) => {
    if (sending) return;
    setReminderType(nextType);
    setSelectedIds(new Set());
    setConfirmOpen(false);
  };

  const updateTemplate = (
    field: keyof DkimReminderTemplate,
    event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
  ) => {
    const value = event.target.value;
    setTemplates((current) => ({
      ...current,
      [reminderType]: { ...current[reminderType], [field]: value },
    }));
  };

  const insertPlaceholder = (token: string) => {
    const field = focusTarget;
    const element = field === "subject" ? subjectRef.current : bodyRef.current;
    const currentValue = activeTemplate[field];
    const start = element?.selectionStart ?? currentValue.length;
    const end = element?.selectionEnd ?? start;
    const nextValue = `${currentValue.slice(0, start)}${token}${currentValue.slice(end)}`;

    setTemplates((current) => ({
      ...current,
      [reminderType]: { ...current[reminderType], [field]: nextValue },
    }));
    requestAnimationFrame(() => {
      const nextElement = field === "subject" ? subjectRef.current : bodyRef.current;
      nextElement?.focus();
      nextElement?.setSelectionRange(start + token.length, start + token.length);
    });
  };

  const toggleRow = (domainId: number) => {
    setSelectedIds((current) => {
      const next = new Set(current);
      if (next.has(domainId)) next.delete(domainId);
      else next.add(domainId);
      return next;
    });
  };

  const toggleVisibleRows = () => {
    setSelectedIds((current) => {
      const next = new Set(current);
      for (const row of selectableVisibleRows) {
        if (allVisibleSelected) next.delete(row.domainId);
        else next.add(row.domainId);
      }
      return next;
    });
  };

  const resetTemplate = () => {
    setTemplates((current) => ({
      ...current,
      [reminderType]: { ...initialTemplates[reminderType] },
    }));
  };

  const sendSelected = async () => {
    if (sending || selectedRows.length === 0) return;
    setConfirmOpen(false);
    setSending(true);
    setProgress({ done: 0, total: selectedRows.length });
    let sentCount = 0;
    let failedCount = 0;
    const failedIds = new Set<number>();

    try {
      for (let index = 0; index < selectedRows.length; index += 5) {
        const batch = selectedRows.slice(index, index + 5);
        const response = await fetch("/api/kavenix/dkim-reminders", {
          body: JSON.stringify({
            bodyTemplate: activeTemplate.body,
            domainIds: batch.map((row) => row.domainId),
            reminderType,
            subjectTemplate: activeTemplate.subject,
          }),
          headers: { "Content-Type": "application/json" },
          method: "POST",
        });
        const payload = (await response.json().catch(() => null)) as {
          message?: string;
          results?: ReminderResult[];
        } | null;

        if (!response.ok || !payload?.results) {
          throw new Error(payload?.message || "DKIM 안내 메일 발송에 실패했습니다.");
        }

        for (const result of payload.results) {
          if (result.status === "sent") sentCount += 1;
          else {
            failedCount += 1;
            failedIds.add(result.domainId);
          }
        }
        setRowOverrides((current) => {
          const next = { ...current };
          for (const row of batch) {
            const result = payload.results?.find((item) => item.domainId === row.domainId);
            if (!result || result.status === "skipped") continue;
            next[row.domainId] = {
              lastReminderAt: result.sentAt ?? new Date().toISOString(),
              lastReminderError: result.error,
              lastReminderStatus: result.status,
              reminderCount:
                result.status === "sent" ? row.reminderCount + 1 : row.reminderCount,
            };
          }
          return next;
        });
        setProgress({
          done: Math.min(index + batch.length, selectedRows.length),
          total: selectedRows.length,
        });
      }

      setSelectedIds(failedIds);
      setToast({
        message:
          failedCount > 0
            ? `${sentCount}건 발송 완료, ${failedCount}건은 발송하지 못했습니다.`
            : `${sentCount}건의 DKIM 안내 메일을 발송했습니다.`,
        tone: failedCount > 0 ? "error" : "success",
      });
      router.refresh();
    } catch (error) {
      setToast({
        message:
          error instanceof Error ? error.message : "DKIM 안내 메일 발송에 실패했습니다.",
        tone: "error",
      });
    } finally {
      setSending(false);
    }
  };

  return (
    <>
      <div className="border-b border-[#edf1f6] px-3 py-4 sm:px-4 lg:px-8">
        <div className="grid gap-2 sm:grid-cols-3">
          <div className="rounded-[12px] border border-[#dce7f8] bg-[#f7faff] px-4 py-3">
            <p className="text-[12px] font-medium text-[#70819d]">전체 안내 대상</p>
            <p className="mt-1 text-[22px] font-semibold tracking-[-0.04em] text-[#16233c]">
              {rows.length.toLocaleString("ko-KR")}건
            </p>
          </div>
          <div className="rounded-[12px] border border-[#dce7f8] bg-white px-4 py-3">
            <p className="text-[12px] font-medium text-[#70819d]">신규 DKIM 재인증</p>
            <p className="mt-1 text-[22px] font-semibold tracking-[-0.04em] text-[#2f6df6]">
              {rotationCount.toLocaleString("ko-KR")}건
            </p>
          </div>
          <div className="rounded-[12px] border border-[#dce7f8] bg-white px-4 py-3">
            <p className="text-[12px] font-medium text-[#70819d]">최초 DNS 연결 미완료</p>
            <div className="mt-1 flex items-end justify-between gap-3">
              <p className="text-[22px] font-semibold tracking-[-0.04em] text-[#16233c]">
                {initialCount.toLocaleString("ko-KR")}건
              </p>
              {unavailableCount > 0 ? (
                <span className="text-[11px] font-semibold text-[#d15b68]">
                  발송 불가 {unavailableCount}건
                </span>
              ) : null}
            </div>
          </div>
        </div>
      </div>

      <div className="border-b border-[#edf1f6] px-3 py-4 sm:px-4 lg:px-8">
        <div className="inline-flex rounded-[11px] border border-[#dbe5f7] bg-[#f4f7fc] p-1">
          {(["dkim_rotation", "initial_dns"] as const).map((type) => {
            const active = reminderType === type;
            const count = type === "dkim_rotation" ? rotationCount : initialCount;
            return (
              <button
                key={type}
                type="button"
                onClick={() => changeType(type)}
                className={`h-9 cursor-pointer rounded-[8px] px-3 text-[12px] font-semibold transition-all ${
                  active
                    ? "bg-white text-[#2f6df6] shadow-[0_2px_8px_rgba(35,67,120,0.12)]"
                    : "text-[#70819d] hover:text-[#344767]"
                }`}
              >
                {reminderTypeLabel(type)} {count.toLocaleString("ko-KR")}
              </button>
            );
          })}
        </div>
      </div>

      <div className="grid border-b border-[#edf1f6] xl:grid-cols-[minmax(0,1.25fr)_minmax(320px,0.75fr)]">
        <div className="border-b border-[#edf1f6] px-3 py-5 sm:px-4 xl:border-b-0 xl:border-r lg:px-8">
          <div className="flex flex-wrap items-start justify-between gap-3">
            <div>
              <h2 className="text-[14px] font-semibold text-[#263957]">안내 메일 템플릿</h2>
              <p className="mt-1 text-[12px] leading-5 text-[#70819d]">
                현재 분류에 맞는 기본 문구가 입력되어 있으며 발송 전에 수정할 수 있습니다.
              </p>
            </div>
            <button
              type="button"
              onClick={resetTemplate}
              className="h-8 cursor-pointer rounded-[8px] px-2.5 text-[12px] font-semibold text-[#657895] hover:bg-[#f3f6fb]"
            >
              기본 문구 복원
            </button>
          </div>

          <div className="mt-4 flex flex-wrap gap-1.5">
            {PLACEHOLDERS.map((token) => (
              <button
                key={token}
                type="button"
                onClick={() => insertPlaceholder(token)}
                className="h-7 cursor-pointer rounded-[7px] border border-[#dbe5f7] bg-[#f8faff] px-2 text-[11px] font-semibold text-[#4f6790] hover:border-[#bcd1ff] hover:text-[#2f6df6]"
              >
                {token}
              </button>
            ))}
          </div>

          <label className="mt-4 block">
            <span className="mb-1.5 block text-[12px] font-semibold text-[#5d7195]">메일 제목</span>
            <input
              ref={subjectRef}
              value={activeTemplate.subject}
              maxLength={180}
              onFocus={() => setFocusTarget("subject")}
              onChange={(event) => updateTemplate("subject", event)}
              className={`${inputClassName} h-10`}
            />
          </label>
          <label className="mt-3 block">
            <span className="mb-1.5 block text-[12px] font-semibold text-[#5d7195]">메일 본문</span>
            <textarea
              ref={bodyRef}
              value={activeTemplate.body}
              maxLength={10_000}
              onFocus={() => setFocusTarget("body")}
              onChange={(event) => updateTemplate("body", event)}
              className={`${inputClassName} min-h-[310px] resize-y py-3 leading-6`}
            />
          </label>
        </div>

        <div className="bg-[#fbfcff] px-3 py-5 sm:px-4 lg:px-8 xl:px-5">
          <div className="flex items-center justify-between gap-3">
            <h2 className="text-[14px] font-semibold text-[#263957]">치환 미리보기</h2>
            {previewRow ? (
              <span className="max-w-[180px] truncate text-[11px] font-medium text-[#70819d]">
                {previewRow.recoveryEmail ?? "보조메일 없음"}
              </span>
            ) : null}
          </div>
          {previewRow ? (
            <div className="mt-3 overflow-hidden rounded-[12px] border border-[#dce6f6] bg-white">
              <div className="border-b border-[#edf1f6] px-4 py-3">
                <p className="text-[11px] font-semibold text-[#8190a8]">제목</p>
                <p className="mt-1 text-[13px] font-semibold leading-5 text-[#243653]">
                  {replacePreviewTokens(activeTemplate.subject, previewRow, domainConnectionUrl)}
                </p>
              </div>
              <p className="whitespace-pre-wrap px-4 py-4 text-[12px] leading-6 text-[#435675]">
                {replacePreviewTokens(activeTemplate.body, previewRow, domainConnectionUrl)}
              </p>
            </div>
          ) : (
            <div className="mt-3 rounded-[12px] border border-dashed border-[#d9e3f4] bg-white px-4 py-12 text-center text-[12px] text-[#8493aa]">
              현재 분류에 안내 대상이 없습니다.
            </div>
          )}
        </div>
      </div>

      <div className="border-b border-[#edf1f6] px-3 py-3 sm:px-4 lg:px-8">
        <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
          <input
            value={query}
            onChange={(event) => setQuery(event.target.value)}
            placeholder="업체명, 도메인, 이메일 검색"
            className={`${inputClassName} h-10 sm:max-w-[380px]`}
          />
          <div className="flex items-center justify-between gap-3 sm:justify-end">
            <span className="text-[12px] font-medium text-[#70819d]">
              {selectedRows.length.toLocaleString("ko-KR")}건 선택
            </span>
            <button
              type="button"
              disabled={sending || selectedRows.length === 0}
              onClick={() => setConfirmOpen(true)}
              className="om-btn-primary h-10 cursor-pointer rounded-[10px] px-4 text-[13px] shadow-none disabled:cursor-not-allowed disabled:opacity-50"
            >
              {sending
                ? `발송 중 ${progress.done}/${progress.total}`
                : "선택 대상 안내 발송"}
            </button>
          </div>
        </div>
      </div>

      <div className="overflow-x-auto">
        <table className="w-full min-w-[1080px] border-collapse text-left">
          <thead>
            <tr className="border-b border-[#edf1f6] text-[12px] font-semibold text-[#7a8ba8]">
              <th className="w-12 py-3 pl-3 pr-2 sm:pl-4 lg:pl-8">
                <input
                  type="checkbox"
                  checked={allVisibleSelected}
                  onChange={toggleVisibleRows}
                  aria-label="현재 목록 전체 선택"
                  className="h-4 w-4 accent-[#2f6df6]"
                />
              </th>
              <th className="px-2 py-3">업체·도메인</th>
              <th className="px-3 py-3">대표 메일</th>
              <th className="px-3 py-3">보조 이메일</th>
              <th className="px-3 py-3">연결 상태</th>
              <th className="px-3 py-3">DKIM 확인</th>
              <th className="py-3 pl-3 pr-3 sm:pr-4 lg:pr-8">최근 안내</th>
            </tr>
          </thead>
          <tbody>
            {visibleRows.length === 0 ? (
              <tr>
                <td colSpan={7} className="px-4 py-14 text-center text-[13px] text-[#7b8ca8]">
                  현재 조건에 맞는 안내 대상이 없습니다.
                </td>
              </tr>
            ) : null}
            {visibleRows.map((row) => {
              const duplicateRecipient =
                row.recoveryEmail &&
                rows.filter((item) => item.recoveryEmail === row.recoveryEmail).length > 1;
              return (
                <tr
                  key={row.domainId}
                  className="border-b border-[#edf1f6] text-[13px] text-[#30425f] last:border-b-0 hover:bg-[#fafcff]"
                >
                  <td className="py-3 pl-3 pr-2 sm:pl-4 lg:pl-8">
                    <input
                      type="checkbox"
                      checked={selectedIds.has(row.domainId)}
                      disabled={!row.contactable || sending}
                      onChange={() => toggleRow(row.domainId)}
                      aria-label={`${row.domain} 안내 대상 선택`}
                      className="h-4 w-4 accent-[#2f6df6] disabled:opacity-40"
                    />
                  </td>
                  <td className="px-2 py-3">
                    <p className="font-semibold text-[#16233c]">{row.companyName}</p>
                    <p className="mt-1 text-[12px] text-[#607493]">{row.domain}</p>
                  </td>
                  <td className="px-3 py-3 text-[#526784]">{row.ownerEmail}</td>
                  <td className="px-3 py-3">
                    <p className={row.contactable ? "text-[#30425f]" : "font-semibold text-[#d15b68]"}>
                      {row.recoveryEmail ?? "보조 이메일 없음"}
                    </p>
                    {duplicateRecipient ? (
                      <p className="mt-1 text-[11px] font-semibold text-[#b26b18]">다른 도메인과 수신 주소 중복</p>
                    ) : null}
                    {!row.contactable && row.recoveryEmail ? (
                      <p className="mt-1 text-[11px] text-[#d15b68]">인증되지 않은 보조 이메일</p>
                    ) : null}
                  </td>
                  <td className="px-3 py-3">
                    <span className={`inline-flex h-7 items-center rounded-[8px] px-2 text-[11px] font-semibold ${
                      row.reminderType === "dkim_rotation"
                        ? "bg-[#edf4ff] text-[#2f6df6]"
                        : "bg-[#fff7e8] text-[#a56a15]"
                    }`}>
                      {reminderTypeLabel(row.reminderType)}
                    </span>
                  </td>
                  <td className="px-3 py-3">
                    <p className={`font-semibold ${row.dkimStatus === "failed" ? "text-[#d64a5f]" : "text-[#8b6a2c]"}`}>
                      {row.dkimStatus === "failed" ? "검증 실패" : "확인 대기"}
                    </p>
                    <p className="mt-1 text-[11px] text-[#8493aa]">{formatDateTime(row.dkimLastCheckedAt)}</p>
                  </td>
                  <td className="py-3 pl-3 pr-3 sm:pr-4 lg:pr-8">
                    <p className={`font-semibold ${
                      row.lastReminderStatus === "sent"
                        ? "text-[#238653]"
                        : row.lastReminderStatus === "failed"
                          ? "text-[#d64a5f]"
                          : "text-[#8493aa]"
                    }`}>
                      {row.lastReminderStatus === "sent"
                        ? `발송 완료 ${row.reminderCount}회`
                        : row.lastReminderStatus === "failed"
                          ? "발송 실패"
                          : "발송 이력 없음"}
                    </p>
                    <p className="mt-1 text-[11px] text-[#8493aa]">{formatDateTime(row.lastReminderAt)}</p>
                    {row.lastReminderError ? (
                      <p className="mt-1 max-w-[220px] truncate text-[11px] text-[#d15b68]" title={row.lastReminderError}>
                        {row.lastReminderError}
                      </p>
                    ) : null}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {confirmOpen ? (
        <div className="fixed inset-0 z-[100] flex items-center justify-center bg-[#0b1426]/35 px-4 backdrop-blur-[2px]">
          <div role="dialog" aria-modal="true" aria-labelledby="dkim-reminder-confirm-title" className="w-full max-w-[460px] rounded-[16px] border border-white/60 bg-white p-5 shadow-[0_28px_80px_rgba(10,27,58,0.24)]">
            <h2 id="dkim-reminder-confirm-title" className="text-[17px] font-semibold tracking-[-0.03em] text-[#16233c]">
              DKIM 안내 메일을 발송할까요?
            </h2>
            <p className="mt-2 text-[13px] leading-6 text-[#667995]">
              선택한 {selectedRows.length.toLocaleString("ko-KR")}개 도메인의 인증된 보조 이메일로 각각 발송합니다. 치환 미리보기와 수신 주소를 다시 확인해주세요.
            </p>
            <div className="mt-4 rounded-[10px] border border-[#e1e8f4] bg-[#f8faff] px-3 py-3">
              <p className="text-[11px] font-semibold text-[#7d8da6]">발송 제목</p>
              <p className="mt-1 text-[13px] font-semibold leading-5 text-[#30425f]">
                {previewRow
                  ? replacePreviewTokens(activeTemplate.subject, previewRow, domainConnectionUrl)
                  : activeTemplate.subject}
              </p>
            </div>
            <div className="mt-5 flex justify-end gap-2">
              <button type="button" onClick={() => setConfirmOpen(false)} className="om-btn-secondary h-10 cursor-pointer rounded-[10px] px-4 text-[13px] text-[#4f617e] shadow-none">
                취소
              </button>
              <button type="button" onClick={() => void sendSelected()} className="om-btn-primary h-10 cursor-pointer rounded-[10px] px-4 text-[13px] shadow-none">
                {selectedRows.length.toLocaleString("ko-KR")}건 발송
              </button>
            </div>
          </div>
        </div>
      ) : null}

      {toast ? (
        <BottomToast
          key={`${toast.tone}-${toast.message}`}
          notice={toast}
          onClose={() => setToast(null)}
        />
      ) : null}
    </>
  );
}
