/**
 * Self-contained scheduling poll widget for GrapesJS landing pages.
 * Rendered via createRoot() outside the App's ConfigProvider — uses inline styles only, no Ant Design.
 * Follows the same pattern as CampaignFormWidget, DonationWidget, etc.
 */
import { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
import { getErrorMessage } from '../../utils/getErrorMessage';

const apiBase = '/api';

// Theme colors matching the dark public pages
const COLORS = {
  bg: '#0d1b2a',
  card: '#1b2838',
  cardAlt: '#243447',
  primary: '#fa8c16',
  primaryHover: '#d46b08',
  text: '#fff',
  textMuted: 'rgba(255,255,255,0.65)',
  border: 'rgba(255,255,255,0.15)',
  success: '#52c41a',
  error: '#ff4d4f',
  yes: '#52c41a',
  ifNeedBe: '#faad14',
  no: '#d9d9d9',
};

const STATUS_COLORS: Record<string, string> = {
  OPEN: '#52c41a',
  CLOSED: '#fa8c16',
  FINALIZED: '#1890ff',
  CANCELLED: '#ff4d4f',
};

const STATUS_LABELS: Record<string, string> = {
  OPEN: 'Open',
  CLOSED: 'Closed',
  FINALIZED: 'Finalized',
  CANCELLED: 'Cancelled',
};

const VOTE_LABELS: Record<string, string> = {
  YES: 'Yes',
  IF_NEED_BE: 'If Need Be',
  NO: 'No',
};

const VOTE_COLORS: Record<string, string> = {
  YES: COLORS.yes,
  IF_NEED_BE: COLORS.ifNeedBe,
  NO: COLORS.no,
};

interface PollOption {
  id: string;
  date: string;
  startTime: string;
  endTime: string;
  yesCount?: number;
  ifNeedBeCount?: number;
  noCount?: number;
  score?: number;
}

interface PollVoter {
  name: string;
  votes: Record<string, string>;
}

interface PollComment {
  id: string;
  authorName: string;
  content: string;
  createdAt: string;
}

interface PollData {
  id: string;
  slug: string;
  title: string;
  description: string | null;
  location: string | null;
  status: string;
  timezone: string;
  votingDeadline: string | null;
  finalizedOptionId: string | null;
  finalizedOption: PollOption | null;
  allowAnonymous: boolean;
  isPrivate?: boolean;
  requiresAuth?: boolean;
  createdBy?: { name: string | null; email: string };
  options: PollOption[];
  voters: PollVoter[];
  comments: PollComment[];
}

interface SchedulingPollWidgetProps {
  pollSlug: string;
  showComments?: boolean;
  title?: string;
}

const inputStyle: React.CSSProperties = {
  width: '100%',
  padding: '10px 14px',
  border: `1px solid ${COLORS.border}`,
  borderRadius: 6,
  background: 'rgba(255,255,255,0.05)',
  color: COLORS.text,
  fontSize: 14,
  outline: 'none',
  boxSizing: 'border-box',
};

const btnStyle: React.CSSProperties = {
  padding: '10px 24px',
  background: COLORS.primary,
  color: '#fff',
  border: 'none',
  borderRadius: 6,
  fontWeight: 600,
  fontSize: 14,
  cursor: 'pointer',
  width: '100%',
};

function formatDate(dateStr: string): string {
  const d = new Date(dateStr + 'T00:00:00');
  return d.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric' });
}

function formatDateTime(dateStr: string): string {
  const d = new Date(dateStr);
  return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: '2-digit' });
}

const VOTER_TOKEN_KEY = 'poll_voter_token_';

