import { WAVE_ACCESS_TOKEN } from '$env/static/private';
import { PUBLIC_WAVE_BUSINESS_ID } from '$env/static/public';
import { createWaveServerClient } from './client';
import {
	CreateInvoiceDocument,
	DeleteInvoiceDocument,
	SendInvoiceDocument,
	UpdateInvoiceDocument,
	ApproveInvoiceDocument,
	CreateProductDocument,
	UpdateProductDocument,
	ArchiveProductDocument,
	CreateCustomerDocument,
	UpdateCustomerDocument,
	DeleteCustomerDocument
} from './generated';

export interface WaveInvoiceItem {
	productId: string;
	description?: string;
	quantity: string;
	unitPrice: string;
}

export interface WaveInvoiceDiscount {
	discountType: 'PERCENTAGE' | 'FIXED';
	name?: string;
	percentage?: string;
	amount?: string;
}

export interface CreateWaveInvoiceInput {
	businessId: string;
	customerId: string;
	status?: 'DRAFT' | 'SAVED' | 'SENT';
	invoiceDate?: string;
	dueDate?: string;
	items: WaveInvoiceItem[];
	discounts?: WaveInvoiceDiscount[];
	memo?: string;
	footer?: string;
}

export interface WaveInvoiceResult {
	success: boolean;
	invoice?: {
		id: string;
		invoiceNumber: string;
		status: string;
		pdfUrl: string;
		viewUrl: string;
	};
	error?: string;
}

