import {__, sprintf} from '@wordpress/i18n';
import {useEffect, useMemo, useRef, useState} from '@wordpress/element';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import Alert from 'react-bootstrap/Alert';
import Table from 'react-bootstrap/Table';
import Spinner from 'react-bootstrap/Spinner';

/**
 * Captions tab — upload, list, and delete caption tracks on a video.
 *
 * Uploads a WebVTT or SRT file for a single BCP-47 language code. The video
 * service treats each `srclang` as the primary key, so uploading the same
 * language twice replaces the previous track. Deletes remove a track by
 * that same code.
 *
 * The `video.captions` array carries { srclang, label } for each existing
 * caption; this component patches that array in place after each mutation
 * so the parent modal reflects the change immediately.
 */
export default function VideoCaptions({video, setVideos}) {
	const [captions, setCaptions] = useState(video.captions || []);
	const [srclang, setSrclang] = useState('en');
	const [label, setLabel] = useState('English');
	const [file, setFile] = useState(null);
	const [uploading, setUploading] = useState(false);
	const [deletingLang, setDeletingLang] = useState(null);
	const [message, setMessage] = useState(null);
	const fileRef = useRef(null);

	// Keep the local list in sync when the parent's video prop changes.
	useEffect(() => {
		setCaptions(video.captions || []);
	}, [video.guid, video.captions && video.captions.length]);

	const languages = useMemo(
		() => [
			{code: 'en', label: 'English'},
			{code: 'es', label: 'Spanish'},
			{code: 'fr', label: 'French'},
			{code: 'de', label: 'German'},
			{code: 'it', label: 'Italian'},
			{code: 'pt', label: 'Portuguese'},
			{code: 'nl', label: 'Dutch'},
			{code: 'sv', label: 'Swedish'},
			{code: 'pl', label: 'Polish'},
			{code: 'ru', label: 'Russian'},
			{code: 'ja', label: 'Japanese'},
			{code: 'ko', label: 'Korean'},
			{code: 'zh', label: 'Chinese'},
			{code: 'ar', label: 'Arabic'},
			{code: 'hi', label: 'Hindi'},
			{code: 'tr', label: 'Turkish'},
			{code: 'id', label: 'Indonesian'},
			{code: 'vi', label: 'Vietnamese'},
			{code: 'th', label: 'Thai'},
		],
		[]
	);

	const labelByCode = useMemo(() => {
		const m = {};
		languages.forEach((l) => (m[l.code] = l.label));
		return m;
	}, [languages]);

	function onLangChange(e) {
		const code = e.target.value;
		setSrclang(code);
		// Auto-fill label unless the user typed a custom one.
		if (Object.values(labelByCode).includes(label) || label === '') {
			setLabel(labelByCode[code] || code);
		}
	}

	function onFileChange(e) {
		const f = e.target.files && e.target.files[0];
		if (!f) {
			setFile(null);
			return;
		}
		const ext = (f.name.split('.').pop() || '').toLowerCase();
		if (ext !== 'vtt' && ext !== 'srt') {
			setMessage({
				variant: 'warning',
				text: __(
					'Only .vtt and .srt caption files are accepted.',
					'infinite-uploads'
				),
			});
			e.target.value = '';
			setFile(null);
			return;
		}
		if (f.size > 512 * 1024) {
			setMessage({
				variant: 'warning',
				text: __(
					'Caption file is too large. Maximum size is 512 KB.',
					'infinite-uploads'
				),
			});
			e.target.value = '';
			setFile(null);
			return;
		}
		setMessage(null);
		setFile(f);
	}

	function updateVideoCaptions(next) {
		setCaptions(next);
		if (typeof setVideos === 'function') {
			setVideos((videos) =>
				videos.map((v) =>
					v.guid === video.guid ? {...v, captions: next} : v
				)
			);
		}
	}

	function onUpload(e) {
		e.preventDefault();
		if (!file) {
			setMessage({
				variant: 'warning',
				text: __('Choose a caption file first.', 'infinite-uploads'),
			});
			return;
		}
		setUploading(true);
		setMessage(null);

		const fd = new FormData();
		fd.append('action', 'infinite-uploads-video-caption-add');
		fd.append('nonce', IUP_VIDEO.nonce);
		fd.append('video_id', video.guid);
		fd.append('srclang', srclang.trim().toLowerCase());
		fd.append('label', label.trim() || labelByCode[srclang] || srclang);
		fd.append('captionsFile', file);

		fetch(ajaxurl, {
			method: 'POST',
			headers: {Accept: 'application/json'},
			body: fd,
		})
			.then((r) => r.json())
			.then((data) => {
				if (data && data.success) {
					const lang = data.data.srclang;
					const next = [
						...captions.filter((c) => c.srclang !== lang),
						{srclang: lang, label: data.data.label},
					];
					updateVideoCaptions(next);
					setFile(null);
					if (fileRef.current) fileRef.current.value = '';
					setMessage({
						variant: 'success',
						text: sprintf(
							/* translators: %s: language label of the caption just added */
							__('%s caption added.', 'infinite-uploads'),
							data.data.label || lang
						),
					});
				} else {
					setMessage({
						variant: 'danger',
						text:
							(data &&
								data.data &&
								(typeof data.data === 'string'
									? data.data
									: data.data.message)) ||
							__(
								'Could not add the caption.',
								'infinite-uploads'
							),
					});
				}
			})
			.catch(() => {
				setMessage({
					variant: 'danger',
					text: __('Could not add the caption.', 'infinite-uploads'),
				});
			})
			.finally(() => setUploading(false));
	}

	function onDelete(lang) {
		if (!lang) return;
		setDeletingLang(lang);
		setMessage(null);
		const fd = new FormData();
		fd.append('action', 'infinite-uploads-video-caption-delete');
		fd.append('nonce', IUP_VIDEO.nonce);
		fd.append('video_id', video.guid);
		fd.append('srclang', lang);

		fetch(ajaxurl, {
			method: 'POST',
			headers: {Accept: 'application/json'},
			body: fd,
		})
			.then((r) => r.json())
			.then((data) => {
				if (data && data.success) {
					updateVideoCaptions(
						captions.filter((c) => c.srclang !== lang)
					);
				} else {
					setMessage({
						variant: 'danger',
						text:
							(data &&
								data.data &&
								(typeof data.data === 'string'
									? data.data
									: data.data.message)) ||
							__(
								'Could not remove the caption.',
								'infinite-uploads'
							),
					});
				}
			})
			.catch(() => {
				setMessage({
					variant: 'danger',
					text: __(
						'Could not remove the caption.',
						'infinite-uploads'
					),
				});
			})
			.finally(() => setDeletingLang(null));
	}

	return (
		<div className="iup-video-captions">
			{message && (
				<Alert
					variant={message.variant}
					className="mb-3"
					onClose={() => setMessage(null)}
					dismissible
				>
					{message.text}
				</Alert>
			)}

			<Row className="mb-4">
				<Col>
					<h6 className="mb-2">
						{__('Existing captions', 'infinite-uploads')}
					</h6>
					{captions.length ? (
						<Table size="sm" striped className="mb-0">
							<thead>
								<tr>
									<th style={{width: '25%'}}>
										{__(
											'Language',
											'infinite-uploads'
										)}
									</th>
									<th>{__('Label', 'infinite-uploads')}</th>
									<th
										style={{width: '90px'}}
										className="text-end"
									>
										{__('', 'infinite-uploads')}
									</th>
								</tr>
							</thead>
							<tbody>
								{captions.map((c) => (
									<tr key={c.srclang}>
										<td>
											<code className="me-1">
												{c.srclang}
											</code>
											{labelByCode[c.srclang] && (
												<span className="text-muted small">
													{labelByCode[c.srclang]}
												</span>
											)}
										</td>
										<td>{c.label || '—'}</td>
										<td className="text-end">
											<Button
												variant="outline-danger"
												size="sm"
												disabled={
													deletingLang === c.srclang
												}
												onClick={() => onDelete(c.srclang)}
											>
												{deletingLang === c.srclang ? (
													<Spinner
														animation="border"
														size="sm"
													/>
												) : (
													__(
														'Remove',
														'infinite-uploads'
													)
												)}
											</Button>
										</td>
									</tr>
								))}
							</tbody>
						</Table>
					) : (
						<p className="text-muted small mb-0">
							{__(
								'No captions on this video yet.',
								'infinite-uploads'
							)}
						</p>
					)}
				</Col>
			</Row>

			<Row>
				<Col>
					<h6 className="mb-2">
						{__('Add a caption', 'infinite-uploads')}
					</h6>
					<Form onSubmit={onUpload}>
						<Row className="mb-3">
							<Col md={4}>
								<Form.Label className="small text-muted">
									{__('Language', 'infinite-uploads')}
								</Form.Label>
								<Form.Select
									value={srclang}
									onChange={onLangChange}
									disabled={uploading}
								>
									{languages.map((l) => (
										<option key={l.code} value={l.code}>
											{l.label} ({l.code})
										</option>
									))}
								</Form.Select>
							</Col>
							<Col md={4}>
								<Form.Label className="small text-muted">
									{__('Label', 'infinite-uploads')}
								</Form.Label>
								<Form.Control
									type="text"
									value={label}
									onChange={(e) => setLabel(e.target.value)}
									placeholder="English"
									disabled={uploading}
								/>
							</Col>
							<Col md={4}>
								<Form.Label className="small text-muted">
									{__(
										'Caption file (.vtt or .srt)',
										'infinite-uploads'
									)}
								</Form.Label>
								<Form.Control
									ref={fileRef}
									type="file"
									accept=".vtt,.srt"
									onChange={onFileChange}
									disabled={uploading}
								/>
							</Col>
						</Row>
						<Row>
							<Col>
								<Button
									type="submit"
									variant="primary"
									disabled={uploading || !file}
								>
									{uploading ? (
										<>
											<Spinner
												animation="border"
												size="sm"
												className="me-2"
											/>
											{__(
												'Uploading…',
												'infinite-uploads'
											)}
										</>
									) : (
										__(
											'Upload caption',
											'infinite-uploads'
										)
									)}
								</Button>
								<span className="text-muted small ms-3">
									{__(
										'Uploading a caption with a language that already exists replaces it.',
										'infinite-uploads'
									)}
								</span>
							</Col>
						</Row>
					</Form>
				</Col>
			</Row>
		</div>
	);
}
