import { program } from 'commander';
import * as fs from 'node:fs';
import yaml from 'js-yaml';
import path from 'path';
import fg from 'fast-glob';
import { type GalleryData, loadGallery, NullGalleryData, type GalleryImage } from './galleryData.ts';
import { createGalleryCollection, createGalleryImage } from './galleryEntityFactory.ts';

const defaultGalleryFileName = 'gallery.yaml';

// 辅助函数：强制将路径转换为 Unix 风格
function toUnixPath(filepath: string) {
	return filepath.split(path.sep).join('/');
}

async function generateGalleryFile(galleryDir: string): Promise<void> {
	try {
		let galleryObj = await loadExistingGallery(galleryDir);
		const newGalleryObj = await createGalleryObjFrom(galleryDir);
		galleryObj = mergeGalleriesObj(galleryObj, newGalleryObj);
		await writeGalleryYaml(galleryDir, galleryObj);
	} catch (error) {
		console.error('Failed to create gallery file:', error);
		process.exit(1);
	}
}

async function loadExistingGallery(galleryDir: string) {
	const existingGalleryFile = path.join(galleryDir, defaultGalleryFileName);
	if (fs.existsSync(existingGalleryFile)) {
		return await loadGallery(existingGalleryFile);
	}
	return NullGalleryData;
}

function mergeGalleriesObj(
	targetGalleryObj: GalleryData,
	sourceGalleryObj: GalleryData,
): GalleryData {
	// 1. 合并图片并保留旧数据
	const mergedImages = getUpdatedImageList(targetGalleryObj, sourceGalleryObj);
	
	// 2. 智能排序：按拍摄时间倒序 (最新的在最前)
	// 如果没有拍摄时间，则按文件名排序作为兜底
	mergedImages.sort((a, b) => {
		const dateA = a.exif?.captureDate ? new Date(a.exif.captureDate).getTime() : 0;
		const dateB = b.exif?.captureDate ? new Date(b.exif.captureDate).getTime() : 0;
		
		if (dateB !== dateA) {
			return dateB - dateA; // 倒序
		}
		return a.path.localeCompare(b.path); // 文件名兜底
	});

	return {
		collections: getUpdatedCollectionList(targetGalleryObj, sourceGalleryObj),
		images: mergedImages,
	};
}

function getUpdatedImageList(targetGalleryObj: GalleryData, sourceGalleryObj: GalleryData) {
	const imagesMap = new Map(targetGalleryObj.images.map((image) => [image.path, image]));
	
	sourceGalleryObj.images.forEach((newImage) => {
		const existingImage = imagesMap.get(newImage.path);
		if (existingImage === undefined) {
			// 如果是新图片，直接添加
			imagesMap.set(newImage.path, newImage);
		} else {
			// 如果图片已存在，更新 EXIF，但保留手动修改的 Meta (标题、描述)
			// 注意：这里我们强制更新 Collections 以支持自动 Feature，
			// 但如果你希望手动移除 Feature 后不被脚本加回来，逻辑需要微调。
			// 目前逻辑：脚本检测到 _featured 会强制加上。
			
			// 检查是否需要合并 featured 标签
			const newIsFeatured = newImage.meta.collections?.includes('featured');
			const oldCollections = existingImage.meta.collections || [];
			
			if (newIsFeatured && !oldCollections.includes('featured')) {
				existingImage.meta.collections = [...oldCollections, 'featured'];
			}
			
			// 更新 EXIF (以防你重新处理了图片)
			existingImage.exif = newImage.exif;
		}
	});
	return Array.from(imagesMap.values());
}

function getUpdatedCollectionList(targetGalleryObj: GalleryData, sourceGalleryObj: GalleryData) {
	const collectionsMap = new Map(
		targetGalleryObj.collections.map((collection) => [collection.id, collection]),
	);
	sourceGalleryObj.collections.forEach((collection) => {
		if (!collectionsMap.get(collection.id)) {
			collectionsMap.set(collection.id, collection);
		}
	});
	return Array.from(collectionsMap.values());
}

async function createGalleryObjFrom(galleryDir: string): Promise<GalleryData> {
	const imageFiles = await fg(`${galleryDir}/**/*.{jpg,jpeg,png}`, {
		dot: false,
	});
	return {
		collections: createCollectionsFrom(imageFiles, galleryDir),
		images: await createImagesFrom(imageFiles, galleryDir),
	};
}

function createCollectionsFrom(imageFiles: string[], galleryDir: string) {
	const uniqueDirNames = new Set(
		imageFiles.map((file) => {
			const relPath = toUnixPath(path.relative(galleryDir, file));
			return path.posix.dirname(relPath);
		}),
	);

	return [...uniqueDirNames]
		.map((dir) => {
			return createGalleryCollection(dir);
		})
		.filter((col) => col.id !== '.');
}

async function createImagesFrom(imageFiles: string[], galleryDir: string) {
	const rawImages = await Promise.all(
		imageFiles.map((file) => createGalleryImage(galleryDir, file)),
	);

	return rawImages.map((img) => {
		// 修复路径
		if (img.path) {
			img.path = toUnixPath(img.path);
		}

		// 自动识别 Featured：如果文件名包含 "_featured"
		// 注意：这取决于你的文件名是大写还是小写，这里做不区分大小写匹配
		const filename = path.basename(img.path).toLowerCase();
		if (filename.includes('_featured') || filename.includes('-featured')) {
			// 初始化 collections 数组
			if (!img.meta.collections) {
				img.meta.collections = [];
			}
			// 避免重复添加
			if (!img.meta.collections.includes('featured')) {
				img.meta.collections.push('featured');
			}
		}

		return img;
	});
}

async function writeGalleryYaml(galleryDir: string, galleryObj: GalleryData) {
	const filePath = path.join(galleryDir, defaultGalleryFileName);
	await fs.promises.writeFile(filePath, yaml.dump(galleryObj), 'utf8');
	console.log('Gallery file created/updated successfully at:', filePath);
}

program.argument('<path to images directory>');
program.parse();

const directoryPath = program.args[0];
if (!directoryPath || !fs.existsSync(directoryPath)) {
	console.error('Invalid directory path provided.');
	process.exit(1);
}

(async () => {
	await generateGalleryFile(directoryPath);
})().catch((error) => {
	console.error('Unhandled error:', error);
	process.exit(1);
});