<script lang="ts">
	import { MapPin, Users, FileText, Plus, Trash2, Pencil } from '@lucide/svelte';
	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 {
		addressesAPI, contactsAPI, documentsAPI,
		type Address, type Contact, type Document, type AddressInput, type ContactInput, type DocumentInput
	} from '$lib/api/crm';
	import { DOC_TYPES, labelOf } from '$lib/components/crm/format';
	import { crmCatalogs } from '$lib/stores/crm-catalogs.svelte';
	import { onMount } from 'svelte';
	import { uploadFile, downloadBlob } from '$lib/api/uploads';
	import { toast } from 'svelte-sonner';

	onMount(() => {
		void crmCatalogs.preload(['tipo_domicilio', 'area', 'pais']);
	});

	// Dueño de los registros relacionados y qué sección mostrar
	let {
		ownerType,
		ownerId,
		section = 'all'
	}: {
		ownerType: 'account' | 'supplier';
		ownerId: number;
		section?: 'addresses' | 'contacts' | 'documents' | 'all';
	} = $props();

	const show = (s: 'addresses' | 'contacts' | 'documents') => section === 'all' || section === s;

	let addresses = $state<Address[]>([]);
	let contacts = $state<Contact[]>([]);
	let documents = $state<Document[]>([]);
	let activeModal = $state<'address' | 'contact' | 'document' | null>(null);
	let editingId = $state<number | null>(null); // null = alta; con valor = edición
	let saving = $state(false);

	let addressForm = $state<AddressInput>({ address_type: 'fiscal', country: 'MEX', is_primary: false });
	let contactForm = $state<ContactInput>({ first_name: '' });
	let documentForm = $state<DocumentInput>({ doc_type: 'constancia_fiscal', name: '' });
	let uploading = $state(false);

	async function onFilePicked(e: Event) {
		const input = e.target as HTMLInputElement;
		const file = input.files?.[0];
		if (!file || !companyId) return;
		uploading = true;
		try {
			const up = await uploadFile(file, companyId);
			documentForm = { ...documentForm, file_key: up.file_key, file_url: up.file_url, name: documentForm.name || up.name };
			toast.success('Archivo subido');
		} catch (err) {
			toast.error(err instanceof Error ? err.message : 'No se pudo subir el archivo');
		} finally {
			uploading = false;
		}
	}

	async function openDoc(d: Document) {
		if (!companyId) return;
		try {
			if (d.file_key) {
				// Descarga por el backend (evita exponer MinIO / host interno)
				const blob = await downloadBlob(d.file_key, companyId);
				const url = URL.createObjectURL(blob);
				window.open(url, '_blank', 'noopener');
				setTimeout(() => URL.revokeObjectURL(url), 60000);
			} else if (d.file_url) {
				window.open(d.file_url, '_blank', 'noopener');
			} else {
				toast.error('El documento no tiene archivo');
			}
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudo abrir el archivo');
		}
	}

	const companyId = $derived(companyStore.activeCompany?.id ?? null);
	const ownerParam = $derived(ownerType === 'account' ? { account_id: ownerId } : { supplier_id: ownerId });

	$effect(() => {
		if (companyId && ownerId) void load(companyId);
	});

	// Estado depende del país seleccionado (catálogo dependiente)
	$effect(() => {
		if (addressForm.country) void crmCatalogs.ensure('estado', addressForm.country);
	});

	async function load(cid: number) {
		try {
			[addresses, contacts, documents] = await Promise.all([
				addressesAPI.list(cid, ownerParam),
				contactsAPI.list(cid, ownerParam),
				documentsAPI.list(cid, ownerParam)
			]);
		} catch (e) {
			toast.error(e instanceof Error ? e.message : 'No se pudieron cargar los datos relacionados');
		}
	}

	function openModal(kind: 'address' | 'contact' | 'document') {
		editingId = null;
		if (kind === 'address') addressForm = { address_type: 'fiscal', country: 'MEX', is_primary: false };
		if (kind === 'contact') contactForm = { first_name: '' };
		if (kind === 'document') documentForm = { doc_type: 'constancia_fiscal', name: '' };
		activeModal = kind;
	}

	function editAddress(a: Address) {
		editingId = a.id;
		addressForm = { ...a };
		activeModal = 'address';
	}
	function editContact(c: Contact) {
		editingId = c.id;
		contactForm = { ...c };
		activeModal = 'contact';
	}
	function editDocument(d: Document) {
		editingId = d.id;
		documentForm = { ...d };
		activeModal = 'document';
	}

	async function saveAddress(e: SubmitEvent) {
		e.preventDefault();
		if (!companyId) return;
		saving = true;
		try {
			if (editingId) await addressesAPI.update(editingId, addressForm, companyId);
			else await addressesAPI.create({ ...addressForm, ...ownerParam }, companyId);
			toast.success(editingId ? 'Dirección actualizada' : 'Dirección agregada');
			activeModal = null;
			await load(companyId);
		} catch (err) {
			toast.error(err instanceof Error ? err.message : 'No se pudo guardar');
		} finally {
			saving = false;
		}
	}

	async function saveContact(e: SubmitEvent) {
		e.preventDefault();
		if (!companyId) return;
		if (!contactForm.first_name?.trim()) { toast.error('El nombre es obligatorio'); return; }
		saving = true;
		try {
			if (editingId) await contactsAPI.update(editingId, contactForm, companyId);
			else await contactsAPI.create({ ...contactForm, ...ownerParam }, companyId);
			toast.success(editingId ? 'Contacto actualizado' : 'Contacto agregado');
			activeModal = null;
			await load(companyId);
		} catch (err) {
			toast.error(err instanceof Error ? err.message : 'No se pudo guardar');
		} finally {
			saving = false;
		}
	}

	async function saveDocument(e: SubmitEvent) {
		e.preventDefault();
		if (!companyId) return;
		if (!documentForm.name?.trim()) { toast.error('El nombre es obligatorio'); return; }
		saving = true;
		try {
			if (editingId) await documentsAPI.update(editingId, documentForm, companyId);
			else await documentsAPI.create({ ...documentForm, ...ownerParam }, companyId);
			toast.success(editingId ? 'Documento actualizado' : 'Documento agregado');
			activeModal = null;
			await load(companyId);
		} catch (err) {
			toast.error(err instanceof Error ? err.message : 'No se pudo guardar');
		} finally {
			saving = false;
		}
	}

	async function removeAddress(a: Address) {
		if (!companyId || !confirm('¿Eliminar dirección?')) return;
		await addressesAPI.remove(a.id, companyId);
		await load(companyId);
	}
	async function removeContact(c: Contact) {
		if (!companyId || !confirm('¿Eliminar contacto?')) return;
		await contactsAPI.remove(c.id, companyId);
		await load(companyId);
	}
	async function removeDocument(d: Document) {
		if (!companyId || !confirm('¿Eliminar documento?')) return;
		await documentsAPI.remove(d.id, companyId);
		await load(companyId);
	}

	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="grid gap-4">
	{#if show('addresses')}
		<Card.Root>
			<Card.Header class="flex flex-row items-center justify-between">
				<Card.Title class="flex items-center gap-2 text-base"><MapPin class="h-4 w-4" /> Direcciones</Card.Title>
				<Button size="sm" variant="outline" onclick={() => openModal('address')}><Plus class="mr-1 h-4 w-4" /> Agregar</Button>
			</Card.Header>
			<Card.Content>
				{#if addresses.length === 0}
					<p class="text-sm text-muted-foreground">Sin direcciones.</p>
				{:else}
					<Table.Root>
						<Table.Header><Table.Row><Table.Head>Tipo</Table.Head><Table.Head>Domicilio</Table.Head><Table.Head>CP</Table.Head><Table.Head>Ciudad</Table.Head><Table.Head></Table.Head></Table.Row></Table.Header>
						<Table.Body>
							{#each addresses as a (a.id)}
								<Table.Row>
									<Table.Cell>{crmCatalogs.label('tipo_domicilio', a.address_type)}{#if a.is_primary}<span class="ml-1 text-[10px] text-primary">(principal)</span>{/if}</Table.Cell>
									<Table.Cell class="text-sm">{[a.street, a.ext_number, a.neighborhood].filter(Boolean).join(' ') || '—'}</Table.Cell>
									<Table.Cell>{a.postal_code ?? '—'}</Table.Cell>
									<Table.Cell>{[a.city, a.state].filter(Boolean).join(', ') || '—'}</Table.Cell>
									<Table.Cell class="text-right"><Button variant="ghost" size="sm" onclick={() => editAddress(a)} aria-label="Editar"><Pencil class="h-4 w-4" /></Button><Button variant="ghost" size="sm" onclick={() => removeAddress(a)} aria-label="Eliminar"><Trash2 class="h-4 w-4 text-destructive" /></Button></Table.Cell>
								</Table.Row>
							{/each}
						</Table.Body>
					</Table.Root>
				{/if}
			</Card.Content>
		</Card.Root>
	{/if}

	{#if show('contacts')}
		<Card.Root>
			<Card.Header class="flex flex-row items-center justify-between">
				<Card.Title class="flex items-center gap-2 text-base"><Users class="h-4 w-4" /> Contactos</Card.Title>
				<Button size="sm" variant="outline" onclick={() => openModal('contact')}><Plus class="mr-1 h-4 w-4" /> Agregar</Button>
			</Card.Header>
			<Card.Content>
				{#if contacts.length === 0}
					<p class="text-sm text-muted-foreground">Sin contactos.</p>
				{:else}
					<Table.Root>
						<Table.Header><Table.Row><Table.Head>Nombre</Table.Head><Table.Head>Puesto / Área</Table.Head><Table.Head>Email</Table.Head><Table.Head>Teléfono</Table.Head><Table.Head></Table.Head></Table.Row></Table.Header>
						<Table.Body>
							{#each contacts as c (c.id)}
								<Table.Row>
									<Table.Cell class="font-medium">{c.first_name} {c.last_name ?? ''}{#if c.is_primary}<span class="ml-1 text-[10px] text-primary">(principal)</span>{/if}</Table.Cell>
									<Table.Cell class="text-sm">{[c.job_title, c.area ? crmCatalogs.label('area', c.area) : null].filter(Boolean).join(' · ') || '—'}</Table.Cell>
									<Table.Cell>{c.email ?? '—'}</Table.Cell>
									<Table.Cell>{c.phone ?? c.mobile ?? '—'}</Table.Cell>
									<Table.Cell class="text-right"><Button variant="ghost" size="sm" onclick={() => editContact(c)} aria-label="Editar"><Pencil class="h-4 w-4" /></Button><Button variant="ghost" size="sm" onclick={() => removeContact(c)} aria-label="Eliminar"><Trash2 class="h-4 w-4 text-destructive" /></Button></Table.Cell>
								</Table.Row>
							{/each}
						</Table.Body>
					</Table.Root>
				{/if}
			</Card.Content>
		</Card.Root>
	{/if}

	{#if show('documents')}
		<Card.Root>
			<Card.Header class="flex flex-row items-center justify-between">
				<Card.Title class="flex items-center gap-2 text-base"><FileText class="h-4 w-4" /> Documentos</Card.Title>
				<Button size="sm" variant="outline" onclick={() => openModal('document')}><Plus class="mr-1 h-4 w-4" /> Agregar</Button>
			</Card.Header>
			<Card.Content>
				{#if documents.length === 0}
					<p class="text-sm text-muted-foreground">Sin documentos.</p>
				{:else}
					<Table.Root>
						<Table.Header><Table.Row><Table.Head>Tipo</Table.Head><Table.Head>Nombre</Table.Head><Table.Head>Archivo</Table.Head><Table.Head></Table.Head></Table.Row></Table.Header>
						<Table.Body>
							{#each documents as d (d.id)}
								<Table.Row>
									<Table.Cell>{labelOf(DOC_TYPES, d.doc_type)}</Table.Cell>
									<Table.Cell class="font-medium">{d.name}</Table.Cell>
									<Table.Cell>{#if d.file_key || d.file_url}<button type="button" class="text-primary hover:underline" onclick={() => openDoc(d)}>Ver</button>{:else}—{/if}</Table.Cell>
									<Table.Cell class="text-right"><Button variant="ghost" size="sm" onclick={() => editDocument(d)} aria-label="Editar"><Pencil class="h-4 w-4" /></Button><Button variant="ghost" size="sm" onclick={() => removeDocument(d)} aria-label="Eliminar"><Trash2 class="h-4 w-4 text-destructive" /></Button></Table.Cell>
								</Table.Row>
							{/each}
						</Table.Body>
					</Table.Root>
				{/if}
			</Card.Content>
		</Card.Root>
	{/if}
</div>

{#if activeModal}
	<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4" role="presentation" onclick={() => (activeModal = null)}>
		<div class="max-h-[90vh] w-full max-w-lg overflow-y-auto rounded-lg border bg-card p-6 shadow-lg" role="dialog" aria-modal="true" tabindex="-1" onclick={(e) => e.stopPropagation()}>
			{#if activeModal === 'address'}
				<h3 class="mb-4 text-base font-semibold">{editingId ? 'Editar dirección' : 'Nueva dirección'}</h3>
				<form class="grid gap-3 sm:grid-cols-2" onsubmit={saveAddress}>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Tipo de domicilio</span><select class={inputCls} bind:value={addressForm.address_type}>{#each crmCatalogs.options('tipo_domicilio') as t (t.value)}<option value={t.value}>{t.label}</option>{/each}</select></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Código Postal</span><input class={inputCls} maxlength="10" bind:value={addressForm.postal_code} /></label>
					<label class="flex flex-col gap-1 text-sm sm:col-span-2"><span class="font-medium">Calle</span><input class={inputCls} bind:value={addressForm.street} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Núm. exterior</span><input class={inputCls} bind:value={addressForm.ext_number} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Núm. interior</span><input class={inputCls} bind:value={addressForm.int_number} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Colonia</span><input class={inputCls} bind:value={addressForm.neighborhood} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Municipio / Ciudad</span><input class={inputCls} bind:value={addressForm.city} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Estado</span>{#if crmCatalogs.options('estado', addressForm.country ?? undefined).length > 0}<select class={inputCls} bind:value={addressForm.state}><option value={undefined}>—</option>{#each crmCatalogs.options('estado', addressForm.country ?? undefined) as s (s.value)}<option value={s.value}>{s.label}</option>{/each}</select>{:else}<input class={inputCls} bind:value={addressForm.state} placeholder="Estado / provincia" />{/if}</label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">País</span><select class={inputCls} bind:value={addressForm.country}><option value={undefined}>—</option>{#each crmCatalogs.options('pais') as p (p.value)}<option value={p.value}>{p.label}</option>{/each}</select></label>
					<label class="flex flex-col gap-1 text-sm sm:col-span-2"><span class="font-medium">Referencias</span><textarea rows="2" class={inputCls} bind:value={addressForm.reference_notes}></textarea></label>
					<label class="flex items-center gap-2 text-sm sm:col-span-2"><input type="checkbox" class="h-4 w-4 rounded border" bind:checked={addressForm.is_primary} /><span>Domicilio principal</span></label>
					<div class="flex justify-end gap-2 sm:col-span-2"><Button type="button" variant="outline" onclick={() => (activeModal = null)}>Cancelar</Button><Button type="submit" disabled={saving}>Guardar</Button></div>
				</form>
			{:else if activeModal === 'contact'}
				<h3 class="mb-4 text-base font-semibold">{editingId ? 'Editar contacto' : 'Nuevo contacto'}</h3>
				<form class="grid gap-3 sm:grid-cols-2" onsubmit={saveContact}>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Nombre *</span><input class={inputCls} bind:value={contactForm.first_name} required /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Apellidos</span><input class={inputCls} bind:value={contactForm.last_name} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Puesto</span><input class={inputCls} bind:value={contactForm.job_title} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Área / Departamento</span><select class={inputCls} bind:value={contactForm.area}><option value={undefined}>—</option>{#each crmCatalogs.options('area') as a (a.value)}<option value={a.value}>{a.label}</option>{/each}</select></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Email</span><input type="email" class={inputCls} bind:value={contactForm.email} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Teléfono</span><input class={inputCls} bind:value={contactForm.phone} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Extensión</span><input class={inputCls} bind:value={contactForm.extension} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Celular</span><input class={inputCls} bind:value={contactForm.mobile} /></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">WhatsApp</span><input class={inputCls} bind:value={contactForm.whatsapp} /></label>
					<div class="flex flex-col gap-1 sm:col-span-2">
						<label class="flex items-center gap-2 text-sm"><input type="checkbox" class="h-4 w-4 rounded border" bind:checked={contactForm.is_primary} /><span>Contacto principal</span></label>
						<label class="flex items-center gap-2 text-sm"><input type="checkbox" class="h-4 w-4 rounded border" bind:checked={contactForm.receives_quotes} /><span>Recibe cotizaciones</span></label>
						<label class="flex items-center gap-2 text-sm"><input type="checkbox" class="h-4 w-4 rounded border" bind:checked={contactForm.receives_invoices} /><span>Recibe facturas</span></label>
						<label class="flex items-center gap-2 text-sm"><input type="checkbox" class="h-4 w-4 rounded border" bind:checked={contactForm.receives_commercial_info} /><span>Recibe información comercial</span></label>
					</div>
					<div class="flex justify-end gap-2 sm:col-span-2"><Button type="button" variant="outline" onclick={() => (activeModal = null)}>Cancelar</Button><Button type="submit" disabled={saving}>Guardar</Button></div>
				</form>
			{:else if activeModal === 'document'}
				<h3 class="mb-4 text-base font-semibold">{editingId ? 'Editar documento' : 'Nuevo documento'}</h3>
				<form class="grid gap-3" onsubmit={saveDocument}>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Tipo</span><select class={inputCls} bind:value={documentForm.doc_type}>{#each DOC_TYPES as t (t.value)}<option value={t.value}>{t.label}</option>{/each}</select></label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">Nombre *</span><input class={inputCls} bind:value={documentForm.name} required /></label>
					<label class="flex flex-col gap-1 text-sm">
						<span class="font-medium">Archivo {#if uploading}<span class="text-xs text-muted-foreground">(subiendo…)</span>{:else if documentForm.file_key}<span class="text-xs text-emerald-600">(cargado)</span>{/if}</span>
						<input type="file" class={inputCls} onchange={onFilePicked} />
					</label>
					<label class="flex flex-col gap-1 text-sm"><span class="font-medium">o URL externa</span><input class={inputCls} bind:value={documentForm.file_url} placeholder="https://…" /></label>
					<div class="flex justify-end gap-2"><Button type="button" variant="outline" onclick={() => (activeModal = null)}>Cancelar</Button><Button type="submit" disabled={saving}>Guardar</Button></div>
				</form>
			{/if}
		</div>
	</div>
{/if}
