import { z } from 'zod';
import { ErrorCode } from '#constants/errors';
import { ValidationError } from '#interfaces/error/ISpecificErrors';

type ZodIssue = z.core.$ZodIssue;

// Map Zod error codes to business error codes from catalog
export const getZodErrorCode = (issue: ZodIssue): ErrorCode => {
	const { code } = issue;
	const fullPath = issue.path.map(String).join('.');

	switch (code) {
		case 'too_small':
			// Handle nested paths containing 'password'
			if (fullPath.includes('password')) return 'PASSWORD_TOO_SHORT';
			return 'VALUE_TOO_SHORT';
		case 'too_big':
			return 'VALUE_TOO_LONG';
		case 'invalid_type': {
			if ((issue as any).expected === 'string') return 'INVALID_STRING_TYPE';
			if ((issue as any).expected === 'number') return 'INVALID_NUMBER_TYPE';
			if ((issue as any).expected === 'boolean') return 'INVALID_BOOLEAN_TYPE';
			return 'INVALID_TYPE';
		}
		case 'invalid_format': {
			const validation = (issue as any).validation;
			// Handle nested paths
			if (fullPath.includes('email') || validation === 'email') return 'INVALID_EMAIL_FORMAT';
			if (fullPath.includes('uuid') || fullPath.includes('id') || validation === 'uuid') return 'INVALID_UUID_FORMAT';
			if (fullPath.includes('url') || validation === 'url') return 'INVALID_URL_FORMAT';
			if (fullPath.includes('phone')) return 'INVALID_PHONE_FORMAT';
			return 'INVALID_FORMAT';
		}
		default: {
			return 'VALIDATION_ERROR';
		}
	}
};

// Map Zod error codes to Vietnamese messages (user-friendly, not technical)
export const getZodErrorMessage = (issue: ZodIssue): { vi: string; en: string } => {
	const { code } = issue;
	const fieldName = issue.path[issue.path.length - 1] as string;

	switch (code) {
		case 'too_small': {
			const min = (issue as any).minimum;
			const exp = (issue as any).expected;
			if (fieldName === 'password') {
				return {
					vi: `Mật khẩu phải có ít nhất ${min ?? exp ?? 8} ký tự`,
					en: `Password must have at least ${min ?? exp ?? 8} characters`,
				};
			}
			return {
				vi: `Phải có ít nhất ${min ?? exp ?? 1} ký tự`,
				en: `Must have at least ${min ?? exp ?? 1} characters`,
			};
		}
		case 'too_big': {
			const max = (issue as any).maximum;
			const expBig = (issue as any).expected;
			return {
				vi: `Không được vượt quá ${max ?? expBig ?? 255} ký tự`,
				en: `Must not exceed ${max ?? expBig ?? 255} characters`,
			};
		}
		case 'invalid_type': {
			const expectedType = (issue as any).expected;
			if (expectedType === 'string') return { vi: 'Phải là văn bản', en: 'Must be text' };
			if (expectedType === 'number') return { vi: 'Phải là số', en: 'Must be a number' };
			if (expectedType === 'boolean') return { vi: 'Phải là đúng/sai', en: 'Must be true/false' };
			return { vi: `Giá trị không hợp lệ`, en: `Invalid value` };
		}
		case 'invalid_format': {
			const validation = (issue as any).validation;
			if (validation === 'email' || fieldName === 'email') return { vi: 'Email không hợp lệ', en: 'Invalid email' };
			if (validation === 'uuid' || fieldName === 'uuid' || fieldName === 'id')
				return { vi: 'ID không hợp lệ', en: 'Invalid ID' };
			if (validation === 'url' || fieldName === 'url') return { vi: 'URL không hợp lệ', en: 'Invalid URL' };
			if (fieldName === 'phone') return { vi: 'Số điện thoại không hợp lệ', en: 'Invalid phone number' };
			return { vi: 'Giá trị không hợp lệ', en: 'Invalid value' };
		}
		default: {
			const message = (issue as any).message;
			return { vi: message || 'Giá trị không hợp lệ', en: message || 'Invalid value' };
		}
	}
};

/**
 * Convert Zod validation error to ValidationError
 * Automatically maps all Zod issues to field errors
 * @param zodError - Zod validation error
 * @returns ValidationError with all field errors aggregated
 */
export const convertZodToValidationError = (zodError: z.ZodError): ValidationError => {
	const fieldErrors = zodError.issues.map((issue) => ({
		field: issue.path.map(String).join('.'),
		code: getZodErrorCode(issue),
		message: getZodErrorMessage(issue),
	}));
	return new ValidationError(fieldErrors);
};
