"use client"

import type { components } from "@shared/api/__generated__/openapi.types"
import type { JSX } from "react"

import cs from "classnames"
import { FunctionComponent, useCallback, useRef, useState } from "react"
import { HexColorPicker } from "react-colorful"
import { Controller, useForm, useWatch } from "react-hook-form"

import {
	Button,
	Select,
	SelectItem,
	Slider,
	Tabs,
	TabsContent,
	TabsList,
	TabsTrigger,
	TextField,
} from "@shared/ui"

import { StylePreview } from "./StylePreview"
import { useCreatePreset, useUpdatePreset } from "./useCaptionPresets"

import styles from "./StyleEditor.module.scss"

type CaptionStyleConfig = components["schemas"]["CaptionStyleConfig"]

interface IStyleEditorProps {
	initialConfig?: CaptionStyleConfig | null
	presetId?: string | null
	presetName?: string
	onSaved: (presetId: string) => void
	onCancel: () => void
}

interface FormValues {
	name: string
	text: {
		font_family: string
		font_size: number
		font_weight: number
		text_color: string
		highlight_color: string
		text_shadow: string | null
		text_stroke_width: number
		text_stroke_color: string
	}
	layout: {
		vertical_position: "top" | "center" | "bottom"
		horizontal_alignment: "left" | "center" | "right"
		padding_px: number
		max_width_pct: number
		lines_per_screen: number
	}
	animation: {
		highlight_style: "color" | "scale" | "underline" | "color_scale"
		highlight_scale: number
		segment_transition: "fade" | "slide" | "none"
		fade_duration_frames: number
		animation_speed: number
	}
	background: {
		bg_color: string
		bg_blur_px: number
		bg_glow_color: string | null
		bg_border_radius_px: number
		bg_padding_px: number
	}
}

const DEFAULT_VALUES: FormValues = {
	name: "",
	text: {
		font_family: "Lobster",
		font_size: 40,
		font_weight: 400,
		text_color: "#FFFFFF",
		highlight_color: "#FFFF00",
		text_shadow: "0 2px 4px rgba(0,0,0,0.5)" as string | null,
		text_stroke_width: 0,
		text_stroke_color: "#000000",
	},
	layout: {
		vertical_position: "bottom" as const,
		horizontal_alignment: "center" as const,
		padding_px: 16,
		max_width_pct: 90,
		lines_per_screen: 2,
	},
	animation: {
		highlight_style: "color" as const,
		highlight_scale: 1.2,
		segment_transition: "fade" as const,
		fade_duration_frames: 5,
		animation_speed: 1.0,
	},
	background: {
		bg_color: "rgba(0,0,0,0.6)",
		bg_blur_px: 0,
		bg_glow_color: null as string | null,
		bg_border_radius_px: 8,
		bg_padding_px: 12,
	},
}

/* ------------------------------------------------------------------ */
/*  Color picker field                                                  */
/* ------------------------------------------------------------------ */

const ColorField: FunctionComponent<{
	value: string
	onChange: (val: string) => void
	label: string
}> = ({ value, onChange, label }) => {
	const [open, setOpen] = useState(false)
	const ref = useRef<HTMLDivElement>(null)

	return (
		<div className={styles.colorField} ref={ref}>
			<span className={styles.fieldLabel}>{label}</span>
			<button
				type="button"
				className={styles.colorSwatch}
				style={{ backgroundColor: value || "transparent" }}
				onClick={() => setOpen(!open)}
			/>
			{open && (
				<div className={styles.colorPopover}>
					<HexColorPicker color={value} onChange={onChange} />
					<button
						type="button"
						className={styles.colorClose}
						onClick={() => setOpen(false)}
					>
						Готово
					</button>
				</div>
			)}
		</div>
	)
}

/* ------------------------------------------------------------------ */
/*  Sub-tab: Текст                                                      */
/* ------------------------------------------------------------------ */

