import { PUBLIC_FRONTEND_URL } from "$lib/core/constants";
import { trpcApiStore } from "$lib/stores/api";
import { toast } from "svelte-sonner";
import { get } from "svelte/store";
import type {
	CreateProductPayload,
	ProductModel,
	UpdateProductPayload,
} from "./data";

export class ProductViewModel {
	products = $state<ProductModel[]>([]);
	loading = $state(false);
	formLoading = $state(false);

	// Selected product for edit/delete operations
	selectedProduct = $state<ProductModel | null>(null);

	async fetchProducts() {
		const api = get(trpcApiStore);
		if (!api) {
			return toast.error("API client not initialized");
		}

		this.loading = true;
		try {
			const result = await api.product.getAllProducts.query();
			if (result.error) {
				toast.error(result.error.message, {
					description: result.error.userHint,
				});
				return false;
			}

			this.products = result.data || [];
			return true;
		} catch (e) {
			console.error(e);
			toast.error("Failed to fetch products", {
				description: "Please try again later",
			});
			return false;
		} finally {
			this.loading = false;
		}
	}

	async createProduct(payload: CreateProductPayload) {
		const api = get(trpcApiStore);
		if (!api) {
			return toast.error("API client not initialized");
		}

		this.formLoading = true;
		try {
			const result = await api.product.createProduct.mutate(payload);
			if (result.error) {
				toast.error(result.error.message, {
					description: result.error.userHint,
				});
				return false;
			}

			toast.success("Product created successfully");
			await this.fetchProducts();
			return true;
		} catch (e) {
			toast.error("Failed to create product", {
				description: "Please try again later",
			});
			return false;
		} finally {
			this.formLoading = false;
		}
	}

	async updateProduct(payload: UpdateProductPayload) {
		const api = get(trpcApiStore);
		if (!api) {
			return toast.error("API client not initialized");
		}

		this.formLoading = true;
		try {
			const result = await api.product.updateProduct.mutate(payload);
			if (result.error) {
				toast.error(result.error.message, {
					description: result.error.userHint,
				});
				return false;
			}

			toast.success("Product updated successfully");
			await this.fetchProducts();
			return true;
		} catch (e) {
			toast.error("Failed to update product", {
				description: "Please try again later",
			});
			return false;
		} finally {
			this.formLoading = false;
			this.selectedProduct = null;
		}
	}

	async deleteProduct(id: number) {
		const api = get(trpcApiStore);
		if (!api) {
			return toast.error("API client not initialized");
		}

		this.formLoading = true;
		try {
			const result = await api.product.deleteProduct.mutate({ id });
			if (result.error) {
				toast.error(result.error.message, {
					description: result.error.userHint,
				});
				return false;
			}

			toast.success("Product deleted successfully");
			await this.fetchProducts();
			return true;
		} catch (e) {
			toast.error("Failed to delete product", {
				description: "Please try again later",
			});
			return false;
		} finally {
			this.formLoading = false;
			this.selectedProduct = null;
		}
	}

	async refreshProductLinkId(id: number) {
		const api = get(trpcApiStore);
		if (!api) {
			return toast.error("API client not initialized");
		}

		try {
			const result = await api.product.refreshProductLinkId.mutate({ id });
			if (result.error) {
				toast.error(result.error.message, {
					description: result.error.userHint,
				});
				return null;
			}

			toast.success("Link ID refreshed successfully");
			await this.fetchProducts();
			return result.data;
		} catch (e) {
			toast.error("Failed to refresh link ID", {
				description: "Please try again later",
			});
			return null;
		}
	}

	selectProduct(product: ProductModel) {
		this.selectedProduct = { ...product };
	}

	clearSelectedProduct() {
		this.selectedProduct = null;
	}

	getDefaultProduct(): CreateProductPayload {
		return {
			title: "",
			description: "",
			longDescription: "",
			price: 0,
			discountPrice: 0,
		};
	}

	async copyLinkToClipboard(linkId: string) {
		try {
			await navigator.clipboard.writeText(
				`${PUBLIC_FRONTEND_URL}/${linkId}`,
			);
			toast.success("Frontend link copied to clipboard");
			return true;
		} catch (e) {
			toast.error("Failed to copy link ID", {
				description: "Please try copying manually",
			});
			return false;
		}
	}
}

export const productVM = new ProductViewModel();
