"use client";

import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import type { FormEvent } from "react";

import { BottomToast, type BottomToastNotice } from "@/components/bottom-toast";

type SecurityMode = "starttls" | "tls";

type SendingServer = {
  assignedDomainCount: number;
  createdAt: string | null;
  enabled: boolean;
  host: string;
  id: number | null;
  isDefault: boolean;
  key: string;
  label: string;
  port: number;
  securityMode: SecurityMode;
  tlsServerName: string | null;
  updatedAt: string | null;
};

type ServerForm = {
  enabled: boolean;
  host: string;
  label: string;
  port: string;
  securityMode: SecurityMode;
  tlsServerName: string;
};

type ServerResponse = {
  message?: string;
  ok?: boolean;
  result?: {
    id?: number;
    server?: SendingServer;
  };
};

const EMPTY_FORM: ServerForm = {
  enabled: true,
  host: "",
  label: "",
  port: "587",
  securityMode: "starttls",
  tlsServerName: "",
};

function formFromServer(server: SendingServer): ServerForm {
  return {
    enabled: server.enabled,
    host: server.host,
    label: server.label,
    port: String(server.port),
    securityMode: server.securityMode,
    tlsServerName: server.tlsServerName ?? "",
  };
}

export function KavenixSendingServerDashboard({
  initialServers,
}: {
  initialServers: SendingServer[];
}) {
  const router = useRouter();
  const [servers, setServers] = useState(initialServers);
  const [editingServer, setEditingServer] = useState<SendingServer | null>(null);
  const [form, setForm] = useState<ServerForm>(EMPTY_FORM);
  const [open, setOpen] = useState(false);
  const [busyAction, setBusyAction] = useState<string | null>(null);
  const [toast, setToast] = useState<BottomToastNotice | null>(null);

  useEffect(() => {
    if (!toast) {
      return;
    }

    const timeoutId = window.setTimeout(() => setToast(null), 4600);
    return () => window.clearTimeout(timeoutId);
  }, [toast]);

  function openCreateDialog() {
    setEditingServer(null);
    setForm(EMPTY_FORM);
    setOpen(true);
  }

  function openEditDialog(server: SendingServer) {
    if (server.isDefault) {
      return;
    }

    setEditingServer(server);
    setForm(formFromServer(server));
    setOpen(true);
  }

  function closeDialog() {
    if (!busyAction) {
      setOpen(false);
    }
  }

  async function submitServer(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    if (busyAction) {
      return;
    }

    const actionKey = editingServer ? `update-${editingServer.id}` : "create";
    setBusyAction(actionKey);

    try {
      const response = await fetch(
        editingServer
          ? `/api/kavenix/sending-servers/${editingServer.id}`
          : "/api/kavenix/sending-servers",
        {
          body: JSON.stringify({
            ...form,
            port: Number(form.port),
          }),
          headers: { "Content-Type": "application/json" },
          method: editingServer ? "PUT" : "POST",
        },
      );
      const payload = (await response.json()) as ServerResponse;
      const savedServer = payload.result?.server;

      if (!response.ok || payload.ok !== true || !savedServer) {
        throw new Error(payload.message || "발송 서버를 저장하지 못했습니다.");
      }

      setServers((current) => {
        const exists = current.some((server) => server.id === savedServer.id);
        return exists
          ? current.map((server) => server.id === savedServer.id ? savedServer : server)
          : [...current, savedServer];
      });
      setOpen(false);
      setToast({
        message: payload.message || "발송 서버를 저장했습니다.",
        tone: "success",
      });
      router.refresh();
    } catch (error) {
      setToast({
        message: error instanceof Error ? error.message : "발송 서버를 저장하지 못했습니다.",
        tone: "error",
      });
    } finally {
      setBusyAction(null);
    }
  }

  async function toggleServer(server: SendingServer) {
    if (!server.id || busyAction || (server.enabled && server.assignedDomainCount > 0)) {
      return;
    }

    const nextEnabled = !server.enabled;
    const actionKey = `toggle-${server.id}`;
    setBusyAction(actionKey);

    try {
      const response = await fetch(`/api/kavenix/sending-servers/${server.id}`, {
        body: JSON.stringify({
          ...formFromServer(server),
          enabled: nextEnabled,
          port: server.port,
        }),
        headers: { "Content-Type": "application/json" },
        method: "PUT",
      });
      const payload = (await response.json()) as ServerResponse;
      const savedServer = payload.result?.server;

      if (!response.ok || payload.ok !== true || !savedServer) {
        throw new Error(payload.message || "서버 상태를 변경하지 못했습니다.");
      }

      setServers((current) => current.map(
        (candidate) => candidate.id === savedServer.id ? savedServer : candidate,
      ));
      setToast({
        message: payload.message || "서버 상태를 변경했습니다.",
        tone: "success",
      });
      router.refresh();
    } catch (error) {
      setToast({
        message: error instanceof Error ? error.message : "서버 상태를 변경하지 못했습니다.",
        tone: "error",
      });
    } finally {
      setBusyAction(null);
    }
  }

  async function deleteServer(server: SendingServer) {
    if (!server.id || busyAction || server.assignedDomainCount > 0) {
      return;
    }

    if (!window.confirm(`${server.label} 발송 서버를 삭제할까요?`)) {
      return;
    }

    const actionKey = `delete-${server.id}`;
    setBusyAction(actionKey);

    try {
      const response = await fetch(`/api/kavenix/sending-servers/${server.id}`, {
        method: "DELETE",
      });
      const payload = (await response.json()) as ServerResponse;

      if (!response.ok || payload.ok !== true) {
        throw new Error(payload.message || "발송 서버를 삭제하지 못했습니다.");
      }

      setServers((current) => current.filter((candidate) => candidate.id !== server.id));
      setToast({
        message: payload.message || "발송 서버를 삭제했습니다.",
        tone: "success",
      });
      router.refresh();
    } catch (error) {
      setToast({
        message: error instanceof Error ? error.message : "발송 서버를 삭제하지 못했습니다.",
        tone: "error",
      });
    } finally {
      setBusyAction(null);
    }
  }

  return (
    <>
      <div className="px-3 py-4 sm:px-4 lg:px-8 lg:py-6">
        <div className="rounded-[20px] border border-[#dfe8f7] bg-[linear-gradient(135deg,#f7faff,#ffffff)] p-4 sm:p-5">
          <div className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
            <div>
              <p className="text-[14px] font-semibold text-[#263b5d]">연결 정보만 등록합니다</p>
              <p className="mt-1.5 max-w-[850px] text-[13px] leading-6 text-[#6c7f9d]">
                호스트명을 권장하며 IPv4와 IPv6도 입력할 수 있습니다. 별도 서버는 기존 메일함 계정으로 SMTP 인증을 받을 수 있어야 하고, 저장 시 네트워크 연결 테스트나 메일 발송은 수행하지 않습니다.
              </p>
            </div>
            <button
              type="button"
              onClick={openCreateDialog}
              className="om-btn-primary h-10 shrink-0 rounded-[10px] px-4 text-[13px] shadow-none"
            >
              발송 서버 추가
            </button>
          </div>
        </div>

        <div className="mt-4 overflow-hidden rounded-[18px] border border-[#e3e9f3] bg-white">
          <div className="overflow-x-auto">
            <table className="min-w-[940px] w-full border-collapse text-left">
              <thead className="bg-[#f7f9fc] text-[12px] font-semibold text-[#647692]">
                <tr>
                  <th className="px-4 py-3">서버</th>
                  <th className="px-4 py-3">호스트 / 포트</th>
                  <th className="px-4 py-3">보안</th>
                  <th className="px-4 py-3">TLS 호스트명</th>
                  <th className="px-4 py-3 text-right">할당 도메인</th>
                  <th className="px-4 py-3 text-right">관리</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-[#edf1f6] text-[13px] text-[#31435f]">
                {servers.map((server) => {
                  const locked = server.assignedDomainCount > 0;
                  const toggling = busyAction === `toggle-${server.id}`;
                  const deleting = busyAction === `delete-${server.id}`;

                  return (
                    <tr key={server.key} className={server.enabled ? "bg-white" : "bg-[#fafbfe]"}>
                      <td className="px-4 py-3.5">
                        <div className="flex items-center gap-2">
                          <span className="font-semibold text-[#1c2b44]">{server.label}</span>
                          {server.isDefault ? (
                            <span className="rounded-full bg-[#eaf1ff] px-2 py-0.5 text-[10px] font-bold text-[#2f6df6]">기본</span>
                          ) : (
                            <span className={`rounded-full px-2 py-0.5 text-[10px] font-bold ${server.enabled ? "bg-[#e9f8f0] text-[#2e8b5a]" : "bg-[#eef1f6] text-[#7c8ba2]"}`}>
                              {server.enabled ? "사용 중" : "중지"}
                            </span>
                          )}
                        </div>
                        <p className="mt-1 font-mono text-[10px] text-[#93a0b5]">{server.key}</p>
                      </td>
                      <td className="px-4 py-3.5 font-mono text-[12px] text-[#425675]">
                        {server.host}:{server.port}
                      </td>
                      <td className="px-4 py-3.5">
                        {server.securityMode === "tls" ? "TLS" : "STARTTLS"}
                      </td>
                      <td className="max-w-[230px] truncate px-4 py-3.5 text-[#687b98]" title={server.tlsServerName ?? ""}>
                        {server.tlsServerName || "자동"}
                      </td>
                      <td className="px-4 py-3.5 text-right font-semibold text-[#2f6df6]">
                        {server.assignedDomainCount.toLocaleString("ko-KR")}개
                      </td>
                      <td className="px-4 py-3.5">
                        {server.isDefault ? (
                          <p className="text-right text-[11px] text-[#8b99ae]">환경변수에서 관리</p>
                        ) : (
                          <div className="flex items-center justify-end gap-1.5">
                            <button
                              type="button"
                              onClick={() => openEditDialog(server)}
                              disabled={Boolean(busyAction)}
                              className="h-8 cursor-pointer rounded-[8px] px-2.5 text-[11px] font-semibold text-[#526784] hover:bg-[#f1f5fb] disabled:cursor-not-allowed disabled:opacity-50"
                            >
                              수정
                            </button>
                            <button
                              type="button"
                              onClick={() => toggleServer(server)}
                              disabled={Boolean(busyAction) || (server.enabled && locked)}
                              title={server.enabled && locked ? "할당된 도메인을 먼저 다른 서버로 변경해주세요." : undefined}
                              className="h-8 cursor-pointer rounded-[8px] px-2.5 text-[11px] font-semibold text-[#526784] hover:bg-[#f1f5fb] disabled:cursor-not-allowed disabled:opacity-40"
                            >
                              {toggling ? "처리 중" : server.enabled ? "중지" : "사용"}
                            </button>
                            <button
                              type="button"
                              onClick={() => deleteServer(server)}
                              disabled={Boolean(busyAction) || locked}
                              title={locked ? "할당된 도메인을 먼저 다른 서버로 변경해주세요." : undefined}
                              className="h-8 cursor-pointer rounded-[8px] px-2.5 text-[11px] font-semibold text-[#c44e58] hover:bg-[#fff1f2] disabled:cursor-not-allowed disabled:opacity-40"
                            >
                              {deleting ? "삭제 중" : "삭제"}
                            </button>
                          </div>
                        )}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      </div>

      {open ? (
        <div
          className="fixed inset-0 z-[10050] flex items-center justify-center bg-[#0f1f38]/34 px-4 py-8 backdrop-blur-[3px]"
          role="presentation"
          onMouseDown={(event) => {
            if (event.currentTarget === event.target) {
              closeDialog();
            }
          }}
        >
          <form
            onSubmit={submitServer}
            className="w-full max-w-[560px] overflow-hidden rounded-[24px] border border-white/90 bg-white shadow-[0_28px_80px_rgba(18,32,65,0.22)]"
          >
            <div className="px-5 pb-5 pt-5 sm:px-6 sm:pt-6">
              <p className="text-[12px] font-semibold text-[#2f6df6]">발송 서버 관리</p>
              <h2 className="mt-1.5 text-[20px] font-semibold tracking-[-0.045em] text-[#16233c]">
                {editingServer ? "서버 연결 정보 수정" : "새 발송 서버 추가"}
              </h2>

              <div className="mt-5 grid gap-4 sm:grid-cols-2">
                <label className="sm:col-span-2">
                  <span className="text-[12px] font-semibold text-[#526784]">서버 이름</span>
                  <input
                    required
                    maxLength={80}
                    value={form.label}
                    onChange={(event) => setForm((current) => ({ ...current, label: event.target.value }))}
                    placeholder="예: 대량발송 KR 1"
                    className="mt-1.5 h-11 w-full rounded-[10px] border border-[#dbe5f3] px-3 text-[13px] outline-none focus:border-[#8eb2ff] focus:ring-2 focus:ring-[#dce8ff]"
                  />
                </label>
                <label>
                  <span className="text-[12px] font-semibold text-[#526784]">호스트명 또는 IP</span>
                  <input
                    required
                    value={form.host}
                    onChange={(event) => setForm((current) => ({ ...current, host: event.target.value }))}
                    placeholder="smtp-bulk1.example.com"
                    className="mt-1.5 h-11 w-full rounded-[10px] border border-[#dbe5f3] px-3 font-mono text-[12px] outline-none focus:border-[#8eb2ff] focus:ring-2 focus:ring-[#dce8ff]"
                  />
                </label>
                <label>
                  <span className="text-[12px] font-semibold text-[#526784]">포트</span>
                  <input
                    required
                    type="number"
                    min={1}
                    max={65535}
                    value={form.port}
                    onChange={(event) => setForm((current) => ({ ...current, port: event.target.value }))}
                    className="mt-1.5 h-11 w-full rounded-[10px] border border-[#dbe5f3] px-3 text-[13px] outline-none focus:border-[#8eb2ff] focus:ring-2 focus:ring-[#dce8ff]"
                  />
                </label>
                <label>
                  <span className="text-[12px] font-semibold text-[#526784]">보안 연결</span>
                  <select
                    value={form.securityMode}
                    onChange={(event) => setForm((current) => ({ ...current, securityMode: event.target.value as SecurityMode }))}
                    className="mt-1.5 h-11 w-full rounded-[10px] border border-[#dbe5f3] bg-white px-3 text-[13px] outline-none focus:border-[#8eb2ff] focus:ring-2 focus:ring-[#dce8ff]"
                  >
                    <option value="starttls">STARTTLS (일반적으로 587)</option>
                    <option value="tls">TLS (일반적으로 465)</option>
                  </select>
                </label>
                <label>
                  <span className="text-[12px] font-semibold text-[#526784]">TLS 호스트명</span>
                  <input
                    value={form.tlsServerName}
                    onChange={(event) => setForm((current) => ({ ...current, tlsServerName: event.target.value }))}
                    placeholder="비우면 호스트명 사용"
                    className="mt-1.5 h-11 w-full rounded-[10px] border border-[#dbe5f3] px-3 font-mono text-[12px] outline-none focus:border-[#8eb2ff] focus:ring-2 focus:ring-[#dce8ff]"
                  />
                </label>
              </div>

              <p className="mt-4 rounded-[12px] bg-[#f5f8fd] px-3.5 py-3 text-[12px] leading-5 text-[#6d7f9a]">
                IP를 입력했다면 인증서에 적힌 도메인을 TLS 호스트명에 입력하세요. 저장 후 도메인 목록에서 서버를 할당해야 실제 발송 경로가 변경됩니다.
              </p>
            </div>

            <div className="flex items-center justify-end gap-2 border-t border-[#edf1f6] px-5 py-4 sm:px-6">
              <button
                type="button"
                onClick={closeDialog}
                disabled={Boolean(busyAction)}
                className="h-10 cursor-pointer rounded-[10px] px-4 text-[13px] font-semibold text-[#667894] hover:bg-[#f3f6fb] disabled:cursor-not-allowed"
              >
                취소
              </button>
              <button
                type="submit"
                disabled={Boolean(busyAction)}
                className="om-btn-primary h-10 rounded-[10px] px-4 text-[13px] shadow-none disabled:cursor-not-allowed disabled:opacity-55"
              >
                {busyAction ? "저장 중..." : editingServer ? "변경 저장" : "서버 추가"}
              </button>
            </div>
          </form>
        </div>
      ) : null}

      {toast ? <BottomToast notice={toast} onClose={() => setToast(null)} /> : null}
    </>
  );
}
