import { z } from "zod";
import type { CreateCustomerInfoPayload, CustomerInfoModel } from "../data";
import { customerInfoModel } from "../data";

/**
 * CustomerInfoViewModel manages single customer information state for checkout.
 * Handles validation, API interactions, and form state for one customer per checkout.
 */
export class CustomerInfoViewModel {
	// State: current customer info being edited/created (single customer for checkout)
	customerInfo = $state<CustomerInfoModel | null>(null);

	// State: validation errors for the current customer info
	errors = $state<Partial<Record<keyof CustomerInfoModel, string>>>({});

	// Loading states
	loading = $state(false);
	formLoading = $state(false);

	/**
	 * Initializes customer info with default empty values for checkout
	 */
	initializeCustomerInfo() {
		this.customerInfo = this.getDefaultCustomerInfo() as CustomerInfoModel;
		this.errors = {};
	}

	/**
	 * Validates customer information data using Zod schema
	 * @param info - Customer info to validate
	 * @returns true if valid, false otherwise
	 */
	validateCustomerInfo(info?: Partial<CustomerInfoModel>): boolean {
		try {
			customerInfoModel.parse(info || this.customerInfo);
			this.errors = {};
			return true;
		} catch (error) {
			if (error instanceof z.ZodError) {
				this.errors = error.errors.reduce(
					(acc, curr) => {
						const path = curr.path[0] as keyof CustomerInfoModel;
						acc[path] = curr.message;
						return acc;
					},
					{} as Record<keyof CustomerInfoModel, string>,
				);
			}
			return false;
		}
	}

	/**
	 * Debounced validation for real-time form feedback
	 * @param info - Customer info to validate
	 * @param delay - Debounce delay in milliseconds (default: 500)
	 */
	private validationTimeout: NodeJS.Timeout | undefined;

	debounceValidate(info: Partial<CustomerInfoModel>, delay = 500) {
		if (this.validationTimeout) {
			clearTimeout(this.validationTimeout);
		}
		this.validationTimeout = setTimeout(() => {
			this.validateCustomerInfo(info);
		}, delay);
	}

	/**
	 * Checks if the current customer info has validation errors
	 * @returns true if there are no errors, false otherwise
	 */
	isValid(): boolean {
		return Object.keys(this.errors).length === 0;
	}

	/**
	 * Checks if customer info is filled out (has required fields)
	 * @returns true if customer info exists and has data, false otherwise
	 */
	isFilled(): boolean {
		if (!this.customerInfo) return false;

		return (
			this.customerInfo.firstName.length > 0 &&
			this.customerInfo.lastName.length > 0 &&
			this.customerInfo.email.length > 0 &&
			this.customerInfo.phoneNumber.length > 0
		);
	}

	/**
	 * Sets the current customer info (for editing existing records)
	 * @param customerInfo - Customer info to edit
	 */
	setCustomerInfo(customerInfo: CustomerInfoModel) {
		this.customerInfo = { ...customerInfo };
		this.errors = {};
	}

	/**
	 * Resets the customer info and errors
	 */
	resetCustomerInfo() {
		this.customerInfo = null;
		this.errors = {};
	}

	/**
	 * Returns a default/empty customer info object for forms
	 * @returns Default customer info payload
	 */
	getDefaultCustomerInfo(): CreateCustomerInfoPayload {
		return {
			firstName: "",
			middleName: "",
			lastName: "",
			email: "",
			phoneCountryCode: "",
			phoneNumber: "",
			country: "",
			state: "",
			city: "",
			zipCode: "",
			address: "",
			address2: null,
		};
	}

	/**
	 * Resets all state (for cleanup or re-initialization)
	 */
	reset() {
		this.customerInfo = null;
		this.errors = {};
		this.loading = false;
		this.formLoading = false;
		if (this.validationTimeout) {
			clearTimeout(this.validationTimeout);
		}
	}
}

export const customerInfoVM = new CustomerInfoViewModel();
