<script lang="ts" setup>
  import { onMounted, reactive, ref } from 'vue'
  import { useRoute, useRouter } from 'vue-router'
  import { auth } from '@/auth'

  interface Field {
    id: number
    name: string
    identifier: string
    type: string
    relationshipType?: 'ONE_TO_ONE' | 'ONE_TO_MANY'
  }
  interface LinkedEntity {
    entity: { id: number, name: string, identifier: string, fields: Field[] }
    relationshipField: Field
    records: Record<string, unknown>[]
  }
  interface UserFile {
    user: { id: number, username: string, role: string }
    linkedEntities: LinkedEntity[]
  }

  const route = useRoute()
  const router = useRouter()
  const file = ref<UserFile>()
  const loading = ref(true)
  const errorMessage = ref('')
  const saving = ref(false)
  const addingChildKey = ref('')
  const childValues = reactive<Record<string, Record<string, string | boolean>>>({})

  function childKey (linked: LinkedEntity) {
    return `${linked.entity.id}-${linked.relationshipField.id}`
  }

  function editableFields (linked: LinkedEntity) {
    return linked.entity.fields.filter(field => field.id !== linked.relationshipField.id)
  }

  function isOneToOne (linked: LinkedEntity) {
    return linked.relationshipField.relationshipType === 'ONE_TO_ONE'
  }

  function createLabel (linked: LinkedEntity) {
    return `${isOneToOne(linked) ? 'Create' : 'Add'} ${linked.entity.name}`
  }

  function inputType (field: Field) {
    if (['NUMBER', 'RELATIONSHIP', 'USER'].includes(field.type)) return 'number'
    if (field.type === 'DATE') return 'date'
    if (field.type === 'EMAIL') return 'email'
    if (field.type === 'PHONE') return 'tel'
    return 'text'
  }

  function startAddingChild (linked: LinkedEntity) {
    const key = childKey(linked)
    childValues[key] = {}
    for (const field of editableFields(linked)) {
      childValues[key][field.identifier] = field.type === 'BOOLEAN' ? false : ''
    }
    addingChildKey.value = key
    errorMessage.value = ''
  }

  async function addChild (linked: LinkedEntity) {
    const key = childKey(linked)
    const body = new URLSearchParams()
    for (const field of editableFields(linked)) {
      body.set(field.identifier, String(childValues[key][field.identifier] ?? ''))
    }
    saving.value = true
    errorMessage.value = ''
    try {
      const response = await fetch(
        `/api/users/${route.params.userId}/children/${encodeURIComponent(linked.entity.name)}/${linked.relationshipField.id}`,
        {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${auth.token}`,
            'Content-Type': 'application/x-www-form-urlencoded',
          },
          body,
        },
      )
      if (!response.ok) throw new Error('Child create failed')
      const created = await response.json() as { values: Record<string, unknown> }
      linked.records.push(created.values)
      addingChildKey.value = ''
    } catch {
      errorMessage.value = `The ${linked.entity.name} could not be added. Check the field values and try again.`
    } finally {
      saving.value = false
    }
  }

  function displayValue (value: unknown) {
    if ([null, undefined, ''].includes(value as null | undefined | string)) return '—'
    if (typeof value === 'boolean') return value ? 'Yes' : 'No'
    return String(value)
  }

  onMounted(async () => {
    try {
      const response = await fetch(`/api/users/${route.params.userId}/file`, {
        headers: { Authorization: `Bearer ${auth.token}` },
      })
      if (response.status === 404) {
        await router.replace('/users')
        return
      }
      if (!response.ok) throw new Error('User file request failed')
      file.value = await response.json() as UserFile
    } catch {
      errorMessage.value = 'Unable to load this user file.'
    } finally {
      loading.value = false
    }
  })
</script>

<template>
  <section class="user-file-page">
    <router-link class="back-link" to="/users">← User Management</router-link>
    <p v-if="loading">Loading user file…</p>
    <p v-else-if="errorMessage" role="alert">{{ errorMessage }}</p>

    <template v-else-if="file">
      <header>
        <p class="eyebrow">User file</p>

        <div class="title-row">
          <h1>{{ file.user.username }}</h1>
          <span class="role-badge">{{ file.user.role }}</span>
        </div>

        <p>All entity records linked to this user.</p>
      </header>

      <p v-if="file.linkedEntities.length === 0" class="empty-state">
        No entities with user references are configured.
      </p>

      <article v-for="linked in file.linkedEntities" :key="childKey(linked)" class="entity-card">
        <div class="entity-heading">
          <div>
            <h2>{{ linked.entity.name }}</h2>
            <p v-if="isOneToOne(linked)">{{ linked.records.length === 0 ? 'Not created' : 'Created' }}</p>
            <p v-else>{{ linked.records.length }} linked {{ linked.records.length === 1 ? 'record' : 'records' }}</p>
          </div>

          <button
            v-if="!isOneToOne(linked) || linked.records.length === 0"
            type="button"
            @click="startAddingChild(linked)"
          >
            {{ createLabel(linked) }}
          </button>
        </div>

        <form
          v-if="addingChildKey === childKey(linked)"
          :aria-label="createLabel(linked)"
          class="child-form"
          @submit.prevent="addChild(linked)"
        >
          <label v-for="field in editableFields(linked)" :key="field.id">
            <span>{{ field.name }}</span>

            <input v-if="field.type === 'BOOLEAN'" v-model="childValues[childKey(linked)][field.identifier]" type="checkbox">

            <input v-else v-model="childValues[childKey(linked)][field.identifier]" :type="inputType(field)">
          </label>

          <div class="form-actions">
            <button :disabled="saving" type="submit">{{ saving ? 'Saving…' : createLabel(linked) }}</button>
            <button :disabled="saving" type="button" @click="addingChildKey = ''">Cancel</button>
          </div>
        </form>

        <p v-if="linked.records.length === 0" class="no-records">
          {{ isOneToOne(linked) ? `No ${linked.entity.name} has been created.` : 'No records linked to this user.' }}
        </p>

        <dl v-else-if="isOneToOne(linked)" class="record-details">
          <template v-for="field in linked.entity.fields" :key="field.id">
            <dt>{{ field.name }}</dt>
            <dd>{{ displayValue(linked.records[0][field.identifier]) }}</dd>
          </template>
        </dl>

        <div v-else class="table-scroll">
          <table>
            <thead>
              <tr>
                <th>ID</th>
                <th v-for="field in linked.entity.fields" :key="field.id">{{ field.name }}</th>
                <th><span class="sr-only">Actions</span></th>
              </tr>
            </thead>

            <tbody>
              <tr v-for="record in linked.records" :key="String(record.id)">
                <td>{{ displayValue(record.id) }}</td>

                <td v-for="field in linked.entity.fields" :key="field.id">
                  {{ displayValue(record[field.identifier]) }}
                </td>

                <td>
                  <router-link
                    :aria-label="`View ${linked.entity.name} record ${record.id}`"
                    class="view-link"
                    :to="`/users/${file.user.id}/entities/${encodeURIComponent(linked.entity.name)}/records/${record.id}`"
                  >
                    View
                  </router-link>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </article>
    </template>
  </section>
</template>

<style scoped>
  .user-file-page { width: 100%; max-width: 78rem; }
  .back-link, .view-link { color: var(--v0-primary); font-weight: 700; text-decoration: none; }
  .back-link:hover, .view-link:hover { text-decoration: underline; }
  header { margin: 1.5rem 0 2rem; }
  .eyebrow { margin: 0 0 0.5rem; color: var(--v0-primary); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
  .title-row { display: flex; align-items: center; gap: 0.8rem; }
  h1, h2 { margin: 0; letter-spacing: -0.03em; }
  h1 { font-size: 2rem; }
  h2 { font-size: 1.25rem; }
  header > p:last-child, .entity-heading p { color: var(--v0-on-surface-variant); }
  .role-badge { padding: 0.25rem 0.6rem; border-radius: 999px; color: var(--v0-primary); background: color-mix(in srgb, var(--v0-primary) 14%, transparent); font-size: 0.8rem; font-weight: 700; }
  .entity-card, .empty-state { margin-bottom: 1.25rem; overflow: hidden; border: 1px solid var(--v0-divider); border-radius: 1rem; background: var(--v0-surface); }
  .entity-heading { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.25rem; border-bottom: 1px solid var(--v0-divider); }
  .entity-heading p { margin: 0.35rem 0 0; font-size: 0.9rem; }
  .empty-state, .no-records { padding: 1.5rem; }
  .table-scroll { overflow-x: auto; }
  .record-details { display: grid; grid-template-columns: minmax(8rem, 12rem) 1fr; margin: 0; padding: 1.25rem; gap: 0.75rem 1rem; }
  .record-details dt { color: var(--v0-on-surface-variant); font-size: 0.8rem; font-weight: 700; text-transform: uppercase; }
  .record-details dd { margin: 0; }
  table { width: 100%; border-collapse: collapse; text-align: left; white-space: nowrap; }
  th, td { padding: 0.85rem 1rem; border-bottom: 1px solid var(--v0-divider); }
  th { color: var(--v0-on-surface-variant); font-size: 0.75rem; text-transform: uppercase; }
  tbody tr:last-child td { border-bottom: 0; }
  button { padding: 0.65rem 0.9rem; border: 1px solid var(--v0-divider); border-radius: 0.6rem; color: inherit; background: var(--v0-surface); font: inherit; font-weight: 700; cursor: pointer; }
  button[type="submit"] { color: var(--v0-on-primary); border-color: var(--v0-primary); background: var(--v0-primary); }
  button:disabled { opacity: 0.55; cursor: wait; }
  .child-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 1rem; padding: 1.25rem; border-bottom: 1px solid var(--v0-divider); }
  .child-form label { display: grid; gap: 0.45rem; }
  .child-form label > span { color: var(--v0-on-surface-variant); font-size: 0.8rem; font-weight: 700; text-transform: uppercase; }
  input { width: 100%; padding: 0.65rem 0.75rem; border: 1px solid var(--v0-divider); border-radius: 0.5rem; color: inherit; background: var(--v0-background); font: inherit; }
  input[type="checkbox"] { width: 1.1rem; }
  .form-actions { display: flex; align-items: end; justify-content: flex-end; gap: 0.5rem; }
  .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
</style>
