<script lang="ts">
	import { enhance } from '$app/forms';
	import { fromGlobalId } from '$lib/utils/relay';
	import IconSpinner from '$lib/components/icons/IconSpinner.svelte';
	import type {
		NexusInvoice,
		NexusRevenue,
		NexusProject,
		WaveProduct,
		WaveLineItem,
		WaveDiscount
	} from './types';
	import { SvelteDate } from 'svelte/reactivity';

	interface Props {
		invoice: NexusInvoice;
		waveCustomerId: string;
		revenues: NexusRevenue[];
		projects: NexusProject[];
		waveProducts: WaveProduct[];
		onSuccess: () => void;
		onCancel: () => void;
	}

	let { invoice, waveCustomerId, revenues, projects, waveProducts, onSuccess, onCancel }: Props =
		$props();

	let submitting = $state(false);
	let error = $state('');

	// Form state
	let invoiceDate = $state(invoice.date);
	let dueDate = $state(calculateDueDate(invoice.date, 15));
	let memo = $state(
		'Thank you for choosing Nexus Cleaning Solutions! We appreciate your business. If you have any feedback or requests, please reach out to us.'
	);
	let footer = $state('');

	// Line items state
	let lineItems = $state<WaveLineItem[]>(buildInitialLineItems());

	// Additional line item state
	let showAddLineItem = $state(false);
	let newProductId = $state('');
	let newDescription = $state('');
	let newQuantity = $state(1);
	let newUnitPrice = $state(0);

	// Discount state
	let hasDiscount = $state(false);
	let discountType = $state<'PERCENTAGE' | 'FIXED'>('PERCENTAGE');
	let discountName = $state('Discount');
	let discountValue = $state(0);

	// Available products for adding (non-archived only)
	let availableProducts = $derived(waveProducts.filter((p) => !p.isArchived));

	function calculateDueDate(fromDate: string, daysToAdd: number): string {
		const date = new SvelteDate(fromDate + 'T00:00:00');
		date.setDate(date.getDate() + daysToAdd);
		return date.toISOString().split('T')[0];
	}

	function getProduct(waveServiceId: string | null): WaveProduct | null {
		if (!waveServiceId) return null;
		return waveProducts.find((p) => fromGlobalId(p.id) === waveServiceId) ?? null;
	}

	function getProductById(productId: string): WaveProduct | null {
		return waveProducts.find((p) => p.id === productId) ?? null;
	}

	function getProductName(waveServiceId: string | null): string {
		const product = getProduct(waveServiceId);
		return product?.name ?? 'Unknown Product';
	}

	function getProductDescription(waveServiceId: string | null): string {
		const product = getProduct(waveServiceId);
		return product?.description ?? '';
	}

	function buildInitialLineItems(): WaveLineItem[] {
		const items: WaveLineItem[] = [];

		// Add revenues as line items
		for (const revenue of revenues) {
			if (!revenue.waveServiceId) continue;

			items.push({
				sourceType: 'revenue',
				sourceId: revenue.id,
				productId: revenue.waveServiceId,
				productName: getProductName(revenue.waveServiceId),
				description: getProductDescription(revenue.waveServiceId),
				quantity: 1,
				unitPrice: parseFloat(String(revenue.amount))
			});
		}

		// Add projects as line items
		for (const project of projects) {
			if (!project.waveServiceId) continue;

			items.push({
				sourceType: 'project',
				sourceId: project.id,
				productId: project.waveServiceId,
				productName: getProductName(project.waveServiceId),
				description: getProductDescription(project.waveServiceId),
				quantity: 1,
				unitPrice: parseFloat(String(project.amount))
			});
		}

		return items;
	}

	// Calculate totals
	let subtotal = $derived(lineItems.reduce((sum, item) => sum + item.quantity * item.unitPrice, 0));

	let discountAmount = $derived(() => {
		if (!hasDiscount || discountValue <= 0) return 0;
		if (discountType === 'PERCENTAGE') {
			return subtotal * (discountValue / 100);
		}
		return discountValue;
	});

	let total = $derived(subtotal - discountAmount());

	function formatCurrency(value: number): string {
		return new Intl.NumberFormat('en-US', {
			style: 'currency',
			currency: 'USD'
		}).format(value);
	}

	function updateLineItem(index: number, field: keyof WaveLineItem, value: string | number) {
		lineItems[index] = { ...lineItems[index], [field]: value };
	}

	function removeLineItem(index: number) {
		lineItems = lineItems.filter((_, i) => i !== index);
	}

	function addLineItem() {
		if (!newProductId) return;

		const product = getProductById(newProductId);
		if (!product) return;

		const decodedProductId = fromGlobalId(product.id);

		lineItems = [
			...lineItems,
			{
				sourceType: 'additional',
				sourceId: `additional-${Date.now()}`,
				productId: decodedProductId,
				productName: product.name,
				description: newDescription || product.description || '',
				quantity: newQuantity,
				unitPrice: newUnitPrice || product.unitPrice
			}
		];

		// Reset form
		showAddLineItem = false;
		newProductId = '';
		newDescription = '';
		newQuantity = 1;
		newUnitPrice = 0;
	}

	function onProductSelect(productId: string) {
		newProductId = productId;
		const product = getProductById(productId);
		if (product) {
			newDescription = product.description || '';
			newUnitPrice = product.unitPrice;
		}
	}

	// Find the Wave product Global ID for a given decoded ID
	function getWaveProductGlobalId(decodedId: string): string | null {
		const product = waveProducts.find((p) => fromGlobalId(p.id) === decodedId);
		return product?.id ?? null;
	}

	// Find the Wave customer Global ID
	function getWaveCustomerGlobalId(): string {
		// waveCustomerId from backend is stored as "businessId;Customer:customerId"
		// Wave API expects base64 encoded "Business:<businessId>;Customer:<customerId>" format
		// which is the same format, just needs to be re-encoded
		return btoa(`Business:${waveCustomerId}`);
	}

	// Build items JSON for form submission
	let itemsJson = $derived(
		JSON.stringify(
			lineItems.map((item) => {
				const productGlobalId = getWaveProductGlobalId(item.productId);
				return {
					productId: productGlobalId,
					description: item.description,
					quantity: item.quantity.toString(),
					unitPrice: item.unitPrice.toString()
				};
			})
		)
	);

	// Build discount JSON for form submission
	let discountJson = $derived(() => {
		if (!hasDiscount || discountValue <= 0) return '';
		const discount: WaveDiscount = {
			type: discountType,
			name: discountName,
			value: discountValue
		};
		return JSON.stringify(discount);
	});

	function getSourceTypeBadgeClass(sourceType: string): string {
		switch (sourceType) {
			case 'revenue':
				return 'bg-secondary-500/20 text-secondary-600 dark:text-secondary-400';
			case 'project':
				return 'bg-accent-500/20 text-accent-600 dark:text-accent-400';
			case 'additional':
				return 'bg-primary-500/20 text-primary-600 dark:text-primary-400';
			default:
				return 'bg-gray-500/20 text-gray-600 dark:text-gray-400';
		}
	}

	function getSourceTypeLabel(sourceType: string): string {
		switch (sourceType) {
			case 'revenue':
				return 'Revenue';
			case 'project':
				return 'Project';
			case 'additional':
				return 'Additional';
			default:
				return sourceType;
		}
	}
