package org.kar.karideo.migration;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.bson.types.ObjectId;
import org.kar.archidata.api.DataResource;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.options.AccessDeletedItems;
import org.kar.archidata.dataAccess.options.OverrideTableName;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.tools.ConfigBaseVariable;
import org.kar.karideo.migration.model.CoverConversion;
import org.kar.karideo.migration.model.MediaConversion;
import org.kar.karideo.migration.model.OIDConversion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Migration20250214 extends MigrationSqlStep {
	private static final Logger LOGGER = LoggerFactory.getLogger(Migration20240226.class);

	public static final int KARSO_INITIALISATION_ID = 1;

	@Override
	public String getName() {
		return "migration-2025-01-04: convert base from UUID to OID";
	}

	@Override
	public void generateStep() throws Exception {

		addAction("""
				ALTER TABLE `data` ADD `_id` binary(12) AFTER `uuid`;
				""");
		addAction((final DBAccess da) -> {
			final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
			for (final OIDConversion elem : datas) {
				elem._id = new ObjectId();
			}
			for (final OIDConversion elem : datas) {
				da.update(elem, elem.uuid, List.of("_id"), new OverrideTableName("data"));
			}
		});
		final List<String> tableToTransform = List.of("media", "season", "series", "type", "user");
		for (final String tableName : tableToTransform) {
			addAction("ALTER TABLE `" + tableName + "` ADD `covers_oid` text NULL;");
			addAction((final DBAccess da) -> {
				final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
				final List<CoverConversion> tableCoverTransforms = da.gets(CoverConversion.class, new AccessDeletedItems(), new OverrideTableName(tableName));
				LOGGER.info("Get somes data: {} {}", datas.size(), tableCoverTransforms.size());
				for (final CoverConversion tableTransform : tableCoverTransforms) {
					final List<ObjectId> values = new ArrayList<>();
					if (tableTransform.covers == null) {
						continue;
					}
					for (final UUID link : tableTransform.covers) {
						for (final OIDConversion data : datas) {
							if (data.uuid.equals(link)) {
								values.add(data._id);
								break;
							}
						}
					}
					if (values.size() != 0) {
						tableTransform.covers_oid = values;
						LOGGER.info("    update: {}: {} => {}", tableTransform.id, tableTransform.covers, tableTransform.covers_oid);
						da.update(tableTransform, tableTransform.id, List.of("covers_oid"), new OverrideTableName(tableName));
					}
				}
			});
			addAction("ALTER TABLE `" + tableName + "` DROP `covers`;");
			addAction("ALTER TABLE `" + tableName + "` CHANGE `covers_oid` `covers` text NULL;");
		}
		addAction("""
				ALTER TABLE `media` ADD `dataOid` binary(12) AFTER dataId;
				""");
		addAction((final DBAccess da) -> {
			final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
			final List<MediaConversion> medias = da.gets(MediaConversion.class, new AccessDeletedItems(), new OverrideTableName("media"));
			for (final MediaConversion media : medias) {
				for (final OIDConversion data : datas) {
					if (data.uuid.equals(media.dataId)) {
						media.dataOid = data._id;
						da.update(media, media.id, List.of("dataOid"), new OverrideTableName("media"));
						break;
					}
				}
			}
		});
		// addAction("""
		// ALTER TABLE `media` DROP `dataId`;
		// """);
		addAction("""
				ALTER TABLE `media` CHANGE `dataId` `dataIdOld` binary(16);
				""");
		addAction("""
				ALTER TABLE `media` CHANGE `dataOid` `dataId` binary(12) NOT NULL;
				""");
		// Move the files...
		addAction((final DBAccess da) -> {
			final String filePath = ConfigBaseVariable.getMediaDataFolder() + "/Migration20250214.txt";
			try (FileWriter writer = new FileWriter(filePath, true)) {
				final List<OIDConversion> datas = da.gets(OIDConversion.class, new AccessDeletedItems(), new OverrideTableName("data"));
				for (final OIDConversion data : datas) {
					final String origin = DataResource.getFileDataOld(data.uuid);
					final String destination = DataResource.getFileData(data._id);
					LOGGER.info("move file = {}", origin);
					LOGGER.info("        ==> {}", destination);
					try {
						Files.move(Paths.get(origin), Paths.get(destination), StandardCopyOption.ATOMIC_MOVE);
					} catch (final NoSuchFileException ex) {
						LOGGER.warn("Fail to move file : {}", ex.getMessage());
					}
					writer.write(origin + " | " + destination + "\n");
					writer.flush();
				}
			} catch (final IOException e) {
				e.printStackTrace();
			}
		});
		addAction("""
				ALTER TABLE `data` DROP INDEX `PRIMARY`;
				""");
		// addAction("""
		// ALTER TABLE `data` DROP `uuid`;
		// """);
		addAction("""
				ALTER TABLE `data` ADD PRIMARY KEY `_id` (`_id`);
				""");
	}

}
