"use client";

import { useEffect, useRef, useState } from "react";
import { Button } from "@/components/ui/Button";
import { SubjectAvatar } from "@/components/ui/SubjectAvatar";
import { SocialAttachSheet } from "@/components/social/SocialAttachSheet";
import { SocialEmojiPicker } from "@/components/social/SocialEmojiPicker";
import { SocialMessageBubble, type SocialPost } from "@/components/social/SocialMessageBubble";
import { SocialSpaceInfoPanel } from "@/components/social/SocialSpaceInfoPanel";
import { SocialPollComposer } from "@/components/social/SocialPollComposer";
import type { SocialSendPayload } from "@/components/social/social-types";
import { useVoiceRecorder, VoiceRecordingBar } from "@/components/social/SocialVoiceRecorder";

export type SpaceDetails = {
  id: number;
  pair_id: number;
  type: "channel" | "group";
  kind?: "social" | "system_announcement" | "school_announcement" | "class_announcement";
  broadcast_space_id?: number | null;
  title: string;
  is_verified?: boolean;
  is_active?: boolean;
  linked_space_id?: number | null;
  class_room_id?: number;
  subject_id?: number;
  class_code?: string | null;
  subject_name?: string | null;
  subject_image_url?: string | null;
  members_count?: number;
  my_role?: string | null;
  can_post?: boolean;
  can_moderate?: boolean;
  can_appoint_leader?: boolean;
  can_roll_call?: boolean;
  can_toggle_active?: boolean;
  can_appoint_admins?: boolean;
};

function useIsDesktop() {
  const [desktop, setDesktop] = useState(false);
  useEffect(() => {
    const mq = window.matchMedia("(min-width: 1024px)");
    const sync = () => setDesktop(mq.matches);
    sync();
    mq.addEventListener("change", sync);
    return () => mq.removeEventListener("change", sync);
  }, []);
  return desktop;
}

function insertAtCursor(value: string, insertion: string, start: number, end: number) {
  const before = value.slice(0, start);
  const after = value.slice(end);
  return {
    next: before + insertion + after,
    cursor: start + insertion.length,
  };
}