export async function createWaveInvoice(input: CreateWaveInvoiceInput): Promise<WaveInvoiceResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(CreateInvoiceDocument, {
		input: {
			businessId: input.businessId,
			customerId: input.customerId,
			status: input.status || 'DRAFT',
			invoiceDate: input.invoiceDate,
			dueDate: input.dueDate,
			items: input.items,
			discounts: input.discounts,
			memo: input.memo,
			footer: input.footer
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to create Wave invoice' };
	}

	const invoiceCreate = result.data?.invoiceCreate;

	if (!invoiceCreate?.didSucceed) {
		const errorMessages = invoiceCreate?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to create Wave invoice' };
	}

	return {
		success: true,
		invoice: invoiceCreate.invoice
			? {
					id: invoiceCreate.invoice.id,
					invoiceNumber: invoiceCreate.invoice.invoiceNumber,
					status: invoiceCreate.invoice.status,
					pdfUrl: invoiceCreate.invoice.pdfUrl,
					viewUrl: invoiceCreate.invoice.viewUrl
				}
			: undefined
	};
}

export interface UpdateWaveInvoiceInput {
	id: string;
	invoiceDate?: string;
	dueDate?: string;
	items?: WaveInvoiceItem[];
	discounts?: WaveInvoiceDiscount[];
	memo?: string;
	footer?: string;
}

export async function updateWaveInvoice(input: UpdateWaveInvoiceInput): Promise<WaveInvoiceResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(UpdateInvoiceDocument, {
		input: {
			id: input.id,
			invoiceDate: input.invoiceDate,
			dueDate: input.dueDate,
			items: input.items,
			discounts: input.discounts,
			memo: input.memo,
			footer: input.footer
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to update Wave invoice' };
	}

	const invoicePatch = result.data?.invoicePatch;

	if (!invoicePatch?.didSucceed) {
		const errorMessages = invoicePatch?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to update Wave invoice' };
	}

	return {
		success: true,
		invoice: invoicePatch.invoice
			? {
					id: invoicePatch.invoice.id,
					invoiceNumber: invoicePatch.invoice.invoiceNumber,
					status: invoicePatch.invoice.status,
					pdfUrl: '',
					viewUrl: ''
				}
			: undefined
	};
}

export interface DeleteWaveInvoiceResult {
	success: boolean;
	error?: string;
}

export async function deleteWaveInvoice(invoiceId: string): Promise<DeleteWaveInvoiceResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(DeleteInvoiceDocument, {
		input: { invoiceId }
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to delete Wave invoice' };
	}

	const invoiceDelete = result.data?.invoiceDelete;

	if (!invoiceDelete?.didSucceed) {
		const errorMessages = invoiceDelete?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to delete Wave invoice' };
	}

	return { success: true };
}

export interface ApproveWaveInvoiceResult {
	success: boolean;
	error?: string;
}

export async function approveWaveInvoice(invoiceId: string): Promise<ApproveWaveInvoiceResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(ApproveInvoiceDocument, {
		input: { invoiceId }
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to approve Wave invoice' };
	}

	const invoiceApprove = result.data?.invoiceApprove;

	if (!invoiceApprove?.didSucceed) {
		const errorMessages = invoiceApprove?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to approve Wave invoice' };
	}

	return { success: true };
}

export async function sendWaveInvoice(invoiceId: string, to: string[]): Promise<WaveInvoiceResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(SendInvoiceDocument, {
		input: { invoiceId, to, attachPDF: true }
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to send Wave invoice' };
	}

	const invoiceSend = result.data?.invoiceSend;

	if (!invoiceSend?.didSucceed) {
		const errorMessages = invoiceSend?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to send Wave invoice' };
	}

	return {
		success: true,
		invoice: invoiceSend.invoice
			? {
					id: invoiceSend.invoice.id,
					invoiceNumber: invoiceSend.invoice.invoiceNumber,
					status: invoiceSend.invoice.status,
					pdfUrl: invoiceSend.invoice.pdfUrl,
					viewUrl: invoiceSend.invoice.viewUrl
				}
			: undefined
	};
}

// =====================
// Product Mutations
// =====================

export interface CreateWaveProductInput {
	name: string;
	unitPrice: number;
	description?: string;
	incomeAccountId?: string;
	expenseAccountId?: string;
	defaultSalesTaxIds?: string[];
}

export interface WaveProductResult {
	success: boolean;
	product?: {
		id: string;
		name: string;
		description: string | null;
		unitPrice: number;
	};
	error?: string;
}

export async function createWaveProduct(input: CreateWaveProductInput): Promise<WaveProductResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(CreateProductDocument, {
		input: {
			businessId: PUBLIC_WAVE_BUSINESS_ID,
			name: input.name,
			unitPrice: input.unitPrice,
			description: input.description,
			incomeAccountId: input.incomeAccountId,
			expenseAccountId: input.expenseAccountId,
			defaultSalesTaxIds: input.defaultSalesTaxIds
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to create product' };
	}

	const productCreate = result.data?.productCreate;

	if (!productCreate?.didSucceed) {
		const errorMessages = productCreate?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to create product' };
	}

	return {
		success: true,
		product: productCreate.product
			? {
					id: productCreate.product.id,
					name: productCreate.product.name,
					description: productCreate.product.description ?? null,
					unitPrice: parseFloat(productCreate.product.unitPrice)
				}
			: undefined
	};
}

export interface UpdateWaveProductInput {
	id: string;
	name?: string;
	unitPrice?: number;
	description?: string;
	incomeAccountId?: string;
	expenseAccountId?: string;
	defaultSalesTaxIds?: string[];
}

export async function updateWaveProduct(input: UpdateWaveProductInput): Promise<WaveProductResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(UpdateProductDocument, {
		input: {
			id: input.id,
			name: input.name,
			unitPrice: input.unitPrice,
			description: input.description,
			incomeAccountId: input.incomeAccountId,
			expenseAccountId: input.expenseAccountId,
			defaultSalesTaxIds: input.defaultSalesTaxIds
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to update product' };
	}

	const productPatch = result.data?.productPatch;

	if (!productPatch?.didSucceed) {
		const errorMessages = productPatch?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to update product' };
	}

	return {
		success: true,
		product: productPatch.product
			? {
					id: productPatch.product.id,
					name: productPatch.product.name,
					description: productPatch.product.description ?? null,
					unitPrice: parseFloat(productPatch.product.unitPrice)
				}
			: undefined
	};
}

export interface ArchiveWaveProductResult {
	success: boolean;
	error?: string;
}

export async function archiveWaveProduct(productId: string): Promise<ArchiveWaveProductResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(ArchiveProductDocument, {
		input: { id: productId }
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to archive product' };
	}

	const productArchive = result.data?.productArchive;

	if (!productArchive?.didSucceed) {
		const errorMessages = productArchive?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to archive product' };
	}

	return { success: true };
}

// =====================
// Customer Mutations
// =====================

export interface WaveAddressInput {
	addressLine1?: string;
	addressLine2?: string;
	city?: string;
	provinceCode?: string;
	countryCode?: string;
	postalCode?: string;
}

export interface CreateWaveCustomerInput {
	name: string;
	firstName?: string;
	lastName?: string;
	email?: string;
	phone?: string;
	mobile?: string;
	address?: WaveAddressInput;
	internalNotes?: string;
	currency?: string;
}

export interface WaveCustomerResult {
	success: boolean;
	customer?: {
		id: string;
		name: string;
		email: string | null;
	};
	error?: string;
}

export async function createWaveCustomer(
	input: CreateWaveCustomerInput
): Promise<WaveCustomerResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(CreateCustomerDocument, {
		input: {
			businessId: PUBLIC_WAVE_BUSINESS_ID,
			name: input.name,
			firstName: input.firstName,
			lastName: input.lastName,
			email: input.email,
			phone: input.phone,
			mobile: input.mobile,
			address: input.address,
			internalNotes: input.internalNotes,
			currency: input.currency
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to create customer' };
	}

	const customerCreate = result.data?.customerCreate;

	if (!customerCreate?.didSucceed) {
		const errorMessages = customerCreate?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to create customer' };
	}

	return {
		success: true,
		customer: customerCreate.customer
			? {
					id: customerCreate.customer.id,
					name: customerCreate.customer.name,
					email: customerCreate.customer.email ?? null
				}
			: undefined
	};
}

export interface UpdateWaveCustomerInput {
	id: string;
	name?: string;
	firstName?: string;
	lastName?: string;
	email?: string;
	phone?: string;
	mobile?: string;
	address?: WaveAddressInput;
	internalNotes?: string;
	currency?: string;
}

export async function updateWaveCustomer(
	input: UpdateWaveCustomerInput
): Promise<WaveCustomerResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(UpdateCustomerDocument, {
		input: {
			id: input.id,
			name: input.name,
			firstName: input.firstName,
			lastName: input.lastName,
			email: input.email,
			phone: input.phone,
			mobile: input.mobile,
			address: input.address,
			internalNotes: input.internalNotes,
			currency: input.currency
		}
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to update customer' };
	}

	const customerPatch = result.data?.customerPatch;

	if (!customerPatch?.didSucceed) {
		const errorMessages = customerPatch?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to update customer' };
	}

	return {
		success: true,
		customer: customerPatch.customer
			? {
					id: customerPatch.customer.id,
					name: customerPatch.customer.name,
					email: customerPatch.customer.email ?? null
				}
			: undefined
	};
}

export interface DeleteWaveCustomerResult {
	success: boolean;
	error?: string;
}

export async function deleteWaveCustomer(customerId: string): Promise<DeleteWaveCustomerResult> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.mutation(DeleteCustomerDocument, {
		input: { id: customerId }
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return { success: false, error: result.error.message || 'Failed to delete customer' };
	}

	const customerDelete = result.data?.customerDelete;

	if (!customerDelete?.didSucceed) {
		const errorMessages = customerDelete?.inputErrors
			?.map(
				(e: { path?: string[] | null; message?: string | null }) =>
					`${e.path?.join('.')}: ${e.message}`
			)
			.join(', ');
		return { success: false, error: errorMessages || 'Failed to delete customer' };
	}

	return { success: true };
}
