<script lang="ts">
	import { ArrowLeft, Receipt, Plus, Trash2, Send, FileCheck, X, FileText, Check, ClipboardCheck } from '@lucide/svelte';
	import { page } from '$app/state';
	import * as Card from '$lib/components/ui/card';
	import * as Table from '$lib/components/ui/table';
	import { Button } from '$lib/components/ui/button';
	import { companyStore } from '$lib/stores/company.svelte';
	import {
		invoicesAPI, invoiceItemsAPI, paymentsAPI,
		type Invoice, type InvoiceInput, type InvoiceItem, type InvoiceItemInput, type Payment, type PaymentInput
	} from '$lib/api/fin';
	import { accountsAPI, type Account } from '$lib/api/crm';
	import { INVOICE_STATUS, QUOTE_CONCEPTS, PAYMENT_METHODS, labelOf, formatMoney } from '$lib/components/crm/format';
	import { toast } from 'svelte-sonner';

	const invoiceId = $derived(Number(page.params.id));
	const companyId = $derived(companyStore.activeCompany?.id ?? null);

	let invoice = $state<Invoice | null>(null);
	let items = $state<InvoiceItem[]>([]);
	let payments = $state<Payment[]>([]);
	let accounts = $state<Account[]>([]);
	let form = $state<InvoiceInput>({});
	let tab = $state('conceptos');
	let loading = $state(false);
	let saving = $state(false);
	let busy = $state(false);
	let addingItem = $state(false);
	let addingPay = $state(false);
	let newItem = $state<InvoiceItemInput>({ invoice_id: 0, concept: 'flete_internacional', quantity: 1, unit_amount: 0 });
	let newPay = $state<PaymentInput>({ invoice_id: 0, amount: 0, method: 'transferencia' });

	$effect(() => {
		const cid = companyId;
		const id = invoiceId;
		if (!cid || !id) return;
		void load(cid, id);
	});

	async function load(cid: number, id: number) {
		loading = true;
		try {
			[invoice, items, payments, accounts] = await Promise.all([
				invoicesAPI.get(id, cid), invoicesAPI.items(id, cid), invoicesAPI.payments(id, cid), accountsAPI.list(cid)
			]);
			form = { ...invoice };
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo cargar la factura');
		} finally {
			loading = false;
		}
	}

	async function reload() {
		if (companyId) {
			[invoice, items, payments] = await Promise.all([
				invoicesAPI.get(invoiceId, companyId), invoicesAPI.items(invoiceId, companyId), invoicesAPI.payments(invoiceId, companyId)
			]);
			form = { ...invoice };
		}
	}

	async function saveHeader() {
		if (!companyId || !invoice) return;
		saving = true;
		try {
			invoice = await invoicesAPI.update(invoice.id, form, companyId);
			await reload();
			toast.success('Cambios guardados');
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo guardar');
		} finally {
			saving = false;
		}
	}

	async function doAction(action: 'emit' | 'send' | 'cancel') {
		if (!companyId || !invoice) return;
		busy = true;
		try {
			invoice = await invoicesAPI[action](invoice.id, companyId);
			form = { ...invoice };
			toast.success(action === 'send' ? 'Factura enviada (PDF generado)' : 'Factura actualizada');
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo actualizar');
		} finally {
			busy = false;
		}
	}

	async function openPdf() {
		if (!companyId || !invoice) return;
		try {
			const { url } = await invoicesAPI.pdfUrl(invoice.id, companyId);
			window.open(url, '_blank', 'noopener');
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo abrir el PDF');
		}
	}

	async function markReview() {
		if (!companyId || !invoice) return;
		busy = true;
		try {
			invoice = await invoicesAPI.markClientReview(invoice.id, companyId);
			form = { ...invoice };
			toast.success('Factura en revisión del cliente');
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo actualizar');
		} finally {
			busy = false;
		}
	}

	async function clientDecision(approved: boolean) {
		if (!companyId || !invoice) return;
		const notes = approved ? null : (window.prompt('Observaciones del cliente:') ?? null);
		busy = true;
		try {
			invoice = await invoicesAPI.clientDecision(invoice.id, approved, companyId, notes);
			form = { ...invoice };
			toast.success(approved ? 'Aprobada por el cliente' : 'Registrada con observaciones');
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo actualizar');
		} finally {
			busy = false;
		}
	}

	function startItem() { newItem = { invoice_id: invoiceId, concept: 'flete_internacional', quantity: 1, unit_amount: 0 }; addingItem = true; }
	async function saveItem() {
		if (!companyId) return;
		try { await invoiceItemsAPI.create({ ...newItem, invoice_id: invoiceId }, companyId); addingItem = false; await reload(); toast.success('Concepto agregado'); }
		catch (e) { toast.error(e instanceof Error ? e.message : 'No se pudo agregar'); }
	}
	async function removeItem(it: InvoiceItem) {
		if (!companyId || !confirm('¿Eliminar concepto?')) return;
		await invoiceItemsAPI.remove(it.id, companyId); await reload();
	}

	function startPay() { newPay = { invoice_id: invoiceId, amount: 0, method: 'transferencia' }; addingPay = true; }
	async function savePay() {
		if (!companyId) return;
		try { await paymentsAPI.create({ ...newPay, invoice_id: invoiceId }, companyId); addingPay = false; await reload(); toast.success('Pago registrado'); }
		catch (e) { toast.error(e instanceof Error ? e.message : 'No se pudo registrar'); }
	}
	async function removePay(p: Payment) {
		if (!companyId || !confirm('¿Eliminar pago?')) return;
		await paymentsAPI.remove(p.id, companyId); await reload();
	}

	const statusClass: Record<string, string> = {
		borrador: 'bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-400',
		emitida: 'bg-blue-100 text-blue-700 dark:bg-blue-950/40 dark:text-blue-400',
		enviada: 'bg-cyan-100 text-cyan-700 dark:bg-cyan-950/40 dark:text-cyan-400',
		en_revision_cliente: 'bg-amber-100 text-amber-700 dark:bg-amber-950/40 dark:text-amber-400',
		pagada: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-950/40 dark:text-emerald-400',
		cancelada: 'bg-red-100 text-red-700 dark:bg-red-950/40 dark:text-red-400'
	};
	const inputCls = 'rounded-md border bg-transparent px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring';