export function SocialSpacePane({
  space,
  posts,
  pinned,
  onSwitchPair,
  onReply,
  onSend,
  onVotePoll,
  votingPollId,
  onPin,
  onUnpin,
  onDelete,
  onTagSearch,
  onOpenMessageSearch,
  onOpenRollCall,
  onBack,
  onToggleActive,
  scheduleId,
  rollCall,
  sending,
}: {
  space: SpaceDetails;
  posts: SocialPost[];
  pinned?: SocialPost | null;
  onSwitchPair: () => void;
  onReply: (post: SocialPost) => void;
  onSend: (payload: SocialSendPayload) => Promise<void>;
  onVotePoll?: (postId: number, optionId: number) => Promise<void>;
  votingPollId?: number | null;
  onPin: (post: SocialPost) => void;
  onUnpin: (post: SocialPost) => void;
  onDelete: (post: SocialPost) => void;
  onTagSearch: (raw: string) => void;
  onOpenMessageSearch?: () => void;
  onOpenRollCall?: () => void;
  onBack?: () => void;
  onToggleActive?: () => void | Promise<void>;
  scheduleId?: number | null;
  rollCall?: { id: number; closes_at?: string; is_open?: boolean; responses_count?: number } | null;
  sending?: boolean;
}) {
  const [replyTo, setReplyTo] = useState<SocialPost | null>(null);
  const [body, setBody] = useState("");
  const [file, setFile] = useState<File | null>(null);
  const [menu, setMenu] = useState<{ post: SocialPost; x: number; y: number } | null>(null);
  const [attachOpen, setAttachOpen] = useState(false);
  const [emojiOpen, setEmojiOpen] = useState(false);
  const [infoOpen, setInfoOpen] = useState(false);
  const [pollOpen, setPollOpen] = useState(false);
  const voice = useVoiceRecorder();
  const [selection, setSelection] = useState({ start: 0, end: 0 });
  const mediaRef = useRef<HTMLInputElement>(null);
  const fileRef = useRef<HTMLInputElement>(null);
  const bodyInputRef = useRef<HTMLInputElement>(null);
  const listRef = useRef<HTMLDivElement>(null);
  const isDesktop = useIsDesktop();
  const avatarName = space.subject_name ?? space.title;

  useEffect(() => {
    listRef.current?.scrollTo({ top: listRef.current.scrollHeight });
  }, [posts.length, space.id]);

  const submit = async () => {
    if (!body.trim() && !file) return;
    await onSend({ body: body.trim(), replyToId: replyTo?.id ?? null, file });
    setBody("");
    setFile(null);
    setReplyTo(null);
  };

  const submitPoll = async (question: string, options: string[]) => {
    await onSend({ pollQuestion: question, pollOptions: options, replyToId: replyTo?.id ?? null });
    setReplyTo(null);
  };

  const submitVoice = async () => {
    const result = await voice.stop();
    if (!result) return;
    await onSend({
      file: result.file,
      postType: "voice",
      durationSeconds: result.durationSeconds,
      replyToId: replyTo?.id ?? null,
    });
    setReplyTo(null);
  };

  const startVoice = async () => {
    setAttachOpen(false);
    setEmojiOpen(false);
    await voice.start();
  };

  const syncSelection = () => {
    const el = bodyInputRef.current;
    if (!el) return;
    setSelection({ start: el.selectionStart ?? body.length, end: el.selectionEnd ?? body.length });
  };

  const insertEmoji = (emoji: string) => {
    const el = bodyInputRef.current;
    const start = el?.selectionStart ?? selection.start ?? body.length;
    const end = el?.selectionEnd ?? selection.end ?? body.length;
    const { next, cursor } = insertAtCursor(body, emoji, start, end);
    setBody(next);
    requestAnimationFrame(() => {
      el?.focus();
      el?.setSelectionRange(cursor, cursor);
      setSelection({ start: cursor, end: cursor });
    });
  };

  const backspaceEmoji = () => {
    const el = bodyInputRef.current;
    const start = el?.selectionStart ?? selection.start ?? body.length;
    const end = el?.selectionEnd ?? selection.end ?? body.length;
    if (start !== end) {
      const next = body.slice(0, start) + body.slice(end);
      setBody(next);
      requestAnimationFrame(() => {
        el?.focus();
        el?.setSelectionRange(start, start);
        setSelection({ start, end: start });
      });
      return;
    }
    if (start <= 0) return;
    const before = body.slice(0, start);
    const after = body.slice(start);
    const chars = [...before];
    chars.pop();
    const next = chars.join("") + after;
    const cursor = chars.join("").length;
    setBody(next);
    requestAnimationFrame(() => {
      el?.focus();
      el?.setSelectionRange(cursor, cursor);
      setSelection({ start: cursor, end: cursor });
    });
  };

  const openAttach = () => {
    setEmojiOpen(false);
    setAttachOpen((v) => !v);
  };

  const openEmoji = () => {
    setAttachOpen(false);
    setEmojiOpen((v) => !v);
    syncSelection();
  };

  return (
    <div className="relative flex min-h-0 min-w-0 flex-1 flex-col bg-[#e8ece9]">
      <header className="z-10 flex items-center gap-2 border-b border-slate-200/80 bg-white/95 px-2 py-2.5 shadow-sm backdrop-blur-sm pt-[max(0.625rem,env(safe-area-inset-top))] sm:gap-3 sm:px-4 sm:pt-2.5">
        {onBack ? (
          <button
            type="button"
            onClick={onBack}
            className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-slate-600 hover:bg-slate-100 lg:hidden"
            aria-label="بازگشت"
          >
            <svg viewBox="0 0 24 24" className="h-5 w-5" fill="none" stroke="currentColor" strokeWidth="2.2" aria-hidden>
              <path d="M9 5l7 7-7 7" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </button>
        ) : null}
        <button
          type="button"
          onClick={() => setInfoOpen(true)}
          className="flex min-w-0 flex-1 items-center gap-2 rounded-xl px-1 py-1 text-right transition hover:bg-slate-50 sm:gap-3"
          aria-label="اطلاعات گفتگو"
        >
          <div className="relative shrink-0">
            <SubjectAvatar
              name={avatarName}
              imageUrl={space.subject_image_url}
              size="md"
              className="rounded-2xl ring-2 ring-white shadow-md"
            />
            <span
              className={`absolute -bottom-0.5 -left-0.5 rounded-md px-1 py-px text-[9px] font-bold text-white shadow ${
                space.type === "group" ? "bg-teal-600" : "bg-sky-500"
              }`}
            >
              {space.type === "group" ? "گ" : "ک"}
            </span>
          </div>
          <div className="min-w-0 flex-1">
            <div className="flex items-center gap-1.5">
              <h2 className="truncate text-sm font-bold text-slate-900 sm:text-base">{space.title}</h2>
              {space.is_verified ? <span className="text-sky-500">✓</span> : null}
              {space.is_active === false ? (
                <span className="rounded-full bg-slate-200 px-2 py-0.5 text-[10px] font-bold text-slate-600">
                  غیرفعال
                </span>
              ) : null}
            </div>
            <div className="truncate text-[11px] text-slate-500">
              {space.kind === "school_announcement"
                ? "کانال مدرسه"
                : space.kind === "class_announcement"
                  ? "اعلان کلاس"
                  : space.kind === "system_announcement"
                    ? "اطلاعیه‌های سامانه"
                    : `${space.members_count ?? 0} عضو${space.subject_name ? ` · ${space.subject_name}` : space.type === "group" ? " · گروه" : " · کانال"}`}
            </div>
          </div>
        </button>
        <div className="flex shrink-0 items-center gap-1">
          <div className="hidden rounded-xl border border-slate-200 bg-slate-50 p-0.5 sm:flex">
            <button
              type="button"
              disabled={!space.linked_space_id}
              className={`rounded-lg px-2.5 py-1 text-[11px] font-semibold disabled:opacity-50 ${space.type === "channel" ? "bg-teal-600 text-white shadow-sm" : "text-slate-600"}`}
              onClick={() => space.type !== "channel" && onSwitchPair()}
            >
              کانال
            </button>
            <button
              type="button"
              disabled={!space.linked_space_id}
              className={`rounded-lg px-2.5 py-1 text-[11px] font-semibold disabled:opacity-50 ${space.type === "group" ? "bg-teal-600 text-white shadow-sm" : "text-slate-600"}`}
              onClick={() => space.type !== "group" && onSwitchPair()}
            >
              گروه
            </button>
          </div>
          <button
            type="button"
            className="rounded-lg p-2 text-slate-600 hover:bg-slate-100 sm:border sm:border-slate-200 sm:px-2 sm:py-1.5 sm:text-xs"
            onClick={() => onOpenMessageSearch?.()}
            aria-label="جستجوی پیام"
          >
            <span className="hidden sm:inline">جستجو</span>
            <svg viewBox="0 0 24 24" className="h-5 w-5 sm:hidden" fill="currentColor" aria-hidden>
              <path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
            </svg>
          </button>
          {space.can_roll_call && scheduleId ? (
            <Button className="hidden px-2.5 py-1.5 text-xs sm:inline-flex" onClick={onOpenRollCall}>
              حضور
            </Button>
          ) : null}
        </div>
      </header>

      {space.linked_space_id ? (
        <div className="flex border-b border-slate-200 bg-white sm:hidden">
          <button
            type="button"
            className={`flex-1 py-2 text-xs font-semibold ${space.type === "channel" ? "border-b-2 border-teal-600 text-teal-700" : "text-slate-500"}`}
            onClick={() => space.type !== "channel" && onSwitchPair()}
          >
            کانال
          </button>
          <button
            type="button"
            className={`flex-1 py-2 text-xs font-semibold ${space.type === "group" ? "border-b-2 border-teal-600 text-teal-700" : "text-slate-500"}`}
            onClick={() => space.type !== "group" && onSwitchPair()}
          >
            گروه
          </button>
        </div>
      ) : null}

      {pinned ? (
        <div className="flex items-center gap-2 border-b border-teal-100 bg-teal-50/95 px-3 py-2 text-xs text-teal-900">
          <span className="font-bold">📌</span>
          <span className="truncate">{pinned.body}</span>
        </div>
      ) : null}

      {rollCall?.is_open ? (
        <div className="border-b border-violet-100 bg-violet-50 px-3 py-2 text-xs text-violet-900">
          حضور آنلاین باز · {rollCall.responses_count ?? 0} پاسخ
        </div>
      ) : null}

      {space.can_roll_call && scheduleId ? (
        <div className="border-b border-slate-100 bg-white px-3 py-2 sm:hidden">
          <Button className="w-full py-2 text-xs" onClick={onOpenRollCall}>
            شروع حضور آنلاین
          </Button>
        </div>
      ) : null}

      <div ref={listRef} className="social-chat-wallpaper min-h-0 flex-1 space-y-3 overflow-y-auto px-3 py-3 sm:px-5 sm:py-4">
        {!posts.length ? (
          <div className="flex h-full min-h-[12rem] items-center justify-center">
            <div className="rounded-2xl bg-white/70 px-6 py-4 text-center text-sm text-slate-500 shadow-sm backdrop-blur-sm">
              هنوز پیامی ارسال نشده
            </div>
          </div>
        ) : (
          [...posts].reverse().map((post) => (
            <div key={post.id} className="flex justify-start">
              <SocialMessageBubble
                post={post}
                onTagClick={onTagSearch}
                onVotePoll={onVotePoll ? (postId, optionId) => void onVotePoll(postId, optionId) : undefined}
                votingPollId={votingPollId}
                onOpenMenu={(p, el) => {
                  const rect = el.getBoundingClientRect();
                  setMenu({ post: p, x: rect.left, y: rect.top });
                }}
              />
            </div>
          ))
        )}
      </div>

      {space.can_post ? (
        <div className="relative z-10 border-t border-slate-200/80 bg-white/95 px-2 py-2 pb-[max(0.5rem,env(safe-area-inset-bottom))] backdrop-blur-sm sm:p-3">
          {replyTo ? (
            <div className="mb-2 flex items-center justify-between rounded-xl border-r-4 border-teal-500 bg-slate-50 px-3 py-2 text-xs">
              <div className="min-w-0">
                <div className="font-semibold text-teal-700">پاسخ به {replyTo.author.name}</div>
                <div className="line-clamp-1 text-slate-500">{replyTo.body}</div>
              </div>
              <button type="button" className="rounded-full px-2 py-1 text-slate-400 hover:bg-slate-200" onClick={() => setReplyTo(null)}>
                ×
              </button>
            </div>
          ) : null}
          {voice.recording ? (
            <VoiceRecordingBar seconds={voice.seconds} onCancel={voice.cancel} onSend={() => void submitVoice()} sending={sending} />
          ) : null}
          {voice.error ? <div className="mb-2 text-xs text-rose-600">{voice.error}</div> : null}
          {file ? (
            <div className="mb-2 flex items-center gap-2 rounded-xl bg-teal-50 px-3 py-2 text-xs text-teal-800">
              <span className="truncate">{file.name}</span>
              <button type="button" className="shrink-0 text-teal-600" onClick={() => setFile(null)}>
                حذف
              </button>
            </div>
          ) : null}
          <div className="flex items-end gap-1 sm:gap-2">
            <div className="relative shrink-0">
              <button
                type="button"
                onClick={openAttach}
                className={`flex h-11 w-11 items-center justify-center rounded-full transition ${
                  attachOpen ? "bg-teal-100 text-teal-800" : "text-teal-700 hover:bg-teal-50"
                }`}
                aria-label="پیوست"
                aria-expanded={attachOpen}
              >
                <svg viewBox="0 0 24 24" className="h-6 w-6" fill="currentColor" aria-hidden>
                  <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
                </svg>
              </button>
              {isDesktop && attachOpen ? (
                <SocialAttachSheet
                  open
                  variant="popover"
                  onClose={() => setAttachOpen(false)}
                  onPickMedia={() => mediaRef.current?.click()}
                  onPickFile={() => fileRef.current?.click()}
                  onPickVoice={() => void startVoice()}
                  onPoll={() => setPollOpen(true)}
                />
              ) : null}
            </div>
            <div className="relative shrink-0">
              <button
                type="button"
                onClick={openEmoji}
                className={`flex h-11 w-11 items-center justify-center rounded-full transition ${
                  emojiOpen ? "bg-teal-100 text-teal-800" : "text-slate-500 hover:bg-slate-100"
                }`}
                aria-label="ایموجی"
                aria-expanded={emojiOpen}
              >
                <svg viewBox="0 0 24 24" className="h-6 w-6" fill="currentColor" aria-hidden>
                  <path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM8.5 8c.83 0 1.5.67 1.5 1.5S9.33 11 8.5 11 7 10.33 7 9.5 7.67 8 8.5 8zm7 0c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5-1.5-.67-1.5-1.5S14.67 8 15.5 8zm-3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z" />
                </svg>
              </button>
              {isDesktop && emojiOpen ? (
                <SocialEmojiPicker
                  open
                  variant="popover"
                  onClose={() => setEmojiOpen(false)}
                  onPick={insertEmoji}
                  onBackspace={backspaceEmoji}
                />
              ) : null}
            </div>
            <input
              ref={bodyInputRef}
              value={body}
              onChange={(e) => setBody(e.target.value)}
              onClick={syncSelection}
              onKeyUp={syncSelection}
              onSelect={syncSelection}
              placeholder={voice.recording ? "در حال ضبط صدا…" : "پیام خود را بنویسید…"}
              disabled={voice.recording}
              className="min-h-[44px] flex-1 rounded-2xl border border-slate-200/80 bg-slate-50/80 px-4 py-2.5 text-sm outline-none transition focus:border-teal-400 focus:bg-white focus:shadow-sm disabled:opacity-50"
              onKeyDown={(e) => {
                if (e.key === "Enter" && !e.shiftKey) {
                  e.preventDefault();
                  void submit();
                }
              }}
            />
            {body.trim() || file ? (
              <button
                type="button"
                disabled={sending || voice.recording}
                onClick={() => void submit()}
                className="flex h-11 w-11 shrink-0 items-center justify-center rounded-full bg-teal-600 text-white shadow-sm shadow-teal-600/30 disabled:opacity-40"
                aria-label="ارسال"
              >
                <svg viewBox="0 0 24 24" className="h-5 w-5 -scale-x-100" fill="currentColor" aria-hidden>
                  <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" />
                </svg>
              </button>
            ) : (
              <button
                type="button"
                disabled={sending || voice.recording}
                onClick={() => void startVoice()}
                className="flex h-11 w-11 shrink-0 items-center justify-center rounded-full text-slate-500 hover:bg-teal-50 hover:text-teal-700"
                aria-label="پیام صوتی"
              >
                <svg viewBox="0 0 24 24" className="h-6 w-6" fill="currentColor" aria-hidden>
                  <path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.91-3c-.49 0-.9.36-.98.85C16.52 14.2 14.47 16 12 16s-4.52-1.8-4.93-4.15c-.08-.49-.49-.85-.98-.85-.61 0-1.09.54-1 1.14.49 3 2.89 5.35 5.91 5.78V20c0 .55.45 1 1 1s1-.45 1-1v-2.08c3.02-.43 5.42-2.78 5.91-5.78.1-.6-.39-1.14-1-1.14z" />
                </svg>
              </button>
            )}
          </div>
          <input
            ref={mediaRef}
            type="file"
            accept="image/*,video/*"
            className="hidden"
            onChange={(e) => {
              setFile(e.target.files?.[0] ?? null);
              setAttachOpen(false);
            }}
          />
          <input
            ref={fileRef}
            type="file"
            className="hidden"
            onChange={(e) => {
              setFile(e.target.files?.[0] ?? null);
              setAttachOpen(false);
            }}
          />
        </div>
      ) : (
        <div className="border-t border-slate-200 bg-slate-50 px-4 py-3 text-center text-sm text-slate-500">
          فقط مشاهده
        </div>
      )}

      {!isDesktop ? (
        <SocialAttachSheet
          open={attachOpen}
          onClose={() => setAttachOpen(false)}
          onPickMedia={() => mediaRef.current?.click()}
          onPickFile={() => fileRef.current?.click()}
          onPickVoice={() => void startVoice()}
          onPoll={() => setPollOpen(true)}
        />
      ) : null}

      {!isDesktop ? (
        <SocialEmojiPicker
          open={emojiOpen}
          onClose={() => setEmojiOpen(false)}
          onPick={insertEmoji}
          onBackspace={backspaceEmoji}
        />
      ) : null}

      <SocialPollComposer open={pollOpen} onClose={() => setPollOpen(false)} onSubmit={submitPoll} sending={sending} />

      <SocialSpaceInfoPanel
        open={infoOpen}
        onClose={() => setInfoOpen(false)}
        space={space}
        pinned={pinned}
        onSwitchPair={onSwitchPair}
        onOpenMessageSearch={onOpenMessageSearch}
        onOpenRollCall={onOpenRollCall}
        onToggleActive={onToggleActive}
        scheduleId={scheduleId}
      />

      {menu ? (
        <div className="fixed inset-0 z-50" onClick={() => setMenu(null)}>
          <div
            className="absolute min-w-[180px] overflow-hidden rounded-2xl border border-slate-200 bg-white shadow-xl"
            style={{
              left: Math.min(menu.x, typeof window !== "undefined" ? window.innerWidth - 200 : menu.x),
              top: Math.min(menu.y, typeof window !== "undefined" ? window.innerHeight - 260 : menu.y),
            }}
            onClick={(e) => e.stopPropagation()}
          >
            {[
              {
                label: "پاسخ",
                action: () => {
                  setReplyTo(menu.post);
                  onReply(menu.post);
                  setMenu(null);
                },
              },
              space.can_moderate
                ? {
                    label: menu.post.is_pinned ? "برداشتن سنجاق" : "سنجاق کردن",
                    action: () => {
                      if (menu.post.is_pinned) onUnpin(menu.post);
                      else onPin(menu.post);
                      setMenu(null);
                    },
                  }
                : null,
              space.can_moderate || menu.post.author.id
                ? {
                    label: "حذف",
                    action: () => {
                      onDelete(menu.post);
                      setMenu(null);
                    },
                  }
                : null,
            ]
              .filter(Boolean)
              .map((item) => (
                <button
                  key={item!.label}
                  type="button"
                  className="block w-full px-4 py-2.5 text-right text-sm hover:bg-slate-50"
                  onClick={item!.action}
                >
                  {item!.label}
                </button>
              ))}
          </div>
        </div>
      ) : null}
    </div>
  );
}