export function SchedulingPollWidget({ pollSlug, showComments = true, title }: SchedulingPollWidgetProps) {
  const [poll, setPoll] = useState<PollData | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Vote form
  const [voterName, setVoterName] = useState('');
  const [voterEmail, setVoterEmail] = useState('');
  const [votes, setVotes] = useState<Record<string, string>>({});
  const [submitting, setSubmitting] = useState(false);
  const [hasVoted, setHasVoted] = useState(false);
  const [submitMsg, setSubmitMsg] = useState<{ type: 'success' | 'error'; text: string } | null>(null);

  // Comment form
  const [commentName, setCommentName] = useState('');
  const [commentContent, setCommentContent] = useState('');
  const [commentSubmitting, setCommentSubmitting] = useState(false);

  const fetchPoll = useCallback(async () => {
    try {
      const { data } = await axios.get<PollData>(`${apiBase}/meeting-planner/public/${pollSlug}`);
      setPoll(data);

      // Check for stored voter token
      const storedToken = localStorage.getItem(VOTER_TOKEN_KEY + pollSlug);
      if (storedToken) {
        setHasVoted(true);
      }
    } catch {
      setError('Poll not found or unavailable');
    } finally {
      setLoading(false);
    }
  }, [pollSlug]);

  useEffect(() => { fetchPoll(); }, [fetchPoll]);

  const handleVoteChange = (optionId: string, value: string) => {
    setVotes((prev) => ({ ...prev, [optionId]: value }));
  };

  const handleSubmitVotes = async () => {
    if (!poll || !voterName.trim()) {
      setSubmitMsg({ type: 'error', text: 'Please enter your name' });
      return;
    }
    if (!Object.keys(votes).length) {
      setSubmitMsg({ type: 'error', text: 'Please vote on at least one option' });
      return;
    }
    const trimmedEmail = voterEmail.trim();
    if (trimmedEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedEmail)) {
      setSubmitMsg({ type: 'error', text: 'Please enter a valid email address, or leave the email field blank' });
      return;
    }

    setSubmitting(true);
    setSubmitMsg(null);
    try {
      const storedToken = localStorage.getItem(VOTER_TOKEN_KEY + pollSlug);
      const { data } = await axios.post(`${apiBase}/meeting-planner/public/${pollSlug}/vote`, {
        voterName: voterName.trim(),
        voterEmail: trimmedEmail || undefined,
        voterToken: storedToken || undefined,
        votes: Object.entries(votes).map(([optionId, value]) => ({ optionId, value })),
      });

      if (data.voterToken) {
        localStorage.setItem(VOTER_TOKEN_KEY + pollSlug, data.voterToken);
      }

      setSubmitMsg({ type: 'success', text: hasVoted ? 'Votes updated!' : 'Votes submitted!' });
      setHasVoted(true);
      fetchPoll();
    } catch (err: unknown) {
      setSubmitMsg({ type: 'error', text: getErrorMessage(err, 'Failed to submit votes') });
    } finally {
      setSubmitting(false);
    }
  };

  const handleSubmitComment = async () => {
    if (!commentName.trim() || !commentContent.trim()) return;
    setCommentSubmitting(true);
    try {
      await axios.post(`${apiBase}/meeting-planner/public/${pollSlug}/comment`, {
        authorName: commentName.trim(),
        content: commentContent.trim(),
      });
      setCommentContent('');
      fetchPoll();
    } catch {
      // Silent fail
    } finally {
      setCommentSubmitting(false);
    }
  };

  if (loading) {
    return (
      <div style={{ textAlign: 'center', padding: 40, color: COLORS.textMuted }}>
        Loading poll...
      </div>
    );
  }

  if (error || !poll) {
    return (
      <div style={{ textAlign: 'center', padding: 40, color: COLORS.textMuted }}>
        {error || 'Poll not found'}
      </div>
    );
  }

  if (poll.requiresAuth) {
    return (
      <div style={{ maxWidth: 700, margin: '0 auto', fontFamily: "'Inter', -apple-system, sans-serif", color: COLORS.text }}>
        {title && (
          <h2 style={{ textAlign: 'center', marginBottom: 8, fontSize: '1.5rem', fontWeight: 700 }}>
            {title}
          </h2>
        )}
        <div style={{
          background: COLORS.card,
          borderRadius: 8,
          border: `1px solid ${COLORS.border}`,
          padding: 32,
          textAlign: 'center',
        }}>
          <div style={{ fontSize: 40, marginBottom: 12 }}>🔒</div>
          <h3 style={{ margin: '0 0 8px', fontSize: '1.25rem' }}>{poll.title}</h3>
          <p style={{ color: COLORS.textMuted, margin: '0 0 20px', lineHeight: 1.5 }}>
            This poll is private. Please sign in to view the details and participate.
          </p>
          <a
            href={`/login?redirect=/poll/${pollSlug}`}
            style={{
              ...btnStyle,
              display: 'inline-block',
              width: 'auto',
              padding: '10px 32px',
              textDecoration: 'none',
            }}
          >
            Sign In to View
          </a>
        </div>
      </div>
    );
  }

  const isOpen = poll.status === 'OPEN';
  const isFinalized = poll.status === 'FINALIZED';
  const bestScore = poll.options.length ? Math.max(...poll.options.map((o) => o.score ?? 0)) : 0;

  return (
    <div style={{ maxWidth: 700, margin: '0 auto', fontFamily: "'Inter', -apple-system, sans-serif", color: COLORS.text }}>
      {/* Title */}
      {title && (
        <h2 style={{ textAlign: 'center', marginBottom: 8, fontSize: '1.5rem', fontWeight: 700 }}>
          {title}
        </h2>
      )}

      {/* Poll header */}
      <div style={{ marginBottom: 16 }}>
        <h3 style={{ margin: '0 0 8px', fontSize: '1.25rem' }}>
          {poll.title}
        </h3>
        {poll.description && (
          <p style={{ color: COLORS.textMuted, margin: '0 0 8px', lineHeight: 1.5 }}>
            {poll.description}
          </p>
        )}
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>
          <span style={{
            display: 'inline-block',
            padding: '2px 10px',
            borderRadius: 4,
            fontSize: 12,
            fontWeight: 600,
            background: `${STATUS_COLORS[poll.status] || '#666'}22`,
            color: STATUS_COLORS[poll.status] || '#666',
            border: `1px solid ${STATUS_COLORS[poll.status] || '#666'}44`,
          }}>
            {STATUS_LABELS[poll.status] || poll.status}
          </span>
          {poll.location && (
            <span style={{ fontSize: 13, color: COLORS.textMuted }}>
              {poll.location}
            </span>
          )}
          <span style={{ fontSize: 13, color: COLORS.textMuted }}>
            {poll.timezone}
          </span>
        </div>
      </div>

      {/* Deadline */}
      {poll.votingDeadline && isOpen && (
        <div style={{
          padding: '8px 14px',
          borderRadius: 6,
          background: 'rgba(250,140,22,0.1)',
          border: '1px solid rgba(250,140,22,0.3)',
          marginBottom: 16,
          fontSize: 13,
          color: COLORS.primary,
        }}>
          Voting deadline: {formatDateTime(poll.votingDeadline)}
        </div>
      )}

      {/* Finalized banner */}
      {isFinalized && poll.finalizedOption && (
        <div style={{
          padding: '12px 16px',
          borderRadius: 6,
          background: 'rgba(82,196,26,0.1)',
          border: '1px solid rgba(82,196,26,0.3)',
          marginBottom: 16,
          color: COLORS.success,
        }}>
          <strong>Date Confirmed:</strong>{' '}
          {formatDate(poll.finalizedOption.date)} — {poll.finalizedOption.startTime}–{poll.finalizedOption.endTime}
        </div>
      )}

      {/* Options table */}
      <div style={{
        background: COLORS.card,
        borderRadius: 8,
        border: `1px solid ${COLORS.border}`,
        overflow: 'hidden',
        marginBottom: 16,
      }}>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr>
                <th style={{ padding: '10px 14px', borderBottom: `2px solid ${COLORS.border}`, textAlign: 'left', minWidth: 130 }}>
                  Participant
                </th>
                {poll.options.map((opt) => (
                  <th
                    key={opt.id}
                    style={{
                      padding: '10px 14px',
                      borderBottom: `2px solid ${COLORS.border}`,
                      textAlign: 'center',
                      minWidth: 100,
                      background: isFinalized && poll.finalizedOptionId === opt.id
                        ? 'rgba(82,196,26,0.12)'
                        : opt.score === bestScore && bestScore > 0
                          ? 'rgba(82,196,26,0.06)'
                          : undefined,
                    }}
                  >
                    <div style={{ fontWeight: 600 }}>{formatDate(opt.date)}</div>
                    <div style={{ fontSize: 11, opacity: 0.7 }}>{opt.startTime}–{opt.endTime}</div>
                    {isFinalized && poll.finalizedOptionId === opt.id && (
                      <span style={{
                        display: 'inline-block',
                        marginTop: 4,
                        padding: '1px 6px',
                        borderRadius: 3,
                        fontSize: 10,
                        fontWeight: 600,
                        background: 'rgba(82,196,26,0.2)',
                        color: COLORS.success,
                      }}>
                        Confirmed
                      </span>
                    )}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {poll.voters.map((voter, i) => (
                <tr key={i}>
                  <td style={{ padding: '8px 14px', borderBottom: `1px solid ${COLORS.border}` }}>
                    {voter.name}
                  </td>
                  {poll.options.map((opt) => {
                    const value = voter.votes[opt.id];
                    return (
                      <td
                        key={opt.id}
                        style={{
                          padding: '8px 14px',
                          borderBottom: `1px solid ${COLORS.border}`,
                          textAlign: 'center',
                          background: value ? `${VOTE_COLORS[value] || '#666'}18` : undefined,
                        }}
                      >
                        {value && (
                          <span style={{
                            display: 'inline-block',
                            padding: '2px 8px',
                            borderRadius: 3,
                            fontSize: 11,
                            fontWeight: 600,
                            background: `${VOTE_COLORS[value] || '#666'}22`,
                            color: VOTE_COLORS[value] || '#666',
                          }}>
                            {VOTE_LABELS[value] || value}
                          </span>
                        )}
                      </td>
                    );
                  })}
                </tr>
              ))}
              {/* Score row */}
              <tr style={{ fontWeight: 600 }}>
                <td style={{ padding: '10px 14px', borderTop: `2px solid ${COLORS.border}` }}>Score</td>
                {poll.options.map((opt) => (
                  <td
                    key={opt.id}
                    style={{
                      padding: '10px 14px',
                      borderTop: `2px solid ${COLORS.border}`,
                      textAlign: 'center',
                      background: opt.score === bestScore && bestScore > 0 ? 'rgba(82,196,26,0.1)' : undefined,
                    }}
                  >
                    <div style={{ fontSize: 16 }}>{opt.score ?? 0}</div>
                    <div style={{ fontSize: 11, opacity: 0.7 }}>
                      {opt.yesCount ?? 0}Y / {opt.ifNeedBeCount ?? 0}M / {opt.noCount ?? 0}N
                    </div>
                  </td>
                ))}
              </tr>
            </tbody>
          </table>
        </div>
      </div>

      {/* Vote form */}
      {isOpen && (
        <div style={{
          background: COLORS.card,
          borderRadius: 8,
          border: `1px solid ${COLORS.border}`,
          padding: 20,
          marginBottom: 16,
        }}>
          <h4 style={{ margin: '0 0 14px', fontSize: 15 }}>
            {hasVoted ? 'Update Your Votes' : 'Cast Your Votes'}
          </h4>

          <div style={{ display: 'flex', gap: 12, marginBottom: 14, flexWrap: 'wrap' }}>
            <input
              type="text"
              placeholder="Your name"
              value={voterName}
              onChange={(e) => setVoterName(e.target.value)}
              style={{ ...inputStyle, flex: '1 1 200px' }}
            />
            <input
              type="email"
              placeholder="Email (optional)"
              value={voterEmail}
              onChange={(e) => setVoterEmail(e.target.value)}
              style={{ ...inputStyle, flex: '1 1 200px' }}
            />
          </div>

          {poll.options.map((opt) => (
            <div key={opt.id} style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 8, flexWrap: 'wrap' }}>
              <span style={{ minWidth: 150, fontSize: 13 }}>
                {formatDate(opt.date)} {opt.startTime}–{opt.endTime}
              </span>
              <div style={{ display: 'flex', gap: 4 }}>
                {(['YES', 'IF_NEED_BE', 'NO'] as const).map((val) => (
                  <button
                    key={val}
                    type="button"
                    onClick={() => handleVoteChange(opt.id, val)}
                    style={{
                      padding: '4px 12px',
                      border: `1px solid ${VOTE_COLORS[val]}66`,
                      borderRadius: 4,
                      fontSize: 12,
                      fontWeight: 600,
                      cursor: 'pointer',
                      background: votes[opt.id] === val ? `${VOTE_COLORS[val]}33` : 'transparent',
                      color: votes[opt.id] === val ? VOTE_COLORS[val] : COLORS.textMuted,
                    }}
                  >
                    {VOTE_LABELS[val]}
                  </button>
                ))}
              </div>
            </div>
          ))}

          {submitMsg && (
            <div style={{
              padding: '8px 14px',
              borderRadius: 6,
              marginTop: 12,
              fontSize: 13,
              background: submitMsg.type === 'success' ? 'rgba(82,196,26,0.1)' : 'rgba(255,77,79,0.1)',
              color: submitMsg.type === 'success' ? COLORS.success : COLORS.error,
              border: `1px solid ${submitMsg.type === 'success' ? 'rgba(82,196,26,0.3)' : 'rgba(255,77,79,0.3)'}`,
            }}>
              {submitMsg.text}
            </div>
          )}

          <button
            type="button"
            onClick={handleSubmitVotes}
            disabled={submitting}
            style={{
              ...btnStyle,
              marginTop: 14,
              opacity: submitting ? 0.6 : 1,
            }}
          >
            {submitting ? 'Submitting...' : hasVoted ? 'Update Votes' : 'Submit Votes'}
          </button>
        </div>
      )}

      {/* Comments */}
      {showComments && (
        <div style={{
          background: COLORS.card,
          borderRadius: 8,
          border: `1px solid ${COLORS.border}`,
          padding: 20,
        }}>
          <h4 style={{ margin: '0 0 14px', fontSize: 15 }}>
            Comments ({poll.comments.length})
          </h4>

          {poll.comments.map((comment) => (
            <div key={comment.id} style={{ marginBottom: 12, paddingBottom: 12, borderBottom: `1px solid ${COLORS.border}` }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                <strong style={{ fontSize: 13 }}>{comment.authorName}</strong>
                <span style={{ fontSize: 11, color: COLORS.textMuted }}>
                  {formatDateTime(comment.createdAt)}
                </span>
              </div>
              <p style={{ margin: 0, fontSize: 13, color: COLORS.textMuted, lineHeight: 1.5 }}>
                {comment.content}
              </p>
            </div>
          ))}

          {poll.status !== 'CANCELLED' && (
            <div style={{ marginTop: 12 }}>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                <input
                  type="text"
                  placeholder="Your name"
                  value={commentName}
                  onChange={(e) => setCommentName(e.target.value)}
                  style={{ ...inputStyle, flex: '0 0 140px' }}
                />
                <input
                  type="text"
                  placeholder="Add a comment..."
                  value={commentContent}
                  onChange={(e) => setCommentContent(e.target.value)}
                  style={{ ...inputStyle, flex: '1 1 200px' }}
                  onKeyDown={(e) => { if (e.key === 'Enter') handleSubmitComment(); }}
                />
                <button
                  type="button"
                  onClick={handleSubmitComment}
                  disabled={commentSubmitting}
                  style={{
                    ...btnStyle,
                    width: 'auto',
                    flex: '0 0 auto',
                    opacity: commentSubmitting ? 0.6 : 1,
                  }}
                >
                  Post
                </button>
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
