"use client";

import { useEffect, useState, useCallback, useMemo } from "react";
import Swal from "sweetalert2";
import { Send, Upload, X, Bell, Plus, Pencil, Trash2, Users, Save } from "lucide-react";

interface Recipient {
  USER_ID: string;
  USER_NAME: string;
  USER_TYPE: string;
  IS_ADMIN: boolean;
  DEPT_NAME: string;
  USER_AGENT: string;
  LAST_SEEN: string;
  DEVICE_CNT: number;
}
interface AllUser {
  USER_ID: string;
  USER_NAME: string;
  USER_TYPE: string;
  IS_ADMIN: boolean;
  DEPT_NAME: string;
  SUBSCRIBED: boolean;
}
interface Group {
  OBJID: string; NAME: string; DESCRIPTION: string | null;
  REGDATE: string; MEMBER_CNT: number; MEMBER_IDS: string[];
}
interface Notice {
  OBJID: string; TITLE: string; BODY: string | null;
  IMAGE_URL: string | null; URL: string | null;
  REGDATE: string; SENT_COUNT: number;
}

export default function AdminNoticesPage() {
  // 그룹
  const [groups, setGroups] = useState<Group[]>([]);
  const [selectedGroups, setSelectedGroups] = useState<Set<string>>(new Set());
  const [editingGroup, setEditingGroup] = useState<{ OBJID?: string; NAME: string; DESCRIPTION: string } | null>(null);
  const [groupMemberSet, setGroupMemberSet] = useState<Set<string>>(new Set());
  const [allUsers, setAllUsers] = useState<AllUser[]>([]);
  const [groupSaving, setGroupSaving] = useState(false);

  // 구독자(개별 선택)
  const [recipients, setRecipients] = useState<Recipient[]>([]);
  const [selectedUsers, setSelectedUsers] = useState<Set<string>>(new Set());
  const [keyword, setKeyword] = useState("");
  const [typeFilter, setTypeFilter] = useState<"" | "U" | "A">("");

  // 작성
  const [title, setTitle] = useState("");
  const [bodyText, setBodyText] = useState("");
  const [imageUrl, setImageUrl] = useState("");
  const [linkUrl, setLinkUrl] = useState("");
  const [uploading, setUploading] = useState(false);
  const [sending, setSending] = useState(false);

  // 과거 공지
  const [past, setPast] = useState<Notice[]>([]);

  // 멤버 picker 검색
  const [memberPickerKw, setMemberPickerKw] = useState("");

  const loadGroups = useCallback(async () => {
    const r = await fetch("/api/m/admin/notices/groups/list", { method: "POST" });
    setGroups((await r.json()).RESULTLIST ?? []);
  }, []);
  const loadRecipients = useCallback(async () => {
    const r = await fetch("/api/m/admin/notices/recipients", { method: "POST" });
    setRecipients((await r.json()).RESULTLIST ?? []);
  }, []);
  const loadAllUsers = useCallback(async () => {
    const r = await fetch("/api/m/admin/notices/all-users", { method: "POST" });
    setAllUsers((await r.json()).RESULTLIST ?? []);
  }, []);
  const loadPast = useCallback(async () => {
    const r = await fetch("/api/m/admin/notices/list", { method: "POST" });
    setPast((await r.json()).RESULTLIST ?? []);
  }, []);
  useEffect(() => { loadGroups(); loadRecipients(); loadAllUsers(); loadPast(); }, [loadGroups, loadRecipients, loadAllUsers, loadPast]);

  const filteredRecipients = useMemo(() => {
    return recipients.filter((u) => {
      if (typeFilter && (typeFilter === "A" ? !u.IS_ADMIN : u.IS_ADMIN)) return false;
      if (keyword) {
        const k = keyword.toLowerCase();
        if (!u.USER_NAME?.toLowerCase().includes(k) && !u.USER_ID?.toLowerCase().includes(k)) return false;
      }
      return true;
    });
  }, [recipients, typeFilter, keyword]);

  // 발송 대상 = 선택 그룹들의 멤버 ∪ 개별 선택
  const finalUserIds = useMemo(() => {
    const set = new Set<string>(selectedUsers);
    for (const g of groups) {
      if (selectedGroups.has(g.OBJID)) for (const uid of g.MEMBER_IDS ?? []) set.add(uid);
    }
    return Array.from(set);
  }, [groups, selectedGroups, selectedUsers]);

  // ===== 그룹 편집 =====
  const openNewGroup = () => {
    setEditingGroup({ NAME: "", DESCRIPTION: "" });
    setGroupMemberSet(new Set());
    setMemberPickerKw("");
  };
  const openEditGroup = (g: Group) => {
    setEditingGroup({ OBJID: g.OBJID, NAME: g.NAME, DESCRIPTION: g.DESCRIPTION ?? "" });
    setGroupMemberSet(new Set(g.MEMBER_IDS ?? []));
    setMemberPickerKw("");
  };
  const closeEditGroup = () => { setEditingGroup(null); setGroupMemberSet(new Set()); };

  const toggleMemberInEdit = (uid: string) => {
    setGroupMemberSet((p) => {
      const n = new Set(p);
      if (n.has(uid)) n.delete(uid); else n.add(uid);
      return n;
    });
  };

  const saveGroup = async () => {
    if (!editingGroup) return;
    if (!editingGroup.NAME.trim()) return Swal.fire({ icon: "warning", title: "그룹명을 입력하세요" });
    setGroupSaving(true);
    try {
      const sv = await fetch("/api/m/admin/notices/groups/save", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ objid: editingGroup.OBJID, name: editingGroup.NAME, description: editingGroup.DESCRIPTION }),
      });
      const sj = await sv.json();
      if (!sj.success) { Swal.fire({ icon: "error", title: "저장 실패", text: sj.message }); return; }
      const groupObjid = sj.objId;
      const mv = await fetch("/api/m/admin/notices/groups/members/save", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ groupObjid, userIds: Array.from(groupMemberSet) }),
      });
      const mj = await mv.json();
      if (!mj.success) { Swal.fire({ icon: "error", title: "멤버 저장 실패", text: mj.message }); return; }
      await Swal.fire({ icon: "success", title: "그룹 저장 완료", timer: 1200, showConfirmButton: false });
      closeEditGroup();
      loadGroups();
    } finally { setGroupSaving(false); }
  };

  const deleteGroup = async () => {
    if (!editingGroup?.OBJID) return;
    const ok = await Swal.fire({ icon: "warning", title: `"${editingGroup.NAME}" 그룹 삭제?`, showCancelButton: true, confirmButtonColor: "#dc2626", confirmButtonText: "삭제" });
    if (!ok.isConfirmed) return;
    setGroupSaving(true);
    try {
      const r = await fetch("/api/m/admin/notices/groups/save", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ objid: editingGroup.OBJID, action: "delete" }),
      });
      const j = await r.json();
      if (j.success) {
        await Swal.fire({ icon: "success", title: "삭제됨", timer: 1000, showConfirmButton: false });
        // 발송 대상에서도 제거
        setSelectedGroups((p) => { const n = new Set(p); n.delete(editingGroup.OBJID!); return n; });
        closeEditGroup(); loadGroups();
      } else Swal.fire({ icon: "error", title: "삭제 실패", text: j.message });
    } finally { setGroupSaving(false); }
  };

  // ===== 개별 선택 토글 =====
  const toggleUser = (id: string) => {
    setSelectedUsers((p) => { const n = new Set(p); if (n.has(id)) n.delete(id); else n.add(id); return n; });
  };
  const toggleAllFiltered = () => {
    const allOn = filteredRecipients.length > 0 && filteredRecipients.every((u) => selectedUsers.has(u.USER_ID));
    setSelectedUsers((p) => {
      const n = new Set(p);
      if (allOn) filteredRecipients.forEach((u) => n.delete(u.USER_ID));
      else filteredRecipients.forEach((u) => n.add(u.USER_ID));
      return n;
    });
  };
  const toggleGroup = (id: string) => {
    setSelectedGroups((p) => { const n = new Set(p); if (n.has(id)) n.delete(id); else n.add(id); return n; });
  };

  // ===== 이미지 업로드 =====
  const onUpload = async (file: File) => {
    setUploading(true);
    try {
      const fd = new FormData();
      fd.append("file", file);
      const r = await fetch("/api/m/items/upload-image", { method: "POST", body: fd });
      const j = await r.json();
      if (j.success) setImageUrl(j.url);
      else Swal.fire({ icon: "error", title: "업로드 실패", text: j.message });
    } finally { setUploading(false); }
  };

  // ===== 발송 =====
  const send = async () => {
    if (!title.trim()) return Swal.fire({ icon: "warning", title: "제목을 입력하세요" });
    if (finalUserIds.length === 0) return Swal.fire({ icon: "warning", title: "수신자(그룹 또는 개별)를 선택하세요" });
    const ok = await Swal.fire({
      icon: "question",
      title: `${finalUserIds.length}명에게 푸시 발송`,
      text: `제목: ${title}`,
      showCancelButton: true, confirmButtonText: "발송", cancelButtonText: "취소",
      confirmButtonColor: "#0f766e",
    });
    if (!ok.isConfirmed) return;
    setSending(true);
    try {
      const sv = await fetch("/api/m/admin/notices/save", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title, body: bodyText, imageUrl, url: linkUrl }),
      });
      const svj = await sv.json();
      if (!svj.success) { Swal.fire({ icon: "error", title: "저장 실패", text: svj.message }); return; }
      const noticeObjid = svj.objId;
      const groupNames = groups.filter((g) => selectedGroups.has(g.OBJID)).map((g) => g.NAME);
      const send = await fetch("/api/m/admin/notices/send-push", {
        method: "POST", headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          noticeObjid, title, message: bodyText,
          url: linkUrl || `/m/notices/${noticeObjid}`,
          userIds: finalUserIds,
          groupNames,
        }),
      });
      const sj = await send.json();
      if (sj.success) {
        await Swal.fire({ icon: "success", title: "발송 완료", text: `성공 ${sj.sent} · 실패 ${sj.failed}`, timer: 1800, showConfirmButton: false });
        setTitle(""); setBodyText(""); setImageUrl(""); setLinkUrl("");
        setSelectedGroups(new Set()); setSelectedUsers(new Set());
        loadPast();
      } else {
        Swal.fire({ icon: "error", title: "발송 실패", text: sj.message });
      }
    } finally { setSending(false); }
  };

  // 멤버 picker (그룹 편집 패널)
  const memberPickerFiltered = useMemo(() => {
    return allUsers.filter((u) => {
      if (memberPickerKw) {
        const k = memberPickerKw.toLowerCase();
        if (!u.USER_NAME.toLowerCase().includes(k) && !u.USER_ID.toLowerCase().includes(k)) return false;
      }
      return true;
    });
  }, [allUsers, memberPickerKw]);

  return (
    <div className="space-y-3">
      <div>
        <h1 className="text-xl sm:text-2xl font-bold inline-flex items-center gap-2">
          <Bell size={18} className="text-emerald-700" /> 푸시알림 게시판
        </h1>
        <p className="text-xs text-slate-500 mt-0.5">왼쪽에서 <b>수신자 그룹</b>을 선택(또는 개별 선택)하고, 오른쪽에 제목·본문·이미지를 작성한 뒤 [발송]을 누르세요.</p>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-[460px_1fr] gap-3 items-start">
        {/* ===== 왼쪽 ===== */}
        <div className="space-y-3">
          {/* 그룹 selector */}
          <div className="bg-white border border-slate-200 rounded-xl overflow-hidden">
            <div className="px-3 py-2 bg-slate-50 border-b border-slate-200 text-xs font-semibold text-slate-600 flex items-center justify-between">
              <span className="inline-flex items-center gap-1"><Users size={13} /> 수신자 그룹 ({groups.length})</span>
              <button onClick={openNewGroup} className="text-[11px] inline-flex items-center gap-1 px-2 py-0.5 rounded bg-emerald-700 text-white font-bold hover:bg-emerald-800">
                <Plus size={11} /> 새 그룹
              </button>
            </div>
            <div className="max-h-[28vh] overflow-y-auto">
              {groups.length === 0 ? (
                <div className="text-center py-6 text-slate-400 text-sm">그룹이 없습니다. [+ 새 그룹] 으로 만들어보세요.</div>
              ) : groups.map((g) => {
                const checked = selectedGroups.has(g.OBJID);
                return (
                  <div key={g.OBJID}
                    className={`flex items-center gap-2 px-3 py-2 border-b border-slate-100 ${checked ? "bg-emerald-50/60" : "hover:bg-slate-50"}`}>
                    <input type="checkbox" checked={checked} onChange={() => toggleGroup(g.OBJID)} className="accent-emerald-600 shrink-0" />
                    <div className="min-w-0 flex-1 cursor-pointer" onClick={() => toggleGroup(g.OBJID)}>
                      <div className="text-sm font-bold truncate">{g.NAME} <span className="text-xs text-slate-500 font-normal">({g.MEMBER_CNT}명)</span></div>
                      {g.DESCRIPTION && <div className="text-[10px] text-slate-500 truncate">{g.DESCRIPTION}</div>}
                    </div>
                    <button onClick={() => openEditGroup(g)} title="멤버 관리" className="shrink-0 text-slate-400 hover:text-emerald-700 p-1">
                      <Pencil size={13} />
                    </button>
                  </div>
                );
              })}
            </div>
          </div>

          {/* 그룹 편집 패널 (권한그룹 스타일 — 아래쪽 전개) */}
          {editingGroup && (
            <div className="bg-white border border-emerald-300 rounded-xl overflow-hidden ring-2 ring-emerald-100">
              <div className="px-3 py-2 bg-emerald-50 border-b border-emerald-200 text-xs font-semibold text-emerald-800 flex items-center justify-between">
                <span>{editingGroup.OBJID ? "그룹 멤버 관리" : "새 그룹"}</span>
                <button onClick={closeEditGroup} className="text-slate-500 hover:text-rose-600"><X size={14} /></button>
              </div>
              <div className="p-3 space-y-2">
                <div>
                  <label className="text-[11px] font-semibold text-slate-600">그룹명 *</label>
                  <input value={editingGroup.NAME} onChange={(e) => setEditingGroup({ ...editingGroup, NAME: e.target.value })}
                    placeholder="예: 본사 거래처"
                    className="w-full h-9 px-2 rounded border border-slate-200 text-sm mt-1" />
                </div>
                <div>
                  <label className="text-[11px] font-semibold text-slate-600">설명 (선택)</label>
                  <input value={editingGroup.DESCRIPTION} onChange={(e) => setEditingGroup({ ...editingGroup, DESCRIPTION: e.target.value })}
                    placeholder="용도/대상 메모"
                    className="w-full h-9 px-2 rounded border border-slate-200 text-sm mt-1" />
                </div>
                <div>
                  <div className="flex items-center justify-between mb-1">
                    <label className="text-[11px] font-semibold text-slate-600">멤버 ({groupMemberSet.size}명)</label>
                    <input value={memberPickerKw} onChange={(e) => setMemberPickerKw(e.target.value)}
                      placeholder="이름/아이디 검색"
                      className="w-40 h-7 px-2 rounded border border-slate-200 text-[11px]" />
                  </div>
                  <div className="max-h-[28vh] overflow-y-auto border border-slate-200 rounded">
                    {memberPickerFiltered.length === 0 ? (
                      <div className="text-center py-6 text-slate-400 text-xs">사용자가 없습니다.</div>
                    ) : memberPickerFiltered.map((u) => {
                      const checked = groupMemberSet.has(u.USER_ID);
                      return (
                        <label key={u.USER_ID}
                          className={`flex items-center gap-2 px-2 py-1.5 border-b border-slate-100 cursor-pointer text-xs ${checked ? "bg-emerald-50/60" : "hover:bg-slate-50"}`}>
                          <input type="checkbox" checked={checked} onChange={() => toggleMemberInEdit(u.USER_ID)} className="accent-emerald-600 shrink-0" />
                          <div className="min-w-0 flex-1">
                            <div className="font-bold truncate">
                              {u.USER_NAME || u.USER_ID}
                              {u.IS_ADMIN && <span className="ml-1 text-[9px] px-1 py-0.5 rounded bg-violet-100 text-violet-700 font-bold">관리자</span>}
                              {u.SUBSCRIBED && <span className="ml-1 text-[9px] px-1 py-0.5 rounded bg-emerald-100 text-emerald-700 font-bold">구독중</span>}
                            </div>
                            <div className="text-[10px] text-slate-500 truncate">{u.USER_ID}</div>
                          </div>
                        </label>
                      );
                    })}
                  </div>
                </div>
                <div className="flex items-center justify-between pt-2 border-t border-slate-100">
                  {editingGroup.OBJID ? (
                    <button onClick={deleteGroup} disabled={groupSaving}
                      className="inline-flex items-center gap-1 h-9 px-3 rounded border border-rose-300 bg-white text-rose-700 text-xs font-bold hover:bg-rose-50 disabled:opacity-50">
                      <Trash2 size={13} /> 그룹 삭제
                    </button>
                  ) : <div />}
                  <button onClick={saveGroup} disabled={groupSaving}
                    className="inline-flex items-center gap-1 h-9 px-4 rounded bg-emerald-700 text-white text-xs font-bold hover:bg-emerald-800 disabled:opacity-50">
                    <Save size={13} /> {groupSaving ? "저장 중…" : "저장"}
                  </button>
                </div>
              </div>
            </div>
          )}

          {/* 개별 선택 (구독자) */}
          <div className="bg-white border border-slate-200 rounded-xl overflow-hidden">
            <div className="px-3 py-2 bg-slate-50 border-b border-slate-200 text-xs font-semibold text-slate-600 flex items-center justify-between">
              <span>개별 선택 (구독자 {recipients.length}명 / 선택 {selectedUsers.size})</span>
              <button onClick={toggleAllFiltered} className="text-[11px] px-2 py-0.5 rounded border border-slate-300 bg-white hover:bg-slate-100">
                {filteredRecipients.length > 0 && filteredRecipients.every((u) => selectedUsers.has(u.USER_ID)) ? "전체 해제" : "표시된 전체 선택"}
              </button>
            </div>
            <div className="p-2 flex gap-1.5 border-b border-slate-100">
              <input value={keyword} onChange={(e) => setKeyword(e.target.value)} placeholder="이름/아이디 검색"
                className="flex-1 h-8 px-2 rounded border border-slate-200 text-xs" />
              <select value={typeFilter} onChange={(e) => setTypeFilter(e.target.value as "" | "U" | "A")}
                className="h-8 px-2 rounded border border-slate-200 bg-white text-xs">
                <option value="">전체</option>
                <option value="U">거래처만</option>
                <option value="A">관리자만</option>
              </select>
            </div>
            <div className="overflow-y-auto max-h-[30vh]">
              {filteredRecipients.length === 0 ? (
                <div className="text-center py-6 text-slate-400 text-xs">구독자가 없습니다.</div>
              ) : filteredRecipients.map((u) => {
                const checked = selectedUsers.has(u.USER_ID);
                return (
                  <label key={u.USER_ID}
                    className={`flex items-center gap-2 px-3 py-1.5 border-b border-slate-100 cursor-pointer text-xs ${checked ? "bg-emerald-50/60" : "hover:bg-slate-50"}`}>
                    <input type="checkbox" checked={checked} onChange={() => toggleUser(u.USER_ID)} className="accent-emerald-600 shrink-0" />
                    <div className="min-w-0 flex-1">
                      <div className="font-bold truncate">
                        {u.USER_NAME || u.USER_ID}
                        {u.IS_ADMIN && <span className="ml-1 text-[9px] px-1 py-0.5 rounded bg-violet-100 text-violet-700 font-bold">관리자</span>}
                      </div>
                      <div className="text-[10px] text-slate-500 truncate">{u.USER_ID}</div>
                    </div>
                  </label>
                );
              })}
            </div>
          </div>
        </div>

        {/* ===== 오른쪽 ===== */}
        <div className="space-y-3">
          <div className="bg-white border border-slate-200 rounded-xl p-4 space-y-3">
            <div>
              <label className="text-xs font-semibold text-slate-600">제목 *</label>
              <input value={title} onChange={(e) => setTitle(e.target.value)}
                placeholder="예: 오늘의 특가" maxLength={60}
                className="w-full h-10 px-3 rounded-lg border border-slate-200 text-sm mt-1" />
              <div className="text-[10px] text-slate-400 mt-0.5">푸시 알림의 제목으로 표시 (60자 이내)</div>
            </div>
            <div>
              <label className="text-xs font-semibold text-slate-600">본문</label>
              <textarea value={bodyText} onChange={(e) => setBodyText(e.target.value)}
                placeholder="알림 내용 + 공지 페이지 본문이 됩니다." rows={6}
                className="w-full px-3 py-2 rounded-lg border border-slate-200 text-sm mt-1 resize-y" />
              <div className="text-[10px] text-slate-400 mt-0.5">푸시 본문에는 앞 240자만 노출. 전체 본문은 공지 페이지에서 확인.</div>
            </div>
            <div>
              <label className="text-xs font-semibold text-slate-600">이미지 첨부 (선택)</label>
              <div className="flex items-center gap-2 mt-1">
                <label className="inline-flex items-center gap-1 h-9 px-3 rounded-lg border border-slate-300 bg-white text-xs font-semibold cursor-pointer hover:bg-slate-50">
                  <Upload size={14} /> 파일 선택
                  <input type="file" accept="image/*" className="hidden"
                    onChange={(e) => { const f = e.target.files?.[0]; if (f) onUpload(f); }} />
                </label>
                {imageUrl && (
                  <button type="button" onClick={() => setImageUrl("")} className="text-rose-500 hover:text-rose-700" title="이미지 제거"><X size={14} /></button>
                )}
                {uploading && <span className="text-xs text-slate-400">업로드 중…</span>}
              </div>
              {imageUrl && (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={imageUrl} alt="첨부" className="mt-2 max-h-64 rounded border border-slate-200" />
              )}
            </div>
            <div>
              <label className="text-xs font-semibold text-slate-600">외부 링크 (선택)</label>
              <input value={linkUrl} onChange={(e) => setLinkUrl(e.target.value)}
                placeholder="https://… (입력 시 푸시 탭하면 해당 URL 로 이동)"
                className="w-full h-10 px-3 rounded-lg border border-slate-200 text-sm mt-1" />
              <div className="text-[10px] text-slate-400 mt-0.5">비워두면 자체 공지 페이지(이미지+본문)로 이동합니다.</div>
            </div>
            <div className="flex justify-between items-center pt-2 border-t border-slate-100">
              <div className="text-xs text-slate-500">
                선택 그룹 {selectedGroups.size} · 개별 {selectedUsers.size} · <b className="text-emerald-700">대상 {finalUserIds.length}명</b>
              </div>
              <button onClick={send} disabled={sending}
                className="inline-flex items-center gap-2 px-5 h-11 rounded-xl bg-emerald-700 text-white text-sm font-bold hover:bg-emerald-800 disabled:opacity-50">
                <Send size={14} /> {sending ? "발송 중…" : `${finalUserIds.length}명에게 발송`}
              </button>
            </div>
          </div>

          {/* 최근 공지 */}
          <div className="bg-white border border-slate-200 rounded-xl overflow-hidden">
            <div className="px-3 py-2 bg-slate-50 border-b border-slate-200 text-xs font-semibold text-slate-600">최근 공지 ({past.length}건)</div>
            <div className="divide-y divide-slate-100 max-h-[40vh] overflow-y-auto">
              {past.length === 0 ? (
                <div className="text-center py-8 text-slate-400 text-sm">아직 작성된 공지가 없습니다.</div>
              ) : past.map((n) => (
                <a key={n.OBJID} href={`/m/notices/${n.OBJID}`} target="_blank" rel="noreferrer"
                   className="flex items-center gap-3 px-3 py-2 hover:bg-slate-50">
                  {n.IMAGE_URL && (
                    // eslint-disable-next-line @next/next/no-img-element
                    <img src={n.IMAGE_URL} alt="" className="w-12 h-12 rounded object-cover shrink-0" />
                  )}
                  <div className="min-w-0 flex-1">
                    <div className="text-sm font-bold truncate">{n.TITLE}</div>
                    <div className="text-[11px] text-slate-500 truncate">{n.REGDATE} · 발송 {n.SENT_COUNT ?? 0}건</div>
                  </div>
                </a>
              ))}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
