import { describe, expect, test } from "bun:test";
import { transformProjectV22ToV23 } from "../transformers/v22-to-v23";

describe("V22 to V23 Migration", () => {
	test("converts project time values from seconds to ticks and fps to a frame-rate object", () => {
		const result = transformProjectV22ToV23({
			project: {
				id: "project-v22-time",
				version: 22,
				metadata: {
					id: "project-v22-time",
					name: "Project",
					duration: 15.5,
					createdAt: "2026-01-01T00:00:00.000Z",
					updatedAt: "2026-01-01T00:00:00.000Z",
				},
				settings: {
					fps: 29.97,
					canvasSize: { width: 1920, height: 1080 },
					background: { type: "color", color: "#000000" },
				},
				timelineViewState: {
					zoomLevel: 1,
					scrollLeft: 120,
					playheadTime: 1.25,
				},
				scenes: [
					{
						id: "scene-1",
					bookmarks: [
						{ time: 2.5, duration: 0.75, note: "Marker", color: "#ff0000" },
						{ time: 4.5 },
					],
						tracks: [
							{
								id: "track-1",
								type: "video",
								elements: [
									{
										id: "element-1",
										type: "video",
										startTime: 1.25,
										duration: 5.5,
										trimStart: 0.25,
										trimEnd: 0.5,
										sourceDuration: 6.25,
										animations: {
											bindings: {
												opacity: {
													path: "opacity",
													kind: "number",
													components: [
														{
															key: "value",
															channelId: "opacity:value",
														},
													],
												},
											},
											channels: {
												"opacity:value": {
													kind: "scalar",
													keys: [
														{
															id: "key-1",
															time: 0.5,
															value: 1,
															segmentToNext: "bezier",
															tangentMode: "flat",
															rightHandle: {
																dt: 0.25,
																dv: 0.2,
															},
														},
														{
															id: "key-2",
															time: 1.0,
															value: 0.4,
															segmentToNext: "linear",
															tangentMode: "flat",
															leftHandle: {
																dt: -0.125,
																dv: -0.1,
															},
														},
													],
												},
											},
										},
									},
								],
							},
						],
						createdAt: "2026-01-01T00:00:00.000Z",
						updatedAt: "2026-01-01T00:00:00.000Z",
					},
				],
			},
		});

		expect(result.skipped).toBe(false);
		expect(result.project.version).toBe(23);

		const metadata = result.project.metadata as Record<string, unknown>;
		expect(metadata.duration).toBe(1_860_000);

		const settings = result.project.settings as Record<string, unknown>;
		expect(settings.fps).toEqual({ numerator: 30_000, denominator: 1_001 });

		const timelineViewState = result.project.timelineViewState as Record<
			string,
			unknown
		>;
		expect(timelineViewState.playheadTime).toBe(150_000);
		expect(timelineViewState.scrollLeft).toBe(120);

		const scenes = result.project.scenes as Array<Record<string, unknown>>;
		const scene = scenes[0];
		expect(scene.bookmarks).toEqual([
			{
				time: 300_000,
				duration: 90_000,
				note: "Marker",
				color: "#ff0000",
			},
			{ time: 540_000 },
		]);

		const tracks = scene.tracks as Array<Record<string, unknown>>;
		const elements = tracks[0].elements as Array<Record<string, unknown>>;
		const element = elements[0];
		expect(element.startTime).toBe(150_000);
		expect(element.duration).toBe(660_000);
		expect(element.trimStart).toBe(30_000);
		expect(element.trimEnd).toBe(60_000);
		expect(element.sourceDuration).toBe(750_000);

		const animations = element.animations as Record<string, unknown>;
		const channels = animations.channels as Record<string, Record<string, unknown>>;
		expect(channels["opacity:value"]).toEqual({
			kind: "scalar",
			keys: [
				{
					id: "key-1",
					time: 60_000,
					value: 1,
					segmentToNext: "bezier",
					tangentMode: "flat",
					rightHandle: {
						dt: 30_000,
						dv: 0.2,
					},
				},
				{
					id: "key-2",
					time: 120_000,
					value: 0.4,
					segmentToNext: "linear",
					tangentMode: "flat",
					leftHandle: {
						dt: -15_000,
						dv: -0.1,
					},
				},
			],
		});
	});

	test("skips projects already on v23", () => {
		const result = transformProjectV22ToV23({
			project: {
				id: "project-v23",
				version: 23,
			},
		});

		expect(result.skipped).toBe(true);
		expect(result.reason).toBe("already v23");
	});

	test("skips projects not on v22", () => {
		const result = transformProjectV22ToV23({
			project: {
				id: "project-v21",
				version: 21,
			},
		});

		expect(result.skipped).toBe(true);
		expect(result.reason).toBe("not v22");
	});
});
