/*
  Migrate legacy Work Activities (1 doc = 1 day, workactivities.activity_date NOT NULL)
  into the new monthly structure (1 doc = 1 month, workactivities.activity_date NULL,
  workactivities.period_year/period_month set, and items store per-day activity_date).

  What it does:
  - Groups daily workactivities by (employee_id, company_id, YEAR(activity_date), MONTH(activity_date))
  - Creates/fetches a monthly workactivity header for each group
  - Moves items by updating workactivityitems.workactivity_id to the monthly header
    and ensures workactivityitems.activity_date is set
  - Disables old daily headers (enabled=false) after moving

  Usage:
    node ./scripts/migrate-workactivities-daily-to-monthly.js

  Notes:
  - Requires DB schema migration to be applied first.
  - Does NOT migrate workflows from daily docs; monthly docs get a Draft workflow if missing.
*/

const db = require("../apps/sapps/helpers/db");

const WORK_ACTIVITY_DOCTYPE_ID = 230;

function pad2(n) {
	return String(n).padStart(2, "0");
}

async function main() {
	await (db.waitForInitialization ? db.waitForInitialization() : db.initializationPromise);

	const { WorkActivity, WorkActivityItem, Workflow, sequelize, Sequelize } = db;
	const { Op } = Sequelize;

	// Fetch all legacy daily docs that still have a date.
	const dailyDocs = await WorkActivity.findAll({
		where: {
			activity_date: { [Op.not]: null },
			enabled: true,
		},
		attributes: ["id", "employee_id", "company_id", "activity_date", "creation", "modified", "modified_by", "owner"],
		order: [["activity_date", "ASC"]],
	});

	if (!dailyDocs.length) {
		console.log("No daily Work Activities found to migrate.");
		return;
	}

	// Group by employee+company+period
	const groups = new Map();
	for (const doc of dailyDocs) {
		const d = new Date(doc.activity_date);
		const periodYear = d.getFullYear();
		const periodMonth = d.getMonth() + 1;
		const key = `${doc.employee_id || "null"}|${doc.company_id || "null"}|${periodYear}|${periodMonth}`;
		const arr = groups.get(key) || [];
		arr.push({ doc, periodYear, periodMonth });
		groups.set(key, arr);
	}

	console.log(`Found ${dailyDocs.length} daily docs in ${groups.size} month-group(s).`);

	let migratedDocs = 0;
	let migratedItems = 0;

	for (const [key, entries] of groups.entries()) {
		const { doc: firstDoc, periodYear, periodMonth } = entries[0];

		const tx = await sequelize.transaction();
		try {
			// Find or create the monthly header
			let monthly = await WorkActivity.findOne({
				where: {
					employee_id: firstDoc.employee_id,
					company_id: firstDoc.company_id,
					period_year: periodYear,
					period_month: periodMonth,
					activity_date: { [Op.is]: null },
					enabled: true,
				},
				transaction: tx,
				lock: tx.LOCK.UPDATE,
			});

			if (!monthly) {
				const now = new Date();
				monthly = await WorkActivity.create(
					{
						creation: firstDoc.creation || now,
						modified: now,
						modified_by: firstDoc.modified_by || 1,
						owner: firstDoc.owner || 1,
						enabled: true,
						activity_date: null,
						work_type: null,
						employee_id: firstDoc.employee_id,
						company_id: firstDoc.company_id,
						period_year: periodYear,
						period_month: periodMonth,
					},
					{ transaction: tx },
				);

				// Ensure workflow exists for the monthly doc
				await Workflow.findOrCreate({
					where: { doctype_id: WORK_ACTIVITY_DOCTYPE_ID, doc_id: monthly.id },
					defaults: {
						creation: now,
						modified: now,
						modified_by: firstDoc.modified_by || 1,
						owner: firstDoc.owner || 1,
						doctype_id: WORK_ACTIVITY_DOCTYPE_ID,
						doc_id: monthly.id,
						status: "Draft",
					},
					transaction: tx,
				});
			}

			// Move items from each daily doc into the monthly header
			for (const { doc } of entries) {
				const updated = await WorkActivityItem.update(
					{
						workactivity_id: monthly.id,
						activity_date: doc.activity_date,
					},
					{
						where: {
							workactivity_id: doc.id,
						},
						transaction: tx,
					},
				);

				// Sequelize returns [affectedCount]
				const affected = Array.isArray(updated) ? updated[0] : 0;
				migratedItems += affected;

				// Disable the old daily header after moving
				await WorkActivity.update(
					{
						enabled: false,
						modified: new Date(),
					},
					{ where: { id: doc.id }, transaction: tx },
				);
				migratedDocs += 1;
			}

			await tx.commit();
			console.log(`Migrated group ${periodYear}-${pad2(periodMonth)} (${key}) -> monthly id ${monthly.id}`);
		} catch (e) {
			await tx.rollback();
			console.error(`Failed migrating group ${key}:`, e);
			throw e;
		}
	}

	console.log(JSON.stringify({ migratedDocs, migratedItems }, null, 2));
}

main().catch((e) => {
	console.error(e);
	process.exit(1);
});
