const dbSAPPS = require("../../helpers/db");
require("dotenv").config();
const { Op } = require("sequelize");
const emailNotificationService = require("../../masters/notifications/emailNotification.service");

module.exports = {
	getAll,
	resend,
};

/**
 * Get all history emails with filters and pagination.
 * Robust implementation following email notification system best practices.
 */
async function getAll(params) {
	try {
		// Validate and sanitize pagination parameters
		const pageIndex = Math.max(0, parseInt(params.pageIndex) || 0);
		const pageSize = Math.min(100, Math.max(1, parseInt(params.pageSize) || 25)); // Max 100, min 1
		const offset = pageIndex * pageSize;
		const limit = pageSize;

		// filter conditions
		const filterConditions = {};

		// Search filter (q) - search in recipient_email, subject
		// Sanitize search query to prevent SQL injection
		if (params.q && typeof params.q === "string" && params.q.trim().length > 0) {
			const sanitizedQuery = params.q.trim().substring(0, 255); // Limit length
			filterConditions[Op.or] = [{ recipient_email: { [Op.like]: `%${sanitizedQuery}%` } }, { subject: { [Op.like]: `%${sanitizedQuery}%` } }];
		}

		// Status filter - validate against enum values
		if (params.f_status) {
			const validStatuses = ["sent", "failed", "pending"];
			if (validStatuses.includes(params.f_status)) {
				filterConditions.status = {
					[Op.eq]: params.f_status,
				};
			}
		}

		// Recipient email filter - sanitize
		if (params.f_recipient_email && typeof params.f_recipient_email === "string") {
			const sanitizedEmail = params.f_recipient_email.trim().substring(0, 255);
			if (sanitizedEmail.length > 0) {
				filterConditions.recipient_email = {
					[Op.like]: `%${sanitizedEmail}%`,
				};
			}
		}

		// Subject filter - sanitize
		if (params.f_subject && typeof params.f_subject === "string") {
			const sanitizedSubject = params.f_subject.trim().substring(0, 255);
			if (sanitizedSubject.length > 0) {
				filterConditions.subject = {
					[Op.like]: `%${sanitizedSubject}%`,
				};
			}
		}

		// Date range filter based on creation field
		// Validate date format and range
		if (params.from_date || params.to_date) {
			filterConditions.creation = {};

			if (params.from_date) {
				try {
					const fromDateStart = new Date(params.from_date);
					// Validate date
					if (!isNaN(fromDateStart.getTime())) {
						fromDateStart.setHours(0, 0, 0, 0);
						filterConditions.creation[Op.gte] = fromDateStart;
					}
				} catch (dateError) {
					console.error("Invalid from_date format:", params.from_date, dateError);
					// Skip invalid date, continue without from_date filter
				}
			}

			if (params.to_date) {
				try {
					const toDateEnd = new Date(params.to_date);
					// Validate date
					if (!isNaN(toDateEnd.getTime())) {
						toDateEnd.setHours(23, 59, 59, 999);
						filterConditions.creation[Op.lte] = toDateEnd;
					}
				} catch (dateError) {
					console.error("Invalid to_date format:", params.to_date, dateError);
					// Skip invalid date, continue without to_date filter
				}
			}

			// Validate date range: to_date should not be before from_date
			if (filterConditions.creation[Op.gte] && filterConditions.creation[Op.lte]) {
				if (filterConditions.creation[Op.lte] < filterConditions.creation[Op.gte]) {
					return {
						success: false,
						message: "Invalid date range: to_date cannot be before from_date.",
						code: "INVALID_DATE_RANGE",
					};
				}
			}
		}

		// Get total count for pagination
		let totalCount = 0;
		try {
			totalCount = await dbSAPPS.HistoryEmail.count({
				where: filterConditions,
			});
		} catch (countError) {
			console.error("Error counting history emails:", countError);
			// Continue with totalCount = 0, but log error for monitoring
		}

		// Get history emails with pagination
		let historyEmails = [];
		try {
			historyEmails = await dbSAPPS.HistoryEmail.findAll({
				where: filterConditions,
				order: [["creation", "DESC"]],
				limit,
				offset,
				include: [
					{
						model: dbSAPPS.User,
						as: "modifier",
						attributes: ["full_name"],
						required: false,
					},
				],
			});

			// Map results with error handling
			historyEmails = historyEmails.map((historyEmail) => {
				try {
					return {
						...historyEmail.dataValues,
						modifier: historyEmail?.modifier?.full_name || null,
					};
				} catch (mapError) {
					console.error("Error mapping history email:", mapError);
					// Return basic data if mapping fails
					return {
						id: historyEmail?.id || null,
						recipient_email: historyEmail?.recipient_email || "-",
						subject: historyEmail?.subject || "-",
						status: historyEmail?.status || "unknown",
						modifier: null,
					};
				}
			});
		} catch (findError) {
			console.error("Error finding history emails:", findError);
			// Return empty array but log error for monitoring
			historyEmails = [];
		}

		return {
			historyEmails,
			totalCount,
			pageIndex,
			pageSize,
			success: true,
			message: "Loaded successfully!",
		};
	} catch (error) {
		// Comprehensive error logging for monitoring
		console.error("Error in getAll history emails:", {
			error: error.message,
			stack: error.stack,
			params: params,
		});

		const errorMessage = error?.message || "Failed to load history emails. Please try again!";
		return {
			success: false,
			message: errorMessage,
			code: error?.code || "UNKNOWN_ERROR",
			historyEmails: [],
			totalCount: 0,
			pageIndex: params?.pageIndex || 0,
			pageSize: params?.pageSize || 25,
		};
	}
}

