<script>
  // Mini family genealogy map. People here are lightweight records (nf_people)
  // independent of login accounts — most real tree nodes (grandparents,
  // deceased relatives, young children) never sign up. Relationships are
  // parent_of (directional) and spouse_of (symmetric, queried both ways).
  import { onMount } from 'svelte';
  import { activeFamilyId } from './family.js';
  import { currentUser } from './auth.js';
  import {
    listPeople, addPerson, updatePerson, removePerson,
    uploadPersonPhoto, removePersonPhoto, getPersonPhotoUrl,
    listRelationships, addRelationship, removeRelationship, getMemorialSadaqahCount
  } from './db.js';
  import { requestedTab } from './nav.js';
  import InfoPanel from './InfoPanel.svelte';
  import Disclaimer from './Disclaimer.svelte';

  let familyId = $state(null);
  activeFamilyId.subscribe(v => familyId = v);

  let people = $state([]);
  let relationships = $state([]);
  let photoUrls = $state({}); // personId -> signed url
  let memorialCounts = $state({}); // personId -> count
  let error = $state('');

  let form = $state({ fullName: '', gender: '', birthDate: '', deathDate: '', notes: '' });
  let editingId = $state(null);

  let relForm = $state({ personAId: '', personBId: '', type: 'parent_of' });

  let uploadingFor = $state(null);
  let expandedId = $state(null);

  async function refresh() {
    if (!familyId) return;
    people = await listPeople(familyId);
    relationships = await listRelationships(familyId);
    // Refresh signed URLs for anyone with a photo — private bucket, so these expire.
    const entries = await Promise.all(
      people.filter(p => p.photoPath).map(async p => [p.id, await getPersonPhotoUrl(p.photoPath)])
    );
    photoUrls = Object.fromEntries(entries);
    const memorialEntries = await Promise.all(
      people.filter(p => p.deathDate).map(async p => [p.id, await getMemorialSadaqahCount(p.id)])
    );
    memorialCounts = Object.fromEntries(memorialEntries);
  }

  function giveInMemory() {
    requestedTab.set('Sadaqah');
  }

  onMount(refresh);
  $effect(() => { familyId; refresh(); });

  function emptyForm() {
    return { fullName: '', gender: '', birthDate: '', deathDate: '', notes: '' };
  }

  async function savePerson() {
    error = '';
    if (!form.fullName) return;
    try {
      if (editingId) {
        await updatePerson(editingId, form);
        editingId = null;
      } else {
        await addPerson(familyId, currentUser()?.id, form);
      }
      form = emptyForm();
      await refresh();
    } catch (e) { error = e.message; }
  }

  function startEdit(p) {
    editingId = p.id;
    form = { fullName: p.fullName, gender: p.gender || '', birthDate: p.birthDate || '', deathDate: p.deathDate || '', notes: p.notes || '' };
  }

  function cancelEdit() {
    editingId = null;
    form = emptyForm();
  }

  async function deletePerson(id) {
    if (!confirm('Remove this person and all their recorded relationships? This cannot be undone.')) return;
    await removePerson(id);
    await refresh();
  }

  async function handlePhotoChange(e, personId) {
    const file = e.target.files?.[0];
    if (!file) return;
    uploadingFor = personId;
    error = '';
    try {
      await uploadPersonPhoto(familyId, personId, file);
      await refresh();
    } catch (err) {
      error = 'Photo upload failed: ' + err.message;
    } finally {
      uploadingFor = null;
      e.target.value = '';
    }
  }

  async function handlePhotoRemove(person) {
    await removePersonPhoto(person.id, person.photoPath);
    await refresh();
  }

  async function addRel() {
    error = '';
    if (!relForm.personAId || !relForm.personBId || relForm.personAId === relForm.personBId) {
      error = 'Pick two different people.';
      return;
    }
    try {
      await addRelationship(familyId, relForm.personAId, relForm.personBId, relForm.type);
      relForm = { personAId: '', personBId: '', type: 'parent_of' };
      await refresh();
    } catch (e) { error = e.message; }
  }

  async function delRel(id) {
    await removeRelationship(id);
    await refresh();
  }

  function personName(id) {
    return people.find(p => p.id === id)?.fullName || '(removed)';
  }

  // Build a simple generational tree: roots = people with no recorded parent.
  // Each node's children = people this person is parent_of. Spouses shown
  // alongside their partner rather than as separate tree branches.
  const childrenOf = $derived.by(() => {
    const map = {};
    for (const r of relationships.filter(r => r.type === 'parent_of')) {
      (map[r.personAId] ??= []).push(r.personBId);
    }
    return map;
  });
  const spousesOf = $derived.by(() => {
    const map = {};
    for (const r of relationships.filter(r => r.type === 'spouse_of')) {
      (map[r.personAId] ??= []).push(r.personBId);
      (map[r.personBId] ??= []).push(r.personAId);
    }
    return map;
  });
  const hasParent = $derived(new Set(relationships.filter(r => r.type === 'parent_of').map(r => r.personBId)));
  const roots = $derived(people.filter(p => !hasParent.has(p.id)));

  function toggleExpand(id) {
    expandedId = expandedId === id ? null : id;
  }
