/**
 * CreatePollModal — compose a new MSC3381 poll.
 *
 * Lives next to ChannelTextarea; the composer's poll button opens
 * it for the active channel. Keeps its own local form state and
 * hands the final payload off to `MessageActionCreators.sendPollStart`
 * on submit. Closes itself on success, surfaces errors inline.
 */
import { useEffect, useMemo, useState } from 'react';
import { useMutation } from 'convex/react';
import { Plus, X } from '@phosphor-icons/react';
import { Button, Modal } from '@discord-clone/ui';
import { api } from '../../../../../convex/_generated/api';
import type { Id } from '../../../../../convex/_generated/dataModel';
import styles from './CreatePollModal.module.css';

interface PollAnswer {
	id: string;
	text: string;
}

interface CreatePollModalProps {
	isOpen: boolean;
	onClose: () => void;
	channelId: string;
}

const MIN_ANSWERS = 2;
const MAX_ANSWERS = 20;
const MAX_QUESTION_LEN = 340;
const MAX_ANSWER_LEN = 340;

/** Short random string for answer ids. Matches Element's format. */
function makeAnswerId(): string {
	const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	let out = '';
	for (let i = 0; i < 16; i++) {
		out += chars[Math.floor(Math.random() * chars.length)];
	}
	return out;
}

export function CreatePollModal({ isOpen, onClose, channelId }: CreatePollModalProps) {
	const createPoll = useMutation(api.polls.create);
	const [question, setQuestion] = useState('');
	// Each draft answer carries a stable id even before submit so
	// React doesn't reshuffle focus between rows when the list
	// mutates. The ids flow straight into the outgoing poll.start.
	const [answers, setAnswers] = useState<PollAnswer[]>(() => [
		{ id: makeAnswerId(), text: '' },
		{ id: makeAnswerId(), text: '' },
	]);
	const [allowMultiple, setAllowMultiple] = useState(false);
	const [disclosed, setDisclosed] = useState(true);
	const [submitting, setSubmitting] = useState(false);
	const [error, setError] = useState<string | null>(null);

	// Reset the form when the modal opens so previous attempts don't
	// linger. Running on `isOpen === true` only avoids wiping the
	// form while the user's submit is in flight.
	useEffect(() => {
		if (!isOpen) return;
		setQuestion('');
		setAnswers([
			{ id: makeAnswerId(), text: '' },
			{ id: makeAnswerId(), text: '' },
		]);
		setAllowMultiple(false);
		setDisclosed(true);
		setSubmitting(false);
		setError(null);
	}, [isOpen]);

	const trimmedQuestion = question.trim();
	const validAnswers = useMemo(
		() => answers.map((a) => ({ ...a, text: a.text.trim() })).filter((a) => a.text.length > 0),
		[answers],
	);
	const canSubmit =
		trimmedQuestion.length > 0 &&
		validAnswers.length >= MIN_ANSWERS &&
		!submitting;

	const setAnswerText = (id: string, text: string) => {
		setAnswers((prev) =>
			prev.map((a) => (a.id === id ? { ...a, text: text.slice(0, MAX_ANSWER_LEN) } : a)),
		);
	};

	const addAnswer = () => {
		setAnswers((prev) =>
			prev.length >= MAX_ANSWERS ? prev : [...prev, { id: makeAnswerId(), text: '' }],
		);
	};

	const removeAnswer = (id: string) => {
		setAnswers((prev) =>
			prev.length <= MIN_ANSWERS ? prev : prev.filter((a) => a.id !== id),
		);
	};

	const handleSubmit = async () => {
		if (!canSubmit) return;
		const myUserId =
			typeof localStorage !== 'undefined' ? localStorage.getItem('userId') : null;
		if (!myUserId) {
			setError('You must be signed in to create a poll.');
			return;
		}
		setSubmitting(true);
		setError(null);
		try {
			await createPoll({
				channelId: channelId as Id<'channels'>,
				createdBy: myUserId as Id<'userProfiles'>,
				question: trimmedQuestion,
				options: validAnswers.map((a) => ({ id: a.id, text: a.text })),
				allowMultiple,
				disclosed,
			});
			onClose();
		} catch (err: any) {
			setError(err?.message || 'Failed to create poll.');
		} finally {
			setSubmitting(false);
		}
	};

	return (
		<Modal.Root isOpen={isOpen} onClose={onClose} size="small">
			<Modal.Header title="Create Poll" onClose={onClose} />
			<Modal.Content>
				<div className={styles.body}>
					<div className={styles.field}>
						<label className={styles.label} htmlFor="poll-question">
							Question
						</label>
						<input
							id="poll-question"
							className={styles.input}
							value={question}
							placeholder="What should we have for lunch?"
							maxLength={MAX_QUESTION_LEN}
							onChange={(e) => setQuestion(e.target.value)}
							disabled={submitting}
						/>
					</div>

					<div className={styles.field}>
						<div className={styles.label}>Answers</div>
						<div className={styles.answerList}>
							{answers.map((answer, i) => (
								<div key={answer.id} className={styles.answerRow}>
									<input
										className={styles.input}
										value={answer.text}
										placeholder={`Answer ${i + 1}`}
										onChange={(e) => setAnswerText(answer.id, e.target.value)}
										disabled={submitting}
									/>
									<button
										type="button"
										className={styles.removeButton}
										onClick={() => removeAnswer(answer.id)}
										disabled={submitting || answers.length <= MIN_ANSWERS}
										aria-label={`Remove answer ${i + 1}`}
									>
										<X size={14} weight="bold" />
									</button>
								</div>
							))}
						</div>
						<button
							type="button"
							className={styles.addButton}
							onClick={addAnswer}
							disabled={submitting || answers.length >= MAX_ANSWERS}
						>
							<Plus size={14} weight="bold" style={{ marginRight: 4, verticalAlign: 'middle' }} />
							Add answer
						</button>
					</div>

					<div className={styles.toggles}>
						<label className={styles.toggleRow}>
							<span className={styles.toggleLabel}>
								<span className={styles.toggleName}>Allow multiple answers</span>
								<span className={styles.toggleHint}>
									Voters can select more than one option.
								</span>
							</span>
							<input
								type="checkbox"
								className={styles.toggleInput}
								checked={allowMultiple}
								onChange={(e) => setAllowMultiple(e.target.checked)}
								disabled={submitting}
							/>
						</label>
						<label className={styles.toggleRow}>
							<span className={styles.toggleLabel}>
								<span className={styles.toggleName}>Show results in real time</span>
								<span className={styles.toggleHint}>
									If off, vote counts stay hidden until you end the poll.
								</span>
							</span>
							<input
								type="checkbox"
								className={styles.toggleInput}
								checked={disclosed}
								onChange={(e) => setDisclosed(e.target.checked)}
								disabled={submitting}
							/>
						</label>
					</div>

					{error && <div className={styles.error}>{error}</div>}

					<div className={styles.actions}>
						<Button variant="secondary" size="sm" onClick={onClose} disabled={submitting}>
							Cancel
						</Button>
						<Button
							variant="primary"
							size="sm"
							onClick={handleSubmit}
							disabled={!canSubmit}
							loading={submitting}
						>
							Create
						</Button>
					</div>
				</div>
			</Modal.Content>
		</Modal.Root>
	);
}