/**
 * Resend email from history email record
 * Robust implementation following email notification system best practices
 * @param {Number} historyEmailId - History email ID to resend
 * @param {Number} modified_by - User ID who triggers resend (required)
 * @param {Number} company_id - Company ID (optional, will try to get from history email if not provided)
 * @returns {Promise<Object>} - Result object with success status and message
 */
async function resend(historyEmailId, params) {
	try {
		const tryExtractCompanyIdFromBody = (html) => {
			if (!html || typeof html !== "string") return null;
			// Expect: <!-- SAPPS_META: {"company_id":123,...} -->
			const match = html.match(/<!--\s*SAPPS_META:\s*({[\s\S]*?})\s*-->/i);
			if (!match || !match[1]) return null;
			try {
				const meta = JSON.parse(match[1]);
				const cid = meta?.company_id;
				return cid != null && !Number.isNaN(Number(cid)) ? Number(cid) : null;
			} catch {
				return null;
			}
		};

		// Validate required parameters
		if (!historyEmailId) {
			return {
				success: false,
				message: "History email ID is required!",
				code: "MISSING_ID",
			};
		}

		if (!params.modified_by) {
			return {
				success: false,
				message: "modified_by (user ID) is required!",
				code: "MISSING_USER_ID",
			};
		}

		// Get history email record
		let historyEmail;
		try {
			historyEmail = await dbSAPPS.HistoryEmail.findByPk(historyEmailId);
			if (!historyEmail) {
				return {
					success: false,
					message: `History email with ID ${historyEmailId} not found!`,
					code: "NOT_FOUND",
				};
			}
		} catch (findError) {
			console.error("Error finding history email:", findError);
			return {
				success: false,
				message: "Failed to retrieve history email record.",
				code: "DATABASE_ERROR",
			};
		}

		// Determine company_id - use from params or try to get from related records
		let companyId = params.company_id;

		if (!companyId) {
			// Try to get company_id from related records
			if (historyEmail.leaveapplication_id) {
				try {
					const leaveApp = await dbSAPPS.LeaveApplication.findByPk(historyEmail.leaveapplication_id, {
						attributes: ["company_id"],
					});
					if (leaveApp) companyId = leaveApp.company_id;
				} catch (err) {
					console.warn("Could not get company_id from leave application:", err);
				}
			}

			if (!companyId && historyEmail.attendancerequest_id) {
				try {
					const attReq = await dbSAPPS.AttendanceRequest.findByPk(historyEmail.attendancerequest_id, {
						attributes: ["company_id"],
					});
					if (attReq) companyId = attReq.company_id;
				} catch (err) {
					console.warn("Could not get company_id from attendance request:", err);
				}
			}

			if (!companyId && historyEmail.absenceclarification_id) {
				try {
					const absClar = await dbSAPPS.AbsenceClarification.findByPk(historyEmail.absenceclarification_id, {
						attributes: ["company_id"],
					});
					if (absClar) companyId = absClar.company_id;
				} catch (err) {
					console.warn("Could not get company_id from absence clarification:", err);
				}
			}

			if (!companyId && historyEmail.permitEase_id) {
				try {
					const permitEase = await dbSAPPS.PermitEase.findByPk(historyEmail.permitEase_id, {
						attributes: ["company_id"],
					});
					if (permitEase) companyId = permitEase.company_id;
				} catch (err) {
					console.warn("Could not get company_id from permit ease:", err);
				}
			}

			// Final fallback: infer from embedded SAPPS_META in HTML (e.g., birthday broadcast)
			if (!companyId) {
				companyId = tryExtractCompanyIdFromBody(historyEmail.body);
			}
		}

		if (!companyId) {
			return {
				success: false,
				message: "Company ID is required for resending email. Please provide company_id parameter.",
				code: "MISSING_COMPANY_ID",
			};
		}

		// Prepare email notification parameters
		// Add note to subject that this is a resent email (preserve original subject)
		const originalSubject = historyEmail.subject || "Email";
		const resentSubject = originalSubject.startsWith("[Resent]") ? originalSubject : `[Resent] ${originalSubject}`;

		const emailParams = {
			company_id: companyId,
			to: historyEmail.recipient_email,
			subject: resentSubject,
			html: historyEmail.body || "",
			modified_by: params.modified_by,
			owner: params.owner || params.modified_by || 1,
			// Preserve original module IDs for history tracking
			leaveapplication_id: historyEmail.leaveapplication_id || null,
			attendancerequest_id: historyEmail.attendancerequest_id || null,
			absenceclarification_id: historyEmail.absenceclarification_id || null,
			permitEase_id: historyEmail.permitEase_id || null,
			upcountry_id: historyEmail.upcountry_id || null,
			maxRetries: params.maxRetries || 3,
			retryDelay: params.retryDelay || 5000,
		};

		// Send email using email notification service
		const sendResult = await emailNotificationService.sendEmailNotification(emailParams);

		if (sendResult.success) {
			return {
				success: true,
				message: `Email resent successfully to ${historyEmail.recipient_email}`,
				historyEmailId: historyEmailId,
			};
		} else {
			return {
				success: false,
				message: `Failed to resend email: ${sendResult.message}`,
				code: sendResult.code || "RESEND_FAILED",
			};
		}
	} catch (error) {
		// Comprehensive error logging for monitoring
		console.error("Error in resend history email:", {
			error: error.message,
			stack: error.stack,
			historyEmailId: historyEmailId,
			params: params,
		});

		const errorMessage = error?.message || "Failed to resend email. Please try again!";
		return {
			success: false,
			message: errorMessage,
			code: error?.code || "UNKNOWN_ERROR",
		};
	}
}