</script>

<div class="module">
  <div class="module-header">
    <h2>Family Tree</h2>
    <InfoPanel
      title="Family Tree"
      what="A simple map of your family — parents, children, spouses, and a photo for each person. Includes anyone: grandparents, relatives who've passed away, children too young for their own account. Nobody here needs to sign in."
      how="Add a person, then link them to others as a parent/child or spouse using the relationship form. The tree below groups people by generation automatically, starting from anyone with no parent recorded."
      fields={[
        { label: 'Full name', hint: 'The only required field.' },
        { label: 'Birth / death date', hint: 'Optional — leave blank if unknown.' },
        { label: 'Photo', hint: 'Upload after adding the person — tap their card to expand it.' },
        { label: 'Relationships', hint: 'Parent of (directional) or Spouse of (mutual) — pick two people and a type.' }
      ]}
    />
  </div>
  <p class="sub">Shared family knowledge — any family member can view and edit this map.</p>

  {#if error}<p class="error-text">{error}</p>{/if}

  <div class="form-card">
    <h3>{editingId ? 'Edit person' : 'Add a person'}</h3>
    <label class="field"><span>Full name</span><input type="text" bind:value={form.fullName} /></label>
    <label class="field"><span>Gender</span>
      <select bind:value={form.gender}>
        <option value="">Unspecified</option>
        <option value="male">Male</option>
        <option value="female">Female</option>
      </select>
    </label>
    <label class="field"><span>Birth date</span><input type="date" bind:value={form.birthDate} /></label>
    <label class="field"><span>Death date (if applicable)</span><input type="date" bind:value={form.deathDate} /></label>
    <label class="field"><span>Notes</span><input type="text" bind:value={form.notes} placeholder="e.g. maiden name, place of origin" /></label>
    <div class="btn-row">
      <button class="btn-primary" onclick={savePerson}>{editingId ? 'Save changes' : 'Add person'}</button>
      {#if editingId}<button class="btn-secondary" onclick={cancelEdit}>Cancel</button>{/if}
    </div>
  </div>

  {#if people.length >= 2}
    <div class="form-card">
      <h3>Add a relationship</h3>
      <label class="field"><span>Person</span>
        <select bind:value={relForm.personAId}>
          <option value="">Select…</option>
          {#each people as p}<option value={p.id}>{p.fullName}</option>{/each}
        </select>
      </label>
      <label class="field"><span>Relationship</span>
        <select bind:value={relForm.type}>
          <option value="parent_of">is parent of</option>
          <option value="spouse_of">is spouse of</option>
        </select>
      </label>
      <label class="field"><span>{relForm.type === 'parent_of' ? 'Child' : 'Spouse'}</span>
        <select bind:value={relForm.personBId}>
          <option value="">Select…</option>
          {#each people as p}<option value={p.id}>{p.fullName}</option>{/each}
        </select>
      </label>
      <button class="btn-primary" onclick={addRel}>Add relationship</button>
    </div>
  {/if}

  <div class="tree-section">
    <h3>Tree</h3>
    {#if roots.length === 0}
      <p class="empty">Add people and relationships above to build the tree.</p>
    {/if}
    {#each roots as root (root.id)}
      {@render personNode(root, 0)}
    {/each}
  </div>

  <div class="all-people-section">
    <h3>All people</h3>
    {#each people as p (p.id)}
      <div class="person-card">
        <button class="person-summary" onclick={() => toggleExpand(p.id)}>
          {#if photoUrls[p.id]}
            <img class="avatar" src={photoUrls[p.id]} alt={p.fullName} />
          {:else}
            <div class="avatar avatar-placeholder">{p.fullName.charAt(0).toUpperCase()}</div>
          {/if}
          <div class="person-info">
            <strong>{p.fullName}</strong>
            <span class="muted">{[p.birthDate, p.deathDate].filter(Boolean).join(' – ') || 'dates unknown'}</span>
          </div>
        </button>
        {#if expandedId === p.id}
          <div class="person-detail">
            {#if p.notes}<p class="notes">{p.notes}</p>{/if}
            {#if p.deathDate}
              <div class="memorial-row">
                {#if memorialCounts[p.id] > 0}
                  <span class="memorial-count">{memorialCounts[p.id]} sadaqah given in their memory</span>
                {/if}
                <button class="btn-small" onclick={giveInMemory}>Give sadaqah in memory of {p.fullName}</button>
              </div>
            {/if}
            <div class="photo-controls">
              <label class="upload-btn">
                {uploadingFor === p.id ? 'Uploading…' : (photoUrls[p.id] ? 'Replace photo' : 'Upload photo')}
                <input type="file" accept="image/*" onchange={(e) => handlePhotoChange(e, p.id)} disabled={uploadingFor === p.id} />
              </label>
              {#if photoUrls[p.id]}<button class="btn-small-danger" onclick={() => handlePhotoRemove(p)}>Remove photo</button>{/if}
            </div>
            <div class="btn-row">
              <button class="btn-small" onclick={() => startEdit(p)}>Edit</button>
              <button class="btn-small-danger" onclick={() => deletePerson(p.id)}>Delete</button>
            </div>
          </div>
        {/if}
      </div>
    {:else}
      <p class="empty">No one added yet.</p>
    {/each}
  </div>

  <div class="relationships-section">
    <h3>Relationships</h3>
    {#each relationships as r (r.id)}
      <div class="rel-row">
        <span>{personName(r.personAId)} {r.type === 'parent_of' ? 'is parent of' : 'is spouse of'} {personName(r.personBId)}</span>
        <button onclick={() => delRel(r.id)}>✕</button>
      </div>
    {:else}
      <p class="empty">No relationships recorded yet.</p>
    {/each}
  </div>

  <Disclaimer text="This tree is informational family knowledge — it is not itself a Faraid heir determination. Use the Faraid Calculator for that." />
</div>

{#snippet personNode(person, depth)}
  <div class="tree-node" style="margin-left: {depth * 20}px">
    <div class="tree-person">
      {#if photoUrls[person.id]}
        <img class="avatar avatar-sm" src={photoUrls[person.id]} alt={person.fullName} />
      {:else}
        <div class="avatar avatar-sm avatar-placeholder">{person.fullName.charAt(0).toUpperCase()}</div>
      {/if}
      <span>{person.fullName}</span>
      {#each (spousesOf[person.id] || []) as spouseId}
        <span class="spouse-tag">⚭ {personName(spouseId)}</span>
      {/each}
    </div>
    {#each (childrenOf[person.id] || []) as childId}
      {@const child = people.find(p => p.id === childId)}
      {#if child}
        {@render personNode(child, depth + 1)}
      {/if}
    {/each}
  </div>
{/snippet}

<style>
  .module { padding: 4px 0 40px; }
  .module-header { display: flex; align-items: center; margin-bottom: 4px; }
  h2 { font-family: 'DM Serif Display', serif; font-size: 24px; color: #E8E4DC; margin-bottom: 0; }
  h3 { font-size: 14px; color: #C9A84C; margin-bottom: 10px; }
  .sub { font-size: 13px; color: #8A8478; margin-bottom: 16px; }
  .error-text { color: #EF4444; font-size: 12.5px; margin-bottom: 12px; }
  .form-card { background: rgba(255,255,255,0.03); border-radius: 12px; padding: 14px; margin-bottom: 16px; }
  .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
  .field span { font-size: 12px; color: #B8B2A6; }
  .field input, .field select { background: rgba(255,255,255,0.05); border: 1px solid rgba(201,168,76,0.2); border-radius: 8px; padding: 10px 12px; color: #E8E4DC; font-size: 14px; width: 100%; }
  .btn-row { display: flex; gap: 8px; }
  .btn-primary { flex: 1; padding: 12px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; background: #C9A84C; color: #070A0D; }
  .btn-secondary { padding: 12px; border-radius: 8px; border: none; background: rgba(255,255,255,0.08); color: #E8E4DC; cursor: pointer; }
  .btn-small { background: rgba(255,255,255,0.08); color: #E8E4DC; border: none; border-radius: 8px; padding: 8px 12px; font-size: 12px; cursor: pointer; }
  .btn-small-danger { background: rgba(239,68,68,0.1); color: #EF4444; border: none; border-radius: 8px; padding: 8px 12px; font-size: 12px; cursor: pointer; }

  .tree-section, .all-people-section, .relationships-section { margin-bottom: 20px; }
  .tree-node { padding: 6px 0; border-left: 1px solid rgba(201,168,76,0.15); padding-left: 10px; }
  .tree-person { display: flex; align-items: center; gap: 8px; font-size: 13px; color: #E8E4DC; }
  .spouse-tag { font-size: 11px; color: #8A8478; }
  .empty { font-size: 13px; color: #8A8478; text-align: center; padding: 16px 0; }

  .person-card { background: rgba(255,255,255,0.03); border-radius: 12px; margin-bottom: 8px; overflow: hidden; }
  .person-summary { display: flex; align-items: center; gap: 10px; width: 100%; padding: 10px; background: none; border: none; cursor: pointer; text-align: left; }
  .avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
  .avatar-sm { width: 24px; height: 24px; }
  .avatar-placeholder { display: flex; align-items: center; justify-content: center; background: rgba(201,168,76,0.15); color: #C9A84C; font-weight: 700; font-size: 15px; }
  .person-info { display: flex; flex-direction: column; gap: 2px; }
  .person-info strong { color: #E8E4DC; font-size: 13.5px; }
  .muted { color: #8A8478; font-size: 11px; }
  .person-detail { padding: 0 12px 12px; }
  .notes { font-size: 12px; color: #B8B2A6; margin-bottom: 10px; }
  .memorial-row { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
  .memorial-count { font-size: 11px; color: #C9A84C; }
  .photo-controls { display: flex; gap: 8px; margin-bottom: 10px; align-items: center; }
  .upload-btn { position: relative; background: rgba(201,168,76,0.15); color: #C9A84C; border-radius: 8px; padding: 8px 12px; font-size: 12px; cursor: pointer; font-weight: 600; }
  .upload-btn input[type=file] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

  .rel-row { display: flex; justify-content: space-between; padding: 8px 0; font-size: 12.5px; color: #E8E4DC; border-bottom: 1px solid rgba(255,255,255,0.06); }
  .rel-row button { background: none; border: none; color: #8A8478; cursor: pointer; }
</style>
