import { useState, useRef, useEffect, useCallback } from 'react';
import { router, usePage } from '@inertiajs/react';
import { AppLayout } from '@/Components/Layout/AppLayout';
import { getEcho } from '@/lib/echo';

type ChatMessage = { id: number; body: string; sender: string; isOwn: boolean; createdAt: string };
type Thread = {
  id: number;
  subject: string;
  unread: number;
  lastBody: string;
  lastSender: string;
  lastAt: string;
  lastIsOwn: boolean;
  messages: ChatMessage[];
};
type User = { id: number; name: string; role: string };
type Classroom = { id: number; name: string };

type Props = {
  threads: Thread[];
  users: User[];
  classrooms: Classroom[];
  classroomStudentIds: Record<number, number[]>;
};

function csrf(): string {
  return (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '';
}

export default function SchoolMessages({ threads: initialThreads, users, classrooms, classroomStudentIds }: Props) {
  const { props: pageProps } = usePage<{ auth?: { user?: { id: number } | null }; realtime?: { key?: string } }>();
  const myId = pageProps.auth?.user?.id ?? null;

  const [threads, setThreads] = useState<Thread[]>(initialThreads);
  const [activeId, setActiveId] = useState<number | null>(initialThreads[0]?.id ?? null);
  const [live, setLive] = useState(false);
  const [composing, setComposing] = useState(false);
  const [replyBody, setReplyBody] = useState('');
  const [sending, setSending] = useState(false);

  // compose form state
  const [recipientIds, setRecipientIds] = useState<number[]>([]);
  const [subject, setSubject] = useState('');
  const [composeBody, setComposeBody] = useState('');
  const [composeProcessing, setComposeProcessing] = useState(false);
  const [searchUser, setSearchUser] = useState('');

  const chatEndRef = useRef<HTMLDivElement>(null);
  const replyRef = useRef<HTMLTextAreaElement>(null);

  const activeThread = threads.find(t => t.id === activeId) ?? null;
  const totalUnread = threads.reduce((s, t) => s + t.unread, 0);

  useEffect(() => {
    chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [activeId, activeThread?.messages.length]);

  // Props are the source of truth. Without this, local state keeps the threads
  // from first render and anything sent afterwards only shows up on a refresh.
  useEffect(() => {
    setThreads(initialThreads);
    setActiveId((current) =>
      current !== null && initialThreads.some((t) => t.id === current)
        ? current
        : initialThreads[0]?.id ?? null
    );
  }, [initialThreads]);

  /** Merge an incoming message into its thread, ignoring duplicates. */
  const appendMessage = useCallback((threadId: number, msg: ChatMessage, bumpUnread: boolean) => {
    setThreads((prev) => prev.map((t) => {
      if (t.id !== threadId) return t;
      if (t.messages.some((m) => m.id === msg.id)) return t;
      return {
        ...t,
        messages: [...t.messages, msg],
        lastBody: msg.body,
        lastSender: msg.sender,
        lastAt: msg.createdAt,
        lastIsOwn: msg.isOwn,
        unread: bumpUnread ? t.unread + 1 : t.unread,
      };
    }));
  }, []);

  // Live delivery over Reverb; falls back to polling when the socket is absent.
  useEffect(() => {
    if (!myId) return;

    const echo = getEcho(pageProps.realtime?.key);

    if (echo) {
      const channel = echo.private(`chat.${myId}`);
      channel.listen('.message.sent', (payload: { threadId: number; message: ChatMessage }) => {
        setLive(true);
        setActiveId((current) => {
          appendMessage(payload.threadId, payload.message, payload.threadId !== current);
          return current;
        });
        // A brand-new thread isn't in local state yet — pull the list fresh.
        setThreads((prev) => {
          if (!prev.some((t) => t.id === payload.threadId)) {
            router.reload({ only: ['threads'] });
          }
          return prev;
        });
      });

      const pusher = (echo.connector as unknown as { pusher?: { connection?: { bind: (e: string, cb: () => void) => void } } }).pusher;
      pusher?.connection?.bind('connected', () => setLive(true));
      pusher?.connection?.bind('unavailable', () => setLive(false));
      pusher?.connection?.bind('failed', () => setLive(false));

      return () => {
        echo.leave(`chat.${myId}`);
      };
    }

    // No socket: poll for new threads/messages.
    const timer = window.setInterval(() => {
      router.reload({ only: ['threads'] });
    }, 5000);
    return () => window.clearInterval(timer);
  }, [myId, appendMessage, pageProps.realtime?.key]);

  // Select thread + mark unread as read
  const selectThread = useCallback((t: Thread) => {
    setActiveId(t.id);
    setComposing(false);
    if (t.unread > 0) {
      const unreadIds = t.messages.filter(m => !m.isOwn).map(m => m.id);
      unreadIds.forEach(id => {
        fetch(`/school/messages/${id}/read`, { method: 'PATCH', headers: { 'X-CSRF-TOKEN': csrf() } });
      });
      setThreads(prev => prev.map(x => x.id === t.id ? { ...x, unread: 0 } : x));
    }
    setTimeout(() => replyRef.current?.focus(), 100);
  }, []);

  const sendReply = useCallback(() => {
    if (!replyBody.trim() || !activeId || sending) return;
    setSending(true);
    router.post(
      `/school/messages/${activeId}/reply`,
      { body: replyBody },
      {
        preserveScroll: true,
        onSuccess: () => setReplyBody(''),
        // onFinish always runs — without it any unexpected error (a 500, a
        // dropped connection) leaves the button spinning forever.
        onFinish: () => setSending(false),
      }
    );
  }, [replyBody, activeId, sending]);

  const sendCompose = useCallback((e: React.FormEvent) => {
    e.preventDefault();
    if (!composeBody.trim() || recipientIds.length === 0 || composeProcessing) return;
    setComposeProcessing(true);
    router.post(
      '/school/messages',
      { recipient_ids: recipientIds, subject, body: composeBody },
      {
        onSuccess: () => {
          setComposing(false);
          setRecipientIds([]);
          setSubject('');
          setComposeBody('');
        },
        // onFinish always runs, even on a 500 — otherwise the button spins forever.
        onFinish: () => setComposeProcessing(false),
      }
    );
  }, [composeBody, recipientIds, subject, composeProcessing]);

  const toggleRecipient = (id: number) => {
    setRecipientIds(prev => prev.includes(id) ? prev.filter(r => r !== id) : [...prev, id]);
  };

  const addClassroom = (cid: string) => {
    const ids = classroomStudentIds[Number(cid)] ?? [];
    setRecipientIds(prev => Array.from(new Set([...prev, ...ids])));
  };

  const filteredUsers = searchUser.trim()
    ? users.filter(u => u.name.includes(searchUser) || u.role.includes(searchUser))
    : users;

  const handleReplyKey = (e: React.KeyboardEvent) => {
    if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) sendReply();
  };

  return (
    <AppLayout title="پیام‌رسانی">
      <div style={{ display: 'flex', height: 'calc(100vh - 120px)', minHeight: 520, gap: 0, borderRadius: 'var(--radius-lg)', overflow: 'hidden', border: '1px solid var(--color-border)', background: 'var(--color-surface)' }}>

        {/* ── Left: Thread list ── */}
        <div style={{ width: 300, minWidth: 260, borderLeft: '1px solid var(--color-border)', display: 'flex', flexDirection: 'column', background: 'var(--color-bg-soft)' }}>
          {/* header */}
          <div style={{ padding: '0.85rem 1rem', borderBottom: '1px solid var(--color-border)', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
            <span style={{ fontWeight: 700, fontSize: '0.97rem', flex: 1 }}>
              <i className="bi bi-chat-dots-fill" style={{ color: 'var(--color-primary)', marginLeft: '0.4rem' }} />
              گفتگوها
              {totalUnread > 0 && (
                <span style={{ background: '#EF4444', color: '#fff', borderRadius: 999, fontSize: '0.68rem', padding: '0.06rem 0.4rem', marginRight: '0.4rem' }}>
                  {totalUnread}
                </span>
              )}
            </span>
            <button
              className="btn btn-primary btn-sm"
              onClick={() => { setComposing(true); setActiveId(null); }}
              title="پیام جدید"
            >
              <i className="bi bi-pencil-square" />
            </button>
          </div>

          {/* list */}
          <div style={{ flex: 1, overflowY: 'auto' }}>
            {threads.length === 0 ? (
              <div style={{ padding: '2rem 1rem', textAlign: 'center', color: 'var(--color-text-muted)', fontSize: '0.85rem' }}>
                <i className="bi bi-inbox" style={{ fontSize: '2rem', display: 'block', marginBottom: '0.5rem', opacity: 0.4 }} />
                هیچ گفتگویی وجود ندارد
              </div>
            ) : (
              threads.map(t => (
                <button
                  key={t.id}
                  onClick={() => selectThread(t)}
                  style={{
                    width: '100%',
                    textAlign: 'right',
                    padding: '0.75rem 1rem',
                    background: activeId === t.id ? 'var(--color-primary-soft)' : 'transparent',
                    cursor: 'pointer',
                    border: 'none',
                    borderBottom: '1px solid var(--color-border)',
                    borderRight: activeId === t.id ? '3px solid var(--color-primary)' : '3px solid transparent',
                    display: 'block',
                    fontFamily: 'inherit',
                    transition: 'background 0.15s',
                  }}
                >
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: '0.3rem' }}>
                    <span style={{ fontWeight: t.unread > 0 ? 700 : 500, fontSize: '0.875rem', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1, color: 'var(--color-text)' }}>
                      {t.subject}
                    </span>
                    <span style={{ fontSize: '0.68rem', color: 'var(--color-text-muted)', flexShrink: 0, marginTop: '0.1rem' }}>{t.lastAt}</span>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: '0.3rem', marginTop: '0.18rem' }}>
                    {t.lastIsOwn && <i className="bi bi-arrow-return-left" style={{ fontSize: '0.7rem', color: 'var(--color-text-muted)', flexShrink: 0 }} />}
                    <span style={{ fontSize: '0.78rem', color: 'var(--color-text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 }}>
                      {t.lastIsOwn ? 'شما: ' : `${t.lastSender}: `}{t.lastBody}
                    </span>
                    {t.unread > 0 && (
                      <span style={{ background: 'var(--color-primary)', color: '#fff', borderRadius: 999, fontSize: '0.65rem', padding: '0.05rem 0.38rem', flexShrink: 0 }}>
                        {t.unread}
                      </span>
                    )}
                  </div>
                </button>
              ))
            )}
          </div>
        </div>

        {/* ── Right: Chat view ── */}
        <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
          {composing ? (
            // Compose new thread
            <form onSubmit={sendCompose} style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
              <div style={{ padding: '0.85rem 1.2rem', borderBottom: '1px solid var(--color-border)', display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                <button type="button" className="btn btn-ghost btn-sm" onClick={() => setComposing(false)}>
                  <i className="bi bi-arrow-right" />
                </button>
                <strong style={{ fontSize: '0.97rem' }}>گفتگوی جدید</strong>
              </div>
              <div style={{ flex: 1, padding: '1.2rem', overflowY: 'auto', display: 'flex', flexDirection: 'column', gap: '1rem' }}>
                {/* Subject */}
                <div>
                  <label style={{ fontSize: '0.82rem', fontWeight: 600, color: 'var(--color-text-muted)', display: 'block', marginBottom: '0.3rem' }}>موضوع (اختیاری)</label>
                  <input
                    className="form-input"
                    value={subject}
                    onChange={e => setSubject(e.target.value)}
                    placeholder="موضوع گفتگو..."
                  />
                </div>
                {/* Classroom shortcut */}
                {classrooms.length > 0 && (
                  <div>
                    <label style={{ fontSize: '0.82rem', fontWeight: 600, color: 'var(--color-text-muted)', display: 'block', marginBottom: '0.3rem' }}>ارسال به کلاس</label>
                    <select className="form-input" defaultValue="" onChange={e => { addClassroom(e.target.value); e.currentTarget.value = ''; }}>
                      <option value="">انتخاب کلاس...</option>
                      {classrooms.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                    </select>
                  </div>
                )}
                {/* User search + chips */}
                <div>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.3rem' }}>
                    <label style={{ fontSize: '0.82rem', fontWeight: 600, color: 'var(--color-text-muted)' }}>
                      گیرندگان
                      {recipientIds.length > 0 && <span style={{ marginRight: '0.4rem', color: 'var(--color-primary)', fontWeight: 700 }}>{recipientIds.length} نفر</span>}
                    </label>
                    {recipientIds.length > 0 && (
                      <button type="button" style={{ background: 'none', border: 'none', color: 'var(--color-danger)', fontSize: '0.78rem', cursor: 'pointer' }} onClick={() => setRecipientIds([])}>
                        پاک کردن همه
                      </button>
                    )}
                  </div>
                  <input
                    className="form-input"
                    value={searchUser}
                    onChange={e => setSearchUser(e.target.value)}
                    placeholder="جستجو در کاربران..."
                    style={{ marginBottom: '0.5rem' }}
                  />
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.4rem', maxHeight: 160, overflowY: 'auto' }}>
                    {filteredUsers.map(u => {
                      const sel = recipientIds.includes(u.id);
                      return (
                        <label key={u.id} style={{
                          display: 'flex', alignItems: 'center', gap: '0.3rem',
                          background: sel ? 'var(--color-primary-soft)' : 'var(--color-bg-soft)',
                          border: `1px solid ${sel ? 'var(--color-primary)' : 'var(--color-border)'}`,
                          borderRadius: 'var(--radius-sm)', padding: '0.25rem 0.6rem',
                          cursor: 'pointer', fontSize: '0.82rem',
                        }}>
                          <input type="checkbox" checked={sel} onChange={() => toggleRecipient(u.id)} style={{ width: 14, height: 14 }} />
                          {u.name}
                          <span style={{ color: 'var(--color-text-muted)', fontSize: '0.7rem' }}>({u.role})</span>
                        </label>
                      );
                    })}
                  </div>
                </div>
                {/* Body */}
                <div style={{ flex: 1 }}>
                  <label style={{ fontSize: '0.82rem', fontWeight: 600, color: 'var(--color-text-muted)', display: 'block', marginBottom: '0.3rem' }}>متن پیام</label>
                  <textarea
                    className="form-input"
                    rows={6}
                    value={composeBody}
                    onChange={e => setComposeBody(e.target.value)}
                    placeholder="پیام خود را بنویسید..."
                    required
                    style={{ resize: 'vertical', minHeight: 120 }}
                  />
                </div>
              </div>
              <div style={{ padding: '0.85rem 1.2rem', borderTop: '1px solid var(--color-border)', display: 'flex', gap: '0.5rem' }}>
                <button className="btn btn-primary" type="submit" disabled={composeProcessing || recipientIds.length === 0 || !composeBody.trim()}>
                  <i className="bi bi-send-fill" /> {composeProcessing ? 'در حال ارسال...' : 'ارسال پیام'}
                </button>
                <button className="btn btn-ghost" type="button" onClick={() => setComposing(false)}>لغو</button>
              </div>
            </form>
          ) : activeThread ? (
            <>
              {/* Chat header */}
              <div style={{ padding: '0.85rem 1.2rem', borderBottom: '1px solid var(--color-border)', display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
                <i className="bi bi-chat-text" style={{ color: 'var(--color-primary)', fontSize: '1.1rem' }} />
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 700, fontSize: '0.97rem' }}>{activeThread.subject}</div>
                  <div style={{ fontSize: '0.75rem', color: 'var(--color-text-muted)', display: 'flex', alignItems: 'center', gap: '0.4rem' }}>
                    <span>{activeThread.messages.length} پیام</span>
                    <span
                      title={live ? 'پیام‌ها لحظه‌ای می‌رسند' : 'اتصال لحظه‌ای برقرار نیست؛ هر چند ثانیه بررسی می‌شود'}
                      style={{ display: 'inline-flex', alignItems: 'center', gap: '0.25rem' }}
                    >
                      <span style={{
                        width: 6, height: 6, borderRadius: '50%',
                        background: live ? 'var(--color-success)' : 'var(--color-text-soft)',
                        display: 'inline-block',
                      }} />
                      {live ? 'آنلاین' : 'بررسی دوره‌ای'}
                    </span>
                  </div>
                </div>
              </div>

              {/* Messages */}
              <div style={{ flex: 1, overflowY: 'auto', padding: '1rem 1.2rem', display: 'flex', flexDirection: 'column', gap: '0.65rem' }}>
                {activeThread.messages.map((msg, idx) => {
                  const prevMsg = idx > 0 ? activeThread.messages[idx - 1] : null;
                  const showSender = !prevMsg || prevMsg.isOwn !== msg.isOwn;
                  return (
                    <div
                      key={msg.id}
                      style={{ display: 'flex', justifyContent: msg.isOwn ? 'flex-end' : 'flex-start' }}
                    >
                      <div style={{ maxWidth: '72%', display: 'flex', flexDirection: 'column', gap: '0.2rem', alignItems: msg.isOwn ? 'flex-end' : 'flex-start' }}>
                        {showSender && !msg.isOwn && (
                          <span style={{ fontSize: '0.72rem', color: 'var(--color-text-muted)', marginBottom: '0.05rem', paddingRight: '0.5rem' }}>
                            {msg.sender}
                          </span>
                        )}
                        <div style={{
                          background: msg.isOwn ? 'var(--color-primary)' : 'var(--color-surface)',
                          color: msg.isOwn ? '#fff' : 'var(--color-text)',
                          border: msg.isOwn ? 'none' : '1px solid var(--color-border)',
                          borderRadius: msg.isOwn ? '18px 18px 4px 18px' : '18px 18px 18px 4px',
                          padding: '0.6rem 0.9rem',
                          fontSize: '0.875rem',
                          lineHeight: 1.65,
                          whiteSpace: 'pre-wrap',
                          wordBreak: 'break-word',
                          boxShadow: '0 1px 3px rgba(0,0,0,0.07)',
                        }}>
                          {msg.body}
                        </div>
                        <span style={{ fontSize: '0.68rem', color: 'var(--color-text-muted)', paddingRight: msg.isOwn ? 0 : '0.5rem', paddingLeft: msg.isOwn ? '0.5rem' : 0 }}>
                          {msg.createdAt}
                        </span>
                      </div>
                    </div>
                  );
                })}
                <div ref={chatEndRef} />
              </div>

              {/* Reply box */}
              <div style={{ padding: '0.75rem 1.2rem', borderTop: '1px solid var(--color-border)', display: 'flex', gap: '0.6rem', alignItems: 'flex-end' }}>
                <textarea
                  ref={replyRef}
                  value={replyBody}
                  onChange={e => setReplyBody(e.target.value)}
                  onKeyDown={handleReplyKey}
                  placeholder="پاسخ بنویسید... (Ctrl+Enter برای ارسال)"
                  rows={2}
                  style={{
                    flex: 1, resize: 'none', border: '1px solid var(--color-border)',
                    borderRadius: 12, padding: '0.55rem 0.8rem', fontFamily: 'inherit',
                    fontSize: '0.875rem', background: 'var(--color-bg-soft)',
                    color: 'var(--color-text)', outline: 'none', lineHeight: 1.55,
                    transition: 'border-color 0.15s',
                  }}
                  onFocus={e => (e.target.style.borderColor = 'var(--color-primary)')}
                  onBlur={e => (e.target.style.borderColor = 'var(--color-border)')}
                />
                <button
                  className="btn btn-primary"
                  onClick={sendReply}
                  disabled={!replyBody.trim() || sending}
                  style={{ borderRadius: 10, height: 44, minWidth: 44, padding: '0 0.85rem' }}
                  title="ارسال (Ctrl+Enter)"
                >
                  {sending
                    ? <i className="bi bi-hourglass-split" />
                    : <i className="bi bi-send-fill" />
                  }
                </button>
              </div>
            </>
          ) : (
            // Empty state
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', color: 'var(--color-text-muted)', gap: '0.75rem' }}>
              <i className="bi bi-chat-dots" style={{ fontSize: '3.5rem', opacity: 0.25 }} />
              <span style={{ fontSize: '0.9rem' }}>یک گفتگو انتخاب کنید یا گفتگوی جدید شروع کنید</span>
              <button className="btn btn-primary btn-sm" onClick={() => setComposing(true)}>
                <i className="bi bi-pencil-square" /> گفتگوی جدید
              </button>
            </div>
          )}
        </div>
      </div>
    </AppLayout>
  );
}