</script>

<form
	method="POST"
	action="?/createWaveInvoice"
	use:enhance={() => {
		submitting = true;
		error = '';
		return async ({ result }) => {
			submitting = false;
			if (result.type === 'failure') {
				const errorMsg = result.data?.error;
				error = typeof errorMsg === 'string' ? errorMsg : 'Failed to create invoice';
			} else if (result.type === 'success') {
				onSuccess();
			}
		};
	}}
	class="space-y-6"
>
	<!-- Hidden fields for form action -->
	<input type="hidden" name="customerId" value={getWaveCustomerGlobalId()} />
	<input type="hidden" name="items" value={itemsJson} />
	<input type="hidden" name="discount" value={discountJson()} />

	<!-- Header -->
	<div class="card-padded">
		<div class="flex items-center justify-between">
			<h3 class="text-lg font-semibold text-theme">Create Wave Invoice</h3>
			<button
				type="button"
				onclick={onCancel}
				class="rounded-lg p-2 text-theme-muted hover:bg-black/5 hover:text-theme dark:hover:bg-white/10"
				aria-label="Cancel"
			>
				<svg class="h-5 w-5" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M6 18L18 6M6 6l12 12"
					/>
				</svg>
			</button>
		</div>
	</div>

	<!-- Warning Box -->
	<div class="warning-box">
		<div class="flex gap-3">
			<svg class="warning-box-icon" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
				<path
					stroke-linecap="round"
					stroke-linejoin="round"
					stroke-width="2"
					d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
				/>
			</svg>
			<div>
				<p class="warning-box-title">Review before submitting</p>
				<p class="warning-box-text">
					Please review and adjust the descriptions and amounts below. This will create a draft
					invoice in Wave — you'll be able to preview and make final edits before sending.
				</p>
			</div>
		</div>
	</div>

	{#if error}
		<div class="mx-4 alert-error">
			{error}
		</div>
	{/if}

	<!-- Invoice Details -->
	<div class="card-padded">
		<h4 class="mb-4 text-sm font-medium text-theme-muted">Invoice Details</h4>
		<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
			<div>
				<label for="invoiceDate" class="mb-1 block text-sm font-medium text-theme">
					Invoice Date
				</label>
				<input
					type="date"
					id="invoiceDate"
					name="invoiceDate"
					bind:value={invoiceDate}
					class="w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
				/>
			</div>
			<div>
				<label for="dueDate" class="mb-1 block text-sm font-medium text-theme">Due Date</label>
				<input
					type="date"
					id="dueDate"
					name="dueDate"
					bind:value={dueDate}
					class="w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
				/>
			</div>
		</div>
	</div>

	<!-- Line Items -->
	<div class="card-padded">
		<div class="mb-4 flex items-center justify-between">
			<h4 class="text-sm font-medium text-theme-muted">Line Items</h4>
			<button
				type="button"
				onclick={() => (showAddLineItem = !showAddLineItem)}
				class="flex items-center gap-1.5 rounded-lg bg-primary-500/10 px-3 py-1.5 text-sm font-medium text-primary-600 transition-colors hover:bg-primary-500/20 dark:text-primary-400"
			>
				<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M12 4v16m8-8H4"
					/>
				</svg>
				Add Item
			</button>
		</div>

		<!-- Add Line Item Form -->
		{#if showAddLineItem}
			<div class="mb-4 rounded-lg border border-primary-500/30 bg-primary-500/5 p-4">
				<h5 class="mb-3 text-sm font-medium text-theme">Add Line Item</h5>
				<div class="space-y-3">
					<div>
						<label for="new-product" class="mb-1 block text-xs text-theme-muted">Product</label>
						<select
							id="new-product"
							onchange={(e) => onProductSelect(e.currentTarget.value)}
							class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
						>
							<option value="">Select a product...</option>
							{#each availableProducts as product (product.id)}
								<option value={product.id}>
									{product.name}
									{#if product.unitPrice > 0}
										({formatCurrency(product.unitPrice)})
									{/if}
								</option>
							{/each}
						</select>
					</div>

					{#if newProductId}
						<div>
							<label for="new-description" class="mb-1 block text-xs text-theme-muted"
								>Description</label
							>
							<input
								type="text"
								id="new-description"
								bind:value={newDescription}
								placeholder="Optional description..."
								class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
							/>
						</div>

						<div class="grid grid-cols-2 gap-3">
							<div>
								<label for="new-quantity" class="mb-1 block text-xs text-theme-muted"
									>Quantity</label
								>
								<input
									type="number"
									id="new-quantity"
									min="0.01"
									step="0.01"
									bind:value={newQuantity}
									class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
								/>
							</div>
							<div>
								<label for="new-price" class="mb-1 block text-xs text-theme-muted">Unit Price</label
								>
								<input
									type="number"
									id="new-price"
									min="0"
									step="0.01"
									bind:value={newUnitPrice}
									class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
								/>
							</div>
						</div>

						<div class="flex gap-2">
							<button
								type="button"
								onclick={addLineItem}
								class="rounded-lg bg-primary-500 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-primary-600"
							>
								Add
							</button>
							<button
								type="button"
								onclick={() => {
									showAddLineItem = false;
									newProductId = '';
								}}
								class="rounded-lg border border-theme interactive px-3 py-1.5 text-sm font-medium text-theme"
							>
								Cancel
							</button>
						</div>
					{/if}
				</div>
			</div>
		{/if}

		<div class="space-y-4">
			{#each lineItems as item, index (item.sourceId)}
				<div class="rounded-lg border border-theme bg-theme-secondary p-4">
					<div class="mb-3 flex items-start justify-between gap-2">
						<div class="flex items-center gap-2">
							<span
								class="inline-flex rounded-full px-2 py-0.5 text-xs font-medium {getSourceTypeBadgeClass(
									item.sourceType
								)}"
							>
								{getSourceTypeLabel(item.sourceType)}
							</span>
							<span class="text-sm font-medium text-theme">{item.productName}</span>
						</div>
						<div class="flex items-center gap-2">
							<span class="text-sm font-semibold text-theme">
								{formatCurrency(item.quantity * item.unitPrice)}
							</span>
							{#if item.sourceType === 'additional'}
								<button
									type="button"
									onclick={() => removeLineItem(index)}
									class="rounded p-1 text-theme-muted transition-colors hover:bg-error-500/10 hover:text-error-600 dark:hover:text-error-400"
									title="Remove item"
								>
									<svg class="h-4 w-4" style="fill: none" stroke="currentColor" viewBox="0 0 24 24">
										<path
											stroke-linecap="round"
											stroke-linejoin="round"
											stroke-width="2"
											d="M6 18L18 6M6 6l12 12"
										/>
									</svg>
								</button>
							{/if}
						</div>
					</div>

					<div class="grid grid-cols-1 gap-3 sm:grid-cols-3">
						<div class="sm:col-span-2">
							<label for="line-item-desc-{index}" class="mb-1 block text-xs text-theme-muted"
								>Description</label
							>
							<input
								type="text"
								id="line-item-desc-{index}"
								value={item.description}
								onchange={(e) => updateLineItem(index, 'description', e.currentTarget.value)}
								class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
							/>
						</div>
						<div class="grid grid-cols-2 gap-2">
							<div>
								<label for="line-item-qty-{index}" class="mb-1 block text-xs text-theme-muted"
									>Qty</label
								>
								<input
									type="number"
									id="line-item-qty-{index}"
									min="0"
									step="1"
									value={item.quantity}
									onchange={(e) =>
										updateLineItem(index, 'quantity', parseFloat(e.currentTarget.value) || 0)}
									class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
								/>
							</div>
							<div>
								<label for="line-item-price-{index}" class="mb-1 block text-xs text-theme-muted"
									>Price</label
								>
								<input
									type="number"
									id="line-item-price-{index}"
									min="0"
									step="0.01"
									value={item.unitPrice}
									onchange={(e) =>
										updateLineItem(index, 'unitPrice', parseFloat(e.currentTarget.value) || 0)}
									class="w-full rounded border border-theme bg-theme px-2 py-1.5 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
								/>
							</div>
						</div>
					</div>
				</div>
			{/each}
		</div>

		<!-- Totals -->
		<div class="mt-4 space-y-2 border-t border-theme pt-4">
			<div class="flex items-center justify-between">
				<span class="text-sm text-theme-muted">Subtotal</span>
				<span class="text-sm font-medium text-theme">
					{formatCurrency(subtotal)}
				</span>
			</div>

			{#if hasDiscount && discountValue > 0}
				<div class="flex items-center justify-between text-error-600 dark:text-error-400">
					<span class="text-sm">
						{discountName}
						{#if discountType === 'PERCENTAGE'}
							({discountValue}%)
						{/if}
					</span>
					<span class="text-sm font-medium">
						-{formatCurrency(discountAmount())}
					</span>
				</div>
			{/if}

			<div class="flex items-center justify-between border-t border-theme pt-2">
				<span class="font-medium text-theme">Total</span>
				<span class="text-lg font-bold text-accent6-600 dark:text-accent6-400">
					{formatCurrency(total)}
				</span>
			</div>
		</div>
	</div>

	<!-- Discount Section -->
	<div class="card-padded">
		<div class="mb-4 flex items-center justify-between">
			<h4 class="text-sm font-medium text-theme-muted">Discount</h4>
			<label class="flex cursor-pointer items-center gap-2">
				<input
					type="checkbox"
					bind:checked={hasDiscount}
					class="h-4 w-4 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
				/>
				<span class="text-sm text-theme">Apply discount</span>
			</label>
		</div>

		{#if hasDiscount}
			<div class="space-y-4">
				<div class="grid grid-cols-1 gap-4 sm:grid-cols-3">
					<div>
						<label for="discountType" class="mb-1 block text-sm font-medium text-theme">Type</label>
						<select
							id="discountType"
							bind:value={discountType}
							class="w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
						>
							<option value="PERCENTAGE">Percentage (%)</option>
							<option value="FIXED">Fixed Amount ($)</option>
						</select>
					</div>
					<div>
						<label for="discountName" class="mb-1 block text-sm font-medium text-theme">Name</label>
						<input
							type="text"
							id="discountName"
							bind:value={discountName}
							placeholder="e.g., Loyalty Discount"
							class="w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
						/>
					</div>
					<div>
						<label for="discountValue" class="mb-1 block text-sm font-medium text-theme">
							{discountType === 'PERCENTAGE' ? 'Percentage' : 'Amount'}
						</label>
						<div class="relative">
							{#if discountType === 'FIXED'}
								<span
									class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3 text-theme-muted"
									>$</span
								>
							{/if}
							<input
								type="number"
								id="discountValue"
								min="0"
								step={discountType === 'PERCENTAGE' ? '1' : '0.01'}
								max={discountType === 'PERCENTAGE' ? '100' : undefined}
								bind:value={discountValue}
								class="w-full rounded-lg border border-theme bg-theme py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500 {discountType ===
								'FIXED'
									? 'pr-3 pl-7'
									: 'px-3'}"
							/>
							{#if discountType === 'PERCENTAGE'}
								<span
									class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3 text-theme-muted"
									>%</span
								>
							{/if}
						</div>
					</div>
				</div>
			</div>
		{/if}
	</div>

	<!-- Notes -->
	<div class="card-padded">
		<h4 class="mb-4 text-sm font-medium text-theme-muted">Additional Notes</h4>
		<div class="space-y-4">
			<div>
				<label for="memo" class="mb-1 block text-sm font-medium text-theme">Memo (Notes)</label>
				<textarea
					id="memo"
					name="memo"
					bind:value={memo}
					rows="2"
					placeholder="Internal notes for the invoice..."
					class="placeholder-theme-muted w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
				></textarea>
			</div>
			<div>
				<label for="footer" class="mb-1 block text-sm font-medium text-theme">Footer</label>
				<textarea
					id="footer"
					name="footer"
					bind:value={footer}
					rows="2"
					placeholder="Footer text shown on the invoice..."
					class="placeholder-theme-muted w-full rounded-lg border border-theme bg-theme px-3 py-2 text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
				></textarea>
			</div>
		</div>
	</div>

	<!-- Actions -->
	<div class="card-padded">
		<div class="flex items-center gap-3">
			<button
				type="submit"
				disabled={submitting || lineItems.length === 0}
				class="flex-1 rounded-lg bg-accent6-500 px-4 py-2.5 font-medium text-white transition-colors hover:bg-accent6-600 disabled:cursor-not-allowed disabled:opacity-50"
			>
				{#if submitting}
					<span class="flex items-center justify-center gap-2">
						<IconSpinner class="h-4 w-4" />
						<span>Creating Invoice...</span>
					</span>
				{:else}
					Create Draft Invoice
				{/if}
			</button>
			<button
				type="button"
				onclick={onCancel}
				disabled={submitting}
				class="rounded-lg border border-theme bg-theme px-4 py-2.5 font-medium text-theme transition-colors hover:bg-black/5 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-white/10"
			>
				Cancel
			</button>
		</div>
	</div>
</form>