const TextFields: FunctionComponent<{
	control: ReturnType<typeof useForm<FormValues>>["control"]
}> = ({ control }) => (
	<div className={styles.fields}>
		<Controller
			name="text.font_family"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>Шрифт</span>
					<Select
						value={field.value}
						onValueChange={field.onChange}
						placeholder="Шрифт"
					>
						{["Lobster", "Inter", "Roboto", "Montserrat", "Open Sans"].map(
							(f) => (
								<SelectItem key={f} value={f}>
									{f}
								</SelectItem>
							),
						)}
					</Select>
				</div>
			)}
		/>
		<Controller
			name="text.font_size"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Размер шрифта"
						unit="px"
						min={16}
						max={96}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="text.font_weight"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>Начертание</span>
					<Select
						value={String(field.value)}
						onValueChange={(v) => field.onChange(Number(v))}
						placeholder="Начертание"
					>
						<SelectItem value="400">Обычный</SelectItem>
						<SelectItem value="700">Жирный</SelectItem>
					</Select>
				</div>
			)}
		/>
		<Controller
			name="text.text_color"
			control={control}
			render={({ field }) => (
				<ColorField
					label="Цвет текста"
					value={field.value}
					onChange={field.onChange}
				/>
			)}
		/>
		<Controller
			name="text.highlight_color"
			control={control}
			render={({ field }) => (
				<ColorField
					label="Цвет выделения"
					value={field.value}
					onChange={field.onChange}
				/>
			)}
		/>
		<Controller
			name="text.text_stroke_width"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Обводка текста"
						unit="px"
						min={0}
						max={5}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="text.text_stroke_color"
			control={control}
			render={({ field }) => (
				<ColorField
					label="Цвет обводки"
					value={field.value}
					onChange={field.onChange}
				/>
			)}
		/>
	</div>
)

/* ------------------------------------------------------------------ */
/*  Sub-tab: Позиция                                                    */
/* ------------------------------------------------------------------ */

const LayoutFields: FunctionComponent<{
	control: ReturnType<typeof useForm<FormValues>>["control"]
}> = ({ control }) => (
	<div className={styles.fields}>
		<Controller
			name="layout.vertical_position"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>
						Вертикальная позиция
					</span>
					<Select
						value={field.value}
						onValueChange={field.onChange}
						placeholder="Позиция"
					>
						<SelectItem value="top">Сверху</SelectItem>
						<SelectItem value="center">По центру</SelectItem>
						<SelectItem value="bottom">Снизу</SelectItem>
					</Select>
				</div>
			)}
		/>
		<Controller
			name="layout.horizontal_alignment"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>Выравнивание</span>
					<Select
						value={field.value}
						onValueChange={field.onChange}
						placeholder="Выравнивание"
					>
						<SelectItem value="left">Слева</SelectItem>
						<SelectItem value="center">По центру</SelectItem>
						<SelectItem value="right">Справа</SelectItem>
					</Select>
				</div>
			)}
		/>
		<Controller
			name="layout.max_width_pct"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Макс. ширина"
						unit="%"
						min={20}
						max={100}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="layout.padding_px"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Отступы"
						unit="px"
						min={0}
						max={64}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="layout.lines_per_screen"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Строк на экране"
						min={1}
						max={4}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
	</div>
)

/* ------------------------------------------------------------------ */
/*  Sub-tab: Анимация                                                   */
/* ------------------------------------------------------------------ */

const AnimationFields: FunctionComponent<{
	control: ReturnType<typeof useForm<FormValues>>["control"]
}> = ({ control }) => (
	<div className={styles.fields}>
		<Controller
			name="animation.highlight_style"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>Стиль выделения</span>
					<Select
						value={field.value}
						onValueChange={field.onChange}
						placeholder="Стиль"
					>
						<SelectItem value="color">Цвет</SelectItem>
						<SelectItem value="scale">Масштаб</SelectItem>
						<SelectItem value="underline">Подчёркивание</SelectItem>
						<SelectItem value="color_scale">
							Цвет + масштаб
						</SelectItem>
					</Select>
				</div>
			)}
		/>
		<Controller
			name="animation.highlight_scale"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Масштаб выделения"
						min={1.0}
						max={2.0}
						step={0.1}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="animation.segment_transition"
			control={control}
			render={({ field }) => (
				<div className={styles.fieldGroup}>
					<span className={styles.fieldLabel}>Переход</span>
					<Select
						value={field.value}
						onValueChange={field.onChange}
						placeholder="Переход"
					>
						<SelectItem value="fade">Затухание</SelectItem>
						<SelectItem value="slide">Сдвиг</SelectItem>
						<SelectItem value="none">Без перехода</SelectItem>
					</Select>
				</div>
			)}
		/>
		<Controller
			name="animation.fade_duration_frames"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Длительность перехода"
						unit=" кадров"
						min={0}
						max={30}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="animation.animation_speed"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Скорость анимации"
						min={0.5}
						max={2.0}
						step={0.1}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
	</div>
)

/* ------------------------------------------------------------------ */
/*  Sub-tab: Фон                                                        */
/* ------------------------------------------------------------------ */

