/*
 * Copyright (C) 2026 Fluxer Contributors
 *
 * This file is part of Fluxer.
 *
 * Fluxer is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fluxer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
 */

import {createNamedStringLiteralUnion, withOpenApiType} from '@fluxer/schema/src/primitives/SchemaPrimitives';
import {z} from 'zod';

export const DesktopChannelEnum = withOpenApiType(
	createNamedStringLiteralUnion(
		[
			['stable', 'Stable', 'The stable release channel for production use'],
			['canary', 'Canary', 'The canary release channel for early access to new features'],
		],
		'The release channel',
	),
	'DesktopChannel',
);
export type DesktopChannel = z.infer<typeof DesktopChannelEnum>;

export const DesktopPlatformEnum = withOpenApiType(
	createNamedStringLiteralUnion(
		[
			['win32', 'Windows', 'Microsoft Windows operating system'],
			['darwin', 'macOS', 'Apple macOS operating system'],
			['linux', 'Linux', 'Linux operating system'],
		],
		'The operating system platform',
	),
	'DesktopPlatform',
);
export type DesktopPlatform = z.infer<typeof DesktopPlatformEnum>;

export const DesktopArchEnum = withOpenApiType(
	createNamedStringLiteralUnion(
		[
			['x64', 'x64', '64-bit x86 architecture (Intel/AMD)'],
			['arm64', 'ARM64', '64-bit ARM architecture (Apple Silicon, ARM processors)'],
		],
		'The CPU architecture',
	),
	'DesktopArch',
);
export type DesktopArch = z.infer<typeof DesktopArchEnum>;

export const DesktopFormatEnum = withOpenApiType(
	createNamedStringLiteralUnion(
		[
			['setup', 'Setup', 'Windows installer executable'],
			['dmg', 'DMG', 'macOS disk image'],
			['zip', 'ZIP', 'Compressed archive'],
			['appimage', 'AppImage', 'Linux portable application'],
			['deb', 'DEB', 'Debian/Ubuntu package'],
			['rpm', 'RPM', 'Red Hat/Fedora package'],
			['tar_gz', 'TAR.GZ', 'Compressed tarball archive'],
		],
		'The package format',
	),
	'DesktopFormat',
);
export type DesktopFormat = z.infer<typeof DesktopFormatEnum>;

export const VersionString = z
	.string()
	.regex(/^\d+\.\d+\.\d+$/u)
	.describe('Semantic version string');

export const DesktopRedirectParam = z.object({
	channel: DesktopChannelEnum,
	plat: DesktopPlatformEnum,
	arch: DesktopArchEnum,
	format: DesktopFormatEnum,
});
export type DesktopRedirectParam = z.infer<typeof DesktopRedirectParam>;

export const DesktopVersionedRedirectParam = z.object({
	channel: DesktopChannelEnum,
	plat: DesktopPlatformEnum,
	arch: DesktopArchEnum,
	version: VersionString,
	format: DesktopFormatEnum,
});
export type DesktopVersionedRedirectParam = z.infer<typeof DesktopVersionedRedirectParam>;

export const DesktopVersionsParam = z.object({
	channel: DesktopChannelEnum,
	plat: DesktopPlatformEnum,
	arch: DesktopArchEnum,
});
export type DesktopVersionsParam = z.infer<typeof DesktopVersionsParam>;

export const DesktopVersionsQuery = z.object({
	limit: z.coerce.number().int().min(1).max(100).default(25).describe('Maximum number of versions to return'),
	before: VersionString.optional().describe('Return versions before this version'),
	after: VersionString.optional().describe('Return versions after this version'),
});
export type DesktopVersionsQuery = z.infer<typeof DesktopVersionsQuery>;

export const VersionFileResponse = z.object({
	url: z.string().describe('Download URL for this file'),
	sha256: z.string().nullable().describe('SHA-256 hash of the file for verification'),
});
export type VersionFileResponse = z.infer<typeof VersionFileResponse>;

export const VersionInfoResponse = z.object({
	version: z.string().describe('Semantic version string (e.g., 1.0.0)'),
	pub_date: z.string().describe('ISO 8601 date when this version was published'),
	files: z.record(DesktopFormatEnum, VersionFileResponse).describe('Map of package format to download files'),
});
export type VersionInfoResponse = z.infer<typeof VersionInfoResponse>;

export const DesktopVersionsResponse = z.object({
	versions: z.array(VersionInfoResponse).max(100).describe('Array of available versions'),
	has_more: z.boolean().describe('Whether more versions are available to fetch'),
});
export type DesktopVersionsResponse = z.infer<typeof DesktopVersionsResponse>;