</script>

<div class="space-y-6">
	<Button variant="ghost" size="sm" href="/dashboard/fin/facturas"><ArrowLeft class="mr-1 h-4 w-4" /> Facturas</Button>

	{#if loading && !invoice}
		<p class="text-sm text-muted-foreground">Cargando…</p>
	{:else if invoice}
		<div class="flex flex-wrap items-start justify-between gap-3">
			<div>
				<h1 class="flex items-center gap-2 text-2xl font-bold tracking-tight"><Receipt class="h-6 w-6" /> {invoice.reference ?? `Factura #${invoice.id}`}</h1>
				<p class="mt-1 text-sm"><span class="inline-flex rounded-full px-2 py-0.5 text-xs font-medium {statusClass[invoice.status] ?? ''}">{labelOf(INVOICE_STATUS, invoice.status)}</span></p>
			</div>
			<div class="flex flex-wrap gap-2">
				{#if invoice.status === 'borrador'}<Button size="sm" variant="outline" onclick={() => doAction('emit')} disabled={busy}><FileCheck class="mr-1 h-4 w-4" /> Emitir</Button>{/if}
				{#if invoice.status === 'emitida'}<Button size="sm" variant="outline" onclick={() => doAction('send')} disabled={busy}><Send class="mr-1 h-4 w-4" /> Enviar (PDF)</Button>{/if}
				{#if invoice.pdf_file_key}<Button size="sm" variant="outline" onclick={openPdf}><FileText class="mr-1 h-4 w-4" /> Ver PDF</Button>{/if}
				{#if invoice.status === 'enviada'}<Button size="sm" variant="outline" onclick={markReview} disabled={busy}><ClipboardCheck class="mr-1 h-4 w-4" /> En revisión</Button>{/if}
				{#if invoice.status === 'enviada' || invoice.status === 'en_revision_cliente'}
					<Button size="sm" variant="outline" onclick={() => clientDecision(true)} disabled={busy}><Check class="mr-1 h-4 w-4 text-emerald-600" /> Cliente aprueba</Button>
					<Button size="sm" variant="outline" onclick={() => clientDecision(false)} disabled={busy}><X class="mr-1 h-4 w-4 text-destructive" /> Con observaciones</Button>
				{/if}
				{#if invoice.status !== 'cancelada' && invoice.status !== 'pagada'}<Button size="sm" variant="outline" onclick={() => doAction('cancel')} disabled={busy}><X class="mr-1 h-4 w-4" /> Cancelar</Button>{/if}
			</div>
		</div>

		{#if invoice.client_reviewed_at}
			<p class="text-xs text-muted-foreground">Revisión del cliente: {invoice.client_approved ? 'aprobada' : 'con observaciones'}{#if invoice.review_notes} — {invoice.review_notes}{/if}</p>
		{/if}

		<div class="grid gap-4 sm:grid-cols-4">
			<Card.Root><Card.Header><Card.Description>Subtotal</Card.Description><Card.Title class="text-lg">{formatMoney(invoice.subtotal, invoice.currency)}</Card.Title></Card.Header></Card.Root>
			<Card.Root><Card.Header><Card.Description>Impuesto ({invoice.tax_rate}%)</Card.Description><Card.Title class="text-lg">{formatMoney(invoice.tax_amount, invoice.currency)}</Card.Title></Card.Header></Card.Root>
			<Card.Root><Card.Header><Card.Description>Total</Card.Description><Card.Title class="text-lg">{formatMoney(invoice.total, invoice.currency)}</Card.Title></Card.Header></Card.Root>
			<Card.Root><Card.Header><Card.Description>Saldo</Card.Description><Card.Title class="text-lg {invoice.balance > 0 ? 'text-amber-600' : 'text-emerald-600'}">{formatMoney(invoice.balance, invoice.currency)}</Card.Title></Card.Header></Card.Root>
		</div>

		<Card.Root>
			<Card.Content class="pt-6">
				<div class="mb-5 flex flex-wrap gap-1 border-b">
					{#each [{ id: 'conceptos', label: 'Conceptos' }, { id: 'pagos', label: 'Pagos / cobranza' }, { id: 'datos', label: 'Datos' }] as t (t.id)}
						<button type="button" class="border-b-2 px-3 py-2 text-sm font-medium transition-colors {tab === t.id ? 'border-primary text-foreground' : 'border-transparent text-muted-foreground hover:text-foreground'}" onclick={() => (tab = t.id)}>{t.label}</button>
					{/each}
				</div>

				{#if tab === 'conceptos'}
					<div class="mb-3 flex justify-end"><Button size="sm" variant="outline" onclick={startItem}><Plus class="mr-1 h-4 w-4" /> Agregar concepto</Button></div>
					{#if addingItem}
						<div class="mb-4 grid gap-3 rounded-md border p-3 sm:grid-cols-2">
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Concepto</span><select class={inputCls} bind:value={newItem.concept}>{#each QUOTE_CONCEPTS as c (c.value)}<option value={c.value}>{c.label}</option>{/each}</select></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Descripción</span><input class={inputCls} bind:value={newItem.description} /></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Cantidad</span><input type="number" min="0" step="0.01" class={inputCls} bind:value={newItem.quantity} /></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Importe unitario</span><input type="number" min="0" step="0.01" class={inputCls} bind:value={newItem.unit_amount} /></label>
							<div class="flex justify-end gap-2 sm:col-span-2"><Button variant="outline" size="sm" onclick={() => (addingItem = false)}>Cancelar</Button><Button size="sm" onclick={saveItem}>Guardar</Button></div>
						</div>
					{/if}
					{#if items.length === 0}
						<p class="text-sm text-muted-foreground">Sin conceptos.</p>
					{:else}
						<Table.Root>
							<Table.Header><Table.Row><Table.Head>Concepto</Table.Head><Table.Head class="text-right">Cant.</Table.Head><Table.Head class="text-right">Unitario</Table.Head><Table.Head class="text-right">Importe</Table.Head><Table.Head></Table.Head></Table.Row></Table.Header>
							<Table.Body>
								{#each items as it (it.id)}
									<Table.Row>
										<Table.Cell class="font-medium">{labelOf(QUOTE_CONCEPTS, it.concept)}{#if it.description}<span class="block text-xs text-muted-foreground">{it.description}</span>{/if}</Table.Cell>
										<Table.Cell class="text-right">{it.quantity}</Table.Cell>
										<Table.Cell class="text-right">{formatMoney(it.unit_amount, invoice.currency)}</Table.Cell>
										<Table.Cell class="text-right">{formatMoney(it.line_total, invoice.currency)}</Table.Cell>
										<Table.Cell class="text-right"><Button variant="ghost" size="sm" onclick={() => removeItem(it)} aria-label="Eliminar"><Trash2 class="h-4 w-4 text-destructive" /></Button></Table.Cell>
									</Table.Row>
								{/each}
							</Table.Body>
						</Table.Root>
					{/if}
				{:else if tab === 'pagos'}
					<div class="mb-3 flex justify-end"><Button size="sm" variant="outline" onclick={startPay}><Plus class="mr-1 h-4 w-4" /> Registrar pago</Button></div>
					{#if addingPay}
						<div class="mb-4 grid gap-3 rounded-md border p-3 sm:grid-cols-2">
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Monto</span><input type="number" min="0" step="0.01" class={inputCls} bind:value={newPay.amount} /></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Fecha</span><input type="date" class={inputCls} bind:value={newPay.payment_date} /></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Método</span><select class={inputCls} bind:value={newPay.method}>{#each PAYMENT_METHODS as m (m.value)}<option value={m.value}>{m.label}</option>{/each}</select></label>
							<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Referencia</span><input class={inputCls} bind:value={newPay.reference} /></label>
							<div class="flex justify-end gap-2 sm:col-span-2"><Button variant="outline" size="sm" onclick={() => (addingPay = false)}>Cancelar</Button><Button size="sm" onclick={savePay}>Guardar</Button></div>
						</div>
					{/if}
					{#if payments.length === 0}
						<p class="text-sm text-muted-foreground">Sin pagos registrados.</p>
					{:else}
						<Table.Root>
							<Table.Header><Table.Row><Table.Head>Fecha</Table.Head><Table.Head>Método</Table.Head><Table.Head>Referencia</Table.Head><Table.Head class="text-right">Monto</Table.Head><Table.Head></Table.Head></Table.Row></Table.Header>
							<Table.Body>
								{#each payments as p (p.id)}
									<Table.Row>
										<Table.Cell>{p.payment_date ?? '—'}</Table.Cell>
										<Table.Cell>{labelOf(PAYMENT_METHODS, p.method)}</Table.Cell>
										<Table.Cell class="font-mono text-xs">{p.reference ?? '—'}</Table.Cell>
										<Table.Cell class="text-right">{formatMoney(p.amount, invoice.currency)}</Table.Cell>
										<Table.Cell class="text-right"><Button variant="ghost" size="sm" onclick={() => removePay(p)} aria-label="Eliminar"><Trash2 class="h-4 w-4 text-destructive" /></Button></Table.Cell>
									</Table.Row>
								{/each}
							</Table.Body>
						</Table.Root>
					{/if}
				{:else}
					<div class="grid gap-4 sm:grid-cols-2">
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Folio</span><input class={inputCls} bind:value={form.reference} /></label>
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Cliente</span><select class={inputCls} bind:value={form.account_id}><option value={undefined}>—</option>{#each accounts as a (a.id)}<option value={a.id}>{a.name}</option>{/each}</select></label>
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Moneda</span><input class={inputCls} maxlength="3" bind:value={form.currency} /></label>
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">% Impuesto</span><input type="number" min="0" max="100" step="0.01" class={inputCls} bind:value={form.tax_rate} /></label>
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Emisión</span><input type="date" class={inputCls} bind:value={form.issue_date} /></label>
						<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Vencimiento</span><input type="date" class={inputCls} bind:value={form.due_date} /></label>
						<label class="flex flex-col gap-1 text-sm sm:col-span-2"><span class="font-medium">Datos bancarios</span><textarea rows="2" class={inputCls} bind:value={form.bank_info}></textarea></label>
						<label class="flex flex-col gap-1 text-sm sm:col-span-2"><span class="font-medium">Notas</span><textarea rows="2" class={inputCls} bind:value={form.notes}></textarea></label>
					</div>
					<div class="mt-6 flex justify-end border-t pt-4"><Button onclick={saveHeader} disabled={saving}>{saving ? 'Guardando…' : 'Guardar cambios'}</Button></div>
				{/if}
			</Card.Content>
		</Card.Root>
	{/if}
</div>