const BackgroundFields: FunctionComponent<{
	control: ReturnType<typeof useForm<FormValues>>["control"]
}> = ({ control }) => (
	<div className={styles.fields}>
		<Controller
			name="background.bg_color"
			control={control}
			render={({ field }) => (
				<ColorField
					label="Цвет фона"
					value={field.value}
					onChange={field.onChange}
				/>
			)}
		/>
		<Controller
			name="background.bg_blur_px"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Размытие фона"
						unit="px"
						min={0}
						max={20}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="background.bg_glow_color"
			control={control}
			render={({ field }) => (
				<ColorField
					label="Цвет свечения"
					value={field.value ?? ""}
					onChange={field.onChange}
				/>
			)}
		/>
		<Controller
			name="background.bg_border_radius_px"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Скругление углов"
						unit="px"
						min={0}
						max={24}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
		<Controller
			name="background.bg_padding_px"
			control={control}
			render={({ field }) => (
				<div className={styles.sliderField}>
					<Slider
						label="Внутренний отступ"
						unit="px"
						min={0}
						max={32}
						value={field.value}
						onChange={field.onChange}
					/>
				</div>
			)}
		/>
	</div>
)

/* ------------------------------------------------------------------ */
/*  Main editor                                                         */
/* ------------------------------------------------------------------ */

const buildDefaultValues = (
	config?: CaptionStyleConfig | null,
	name?: string,
): FormValues => ({
	name: name ?? "",
	text: { ...DEFAULT_VALUES.text, ...config?.text },
	layout: { ...DEFAULT_VALUES.layout, ...config?.layout },
	animation: { ...DEFAULT_VALUES.animation, ...config?.animation },
	background: { ...DEFAULT_VALUES.background, ...config?.background },
})

export const StyleEditor: FunctionComponent<IStyleEditorProps> = ({
	initialConfig,
	presetId,
	presetName,
	onSaved,
	onCancel,
}): JSX.Element => {
	const isEditing = !!presetId

	const { control, handleSubmit, formState } = useForm<FormValues>({
		defaultValues: buildDefaultValues(initialConfig, presetName),
	})

	const watchedValues = useWatch({ control })
	const previewConfig: CaptionStyleConfig = {
		text: watchedValues.text as CaptionStyleConfig["text"],
		layout: watchedValues.layout as CaptionStyleConfig["layout"],
		animation: watchedValues.animation as CaptionStyleConfig["animation"],
		background:
			watchedValues.background as CaptionStyleConfig["background"],
	}

	const createPreset = useCreatePreset()
	const updatePreset = useUpdatePreset()
	const isSaving = createPreset.isPending || updatePreset.isPending

	const onSubmit = useCallback(
		(data: FormValues) => {
			const styleConfig: CaptionStyleConfig = {
				text: data.text,
				layout: data.layout,
				animation: data.animation,
				background: data.background,
			}

			if (isEditing && presetId) {
				updatePreset.mutate(
					{
						params: { path: { preset_id: presetId } },
						body: {
							name: data.name || undefined,
							style_config: styleConfig,
						},
					},
					{ onSuccess: () => onSaved(presetId) },
				)
			} else {
				createPreset.mutate(
					{
						body: {
							name: data.name,
							style_config: styleConfig,
						},
					},
					{ onSuccess: (res) => onSaved(res.id) },
				)
			}
		},
		[isEditing, presetId, createPreset, updatePreset, onSaved],
	)

	return (
		<form
			className={styles.editor}
			onSubmit={handleSubmit(onSubmit)}
			data-testid="StyleEditor"
		>
			<StylePreview config={previewConfig} size="large" />

			<div className={styles.nameRow}>
				<Controller
					name="name"
					control={control}
					rules={{ required: !isEditing }}
					render={({ field }) => (
						<TextField
							{...field}
							id="preset-name"
							placeholder="Название пресета"
							className={styles.nameField}
						/>
					)}
				/>
			</div>

			<Tabs defaultValue="text" className={styles.tabs}>
				<TabsList>
					<TabsTrigger value="text">Текст</TabsTrigger>
					<TabsTrigger value="layout">Позиция</TabsTrigger>
					<TabsTrigger value="animation">Анимация</TabsTrigger>
					<TabsTrigger value="background">Фон</TabsTrigger>
				</TabsList>
				<TabsContent value="text">
					<TextFields control={control} />
				</TabsContent>
				<TabsContent value="layout">
					<LayoutFields control={control} />
				</TabsContent>
				<TabsContent value="animation">
					<AnimationFields control={control} />
				</TabsContent>
				<TabsContent value="background">
					<BackgroundFields control={control} />
				</TabsContent>
			</Tabs>

			<div className={styles.editorFooter}>
				<Button
					type="button"
					variant="outline"
					onClick={onCancel}
				>
					Отмена
				</Button>
				<Button
					type="submit"
					variant="primary"
					disabled={isSaving || (!isEditing && !formState.dirtyFields.name)}
				>
					{isSaving
						? "Сохранение..."
						: isEditing
							? "Сохранить"
							: "Создать пресет"}
				</Button>
			</div>
		</form>
	)
}
