import { test, expect } from "#tests/e2e/fixtures/upload"

test.describe("File Type and Extension Validation (Integration)", () => {
	test.describe("Input Accept Attribute", () => {
		test("should restrict file input to video/* MIME types", async ({
			uploadPage,
		}) => {
			await expect(uploadPage.fileInput).toHaveAttribute(
				"accept",
				"video/*",
			)
		})
	})

	test.describe("Valid Video Files", () => {
		test("should accept and upload an MP4 file", async ({ uploadPage }) => {
			const { page, testVideoPath } = uploadPage

			await uploadPage.uploadFile(testVideoPath)

			await expect(
				page.locator("[data-testid='VerifyStep']"),
			).toBeVisible({ timeout: 30_000 })

			await expect(
				page
					.locator("[data-testid='VerifyStep']")
					.getByText("Готово к обработке"),
			).toBeVisible({ timeout: 10_000 })
		})

		test("should attempt upload for a WebM file", async ({ uploadPage }) => {
			const { page, dropZone } = uploadPage

			// Create a minimal buffer pretending to be WebM
			const webmBuffer = Buffer.from([
				0x1a, 0x45, 0xdf, 0xa3, // EBML header magic
				0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
			])

			await uploadPage.uploadBuffer("test.webm", "video/webm", webmBuffer)

			// Upload should begin (progress or error — both prove the file was sent)
			const uploadStarted = await Promise.race([
				dropZone
					.getByText("Загрузка файла...")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
			])

			expect(uploadStarted).toBe(true)
		})

		test("should attempt upload for an MOV file", async ({ uploadPage }) => {
			const { page, dropZone } = uploadPage

			// Minimal ftyp atom for MOV
			const movBuffer = Buffer.from([
				0x00, 0x00, 0x00, 0x14, // size: 20
				0x66, 0x74, 0x79, 0x70, // ftyp
				0x71, 0x74, 0x20, 0x20, // qt (QuickTime)
				0x00, 0x00, 0x00, 0x00, // minor version
				0x71, 0x74, 0x20, 0x20, // compatible brand
			])

			await uploadPage.uploadBuffer(
				"test.mov",
				"video/quicktime",
				movBuffer,
			)

			const uploadStarted = await Promise.race([
				dropZone
					.getByText("Загрузка файла...")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
			])

			expect(uploadStarted).toBe(true)
		})
	})

	test.describe("Non-Video Files (Bypass via setInputFiles)", () => {
		test("should attempt to upload a non-video file (no client-side validation)", async ({
			uploadPage,
		}) => {
			const { page, dropZone } = uploadPage

			// setInputFiles bypasses the accept attribute — proves no JS validation
			const txtBuffer = Buffer.from("Hello, this is a text file")
			await uploadPage.uploadBuffer(
				"document.txt",
				"text/plain",
				txtBuffer,
			)

			// Upload should begin regardless — component has no file type check
			const uploadStarted = await Promise.race([
				dropZone
					.getByText("Загрузка файла...")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 10_000 })
					.then(() => true)
					.catch(() => false),
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 10_000 })
					.then(() => true)
					.catch(() => false),
			])

			expect(uploadStarted).toBe(true)
		})

		test("should attempt to upload a PDF file", async ({ uploadPage }) => {
			const { page, dropZone } = uploadPage

			const pdfBuffer = Buffer.from("%PDF-1.4 fake content")
			await uploadPage.uploadBuffer(
				"document.pdf",
				"application/pdf",
				pdfBuffer,
			)

			const uploadStarted = await Promise.race([
				dropZone
					.getByText("Загрузка файла...")
					.waitFor({ timeout: 5_000 })
					.then(() => true)
					.catch(() => false),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 10_000 })
					.then(() => true)
					.catch(() => false),
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 10_000 })
					.then(() => true)
					.catch(() => false),
			])

			expect(uploadStarted).toBe(true)
		})
	})

	test.describe("Edge Cases — File Names", () => {
		test("should handle a file with Unicode characters in the name", async ({
			uploadPage,
		}) => {
			const { page, dropZone, testVideoPath } = uploadPage
			const fs = await import("node:fs")

			const videoContent = fs.readFileSync(testVideoPath)

			await uploadPage.uploadBuffer(
				"видео_тест_2026.mp4",
				"video/mp4",
				videoContent,
			)

			// Should upload successfully
			const result = await Promise.race([
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 30_000 })
					.then(() => "verify" as const),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 30_000 })
					.then(() => "error" as const),
			])

			// Both outcomes are valid — we verify no crash
			expect(["verify", "error"]).toContain(result)
		})

		test("should handle a file with special characters in the name", async ({
			uploadPage,
		}) => {
			const { page, dropZone, testVideoPath } = uploadPage
			const fs = await import("node:fs")

			const videoContent = fs.readFileSync(testVideoPath)

			await uploadPage.uploadBuffer(
				"test file (1) [final].mp4",
				"video/mp4",
				videoContent,
			)

			const result = await Promise.race([
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 30_000 })
					.then(() => "verify" as const),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 30_000 })
					.then(() => "error" as const),
			])

			expect(["verify", "error"]).toContain(result)
		})

		test("should handle a zero-byte video file", async ({ uploadPage }) => {
			const { page, dropZone } = uploadPage

			const emptyBuffer = Buffer.alloc(0)
			await uploadPage.uploadBuffer("empty.mp4", "video/mp4", emptyBuffer)

			// Should attempt upload, likely fail server-side
			const result = await Promise.race([
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 15_000 })
					.then(() => "error" as const),
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 15_000 })
					.then(() => "verify" as const),
			])

			expect(["error", "verify"]).toContain(result)
		})

		test("should handle a file with no extension", async ({
			uploadPage,
		}) => {
			const { page, dropZone, testVideoPath } = uploadPage
			const fs = await import("node:fs")

			const videoContent = fs.readFileSync(testVideoPath)

			await uploadPage.uploadBuffer(
				"videofile",
				"video/mp4",
				videoContent,
			)

			const result = await Promise.race([
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 30_000 })
					.then(() => "verify" as const),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 30_000 })
					.then(() => "error" as const),
			])

			expect(["verify", "error"]).toContain(result)
		})

		test("should handle a file with double extension", async ({
			uploadPage,
		}) => {
			const { page, dropZone, testVideoPath } = uploadPage
			const fs = await import("node:fs")

			const videoContent = fs.readFileSync(testVideoPath)

			await uploadPage.uploadBuffer(
				"video.mp4.mp4",
				"video/mp4",
				videoContent,
			)

			const result = await Promise.race([
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 30_000 })
					.then(() => "verify" as const),
				dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 30_000 })
					.then(() => "error" as const),
			])

			expect(["verify", "error"]).toContain(result)
		})
	})

	test.describe("FormData Payload Verification", () => {
		test("should send file in FormData and include correct folder path", async ({
			uploadPage,
		}) => {
			const { page, projectId, testVideoPath } = uploadPage

			let requestFired = false
			let hasAuthHeader = false
			let requestUrl = ""

			page.on("request", (req) => {
				if (req.url().includes("/api/files/upload")) {
					requestFired = true
					requestUrl = req.url()
					hasAuthHeader = !!req.headers()["authorization"]
				}
			})

			await uploadPage.uploadFile(testVideoPath)

			// Wait for the request to fire
			await expect(async () => {
				expect(requestFired).toBe(true)
			}).toPass({ timeout: 10_000 })

			expect(requestUrl).toContain("/api/files/upload")
			expect(hasAuthHeader).toBe(true)

			// Wait for upload to complete (verify or error)
			await Promise.race([
				page
					.locator("[data-testid='VerifyStep']")
					.waitFor({ timeout: 30_000 }),
				uploadPage.dropZone
					.getByText("Не удалось загрузить файл")
					.waitFor({ timeout: 30_000 }),
			])
		})
	})
})
