---
import { Icon } from 'astro-icon/components'
import { actions, isInputError } from 'astro:actions'

import BadgeSmall from '../../../components/BadgeSmall.astro'
import Button from '../../../components/Button.astro'
import InputCardGroup from '../../../components/InputCardGroup.astro'
import InputImageFile from '../../../components/InputImageFile.astro'
import InputSelect from '../../../components/InputSelect.astro'
import InputSubmitButton from '../../../components/InputSubmitButton.astro'
import InputText from '../../../components/InputText.astro'
import InputTextArea from '../../../components/InputTextArea.astro'
import MyPicture from '../../../components/MyPicture.astro'
import TimeFormatted from '../../../components/TimeFormatted.astro'
import { getServiceUserRoleInfo, serviceUserRoles } from '../../../constants/serviceUserRoles'
import BaseLayout from '../../../layouts/BaseLayout.astro'
import { prisma } from '../../../lib/prisma'

const { username } = Astro.params

if (!username) return Astro.rewrite('/404')

const updateResult = Astro.getActionResult(actions.admin.user.update)
Astro.locals.banners.addIfSuccess(updateResult, 'User updated successfully')
if (updateResult && !updateResult.error && username !== updateResult.data.updatedUser.name) {
  return Astro.redirect(`/admin/users/${updateResult.data.updatedUser.name}`)
}
const updateInputErrors = isInputError(updateResult?.error) ? updateResult.error.fields : {}

const addAffiliationResult = Astro.getActionResult(actions.admin.user.serviceAffiliations.add)
Astro.locals.banners.addIfSuccess(addAffiliationResult, 'Service affiliation added successfully')

const removeAffiliationResult = Astro.getActionResult(actions.admin.user.serviceAffiliations.remove)
Astro.locals.banners.addIfSuccess(removeAffiliationResult, 'Service affiliation removed successfully')

const addKarmaTransactionResult = Astro.getActionResult(actions.admin.user.karmaTransactions.add)
Astro.locals.banners.addIfSuccess(addKarmaTransactionResult, 'Karma transaction added successfully')

const [user, allServices] = await Astro.locals.banners.tryMany([
  [
    'Failed to load user profile',
    async () => {
      if (!username) return null

      return await prisma.user.findUnique({
        where: { name: username },
        select: {
          id: true,
          name: true,
          displayName: true,
          picture: true,
          link: true,
          admin: true,
          verified: true,
          verifier: true,
          spammer: true,
          verifiedLink: true,
          internalNotes: {
            select: {
              id: true,
              content: true,
              createdAt: true,
              addedByUser: {
                select: {
                  id: true,
                  name: true,
                  displayName: true,
                  picture: true,
                },
              },
            },
            orderBy: {
              createdAt: 'desc',
            },
          },
          serviceAffiliations: {
            select: {
              id: true,
              role: true,
              createdAt: true,
              service: {
                select: {
                  id: true,
                  name: true,
                  slug: true,
                },
              },
            },
            orderBy: {
              createdAt: 'desc',
            },
          },
        },
      })
    },
    null,
  ],
  [
    'Failed to load services',
    async () => {
      return await prisma.service.findMany({
        select: {
          id: true,
          name: true,
        },
        orderBy: {
          name: 'asc',
        },
      })
    },
    [],
  ],
])

if (!user) return Astro.rewrite('/404')
---

<BaseLayout
  pageTitle={`${user.displayName ?? user.name} - User`}
  widthClassName="max-w-screen-lg"
  className={{ main: 'space-y-24' }}
>
  <div class="mt-12">
    {
      !!user.picture && (
        <MyPicture
          src={user.picture}
          alt=""
          width={80}
          height={80}
          class="mx-auto mb-2 block size-20 rounded-full"
        />
      )
    }
    <h1
      class="font-title mb-2 flex items-center justify-center gap-2 text-center text-3xl leading-none font-bold"
    >
      {user.displayName ? `${user.displayName} (${user.name})` : user.name}
    </h1>

    <div class="mb-4 flex flex-wrap justify-center gap-2">
      {user.admin && <BadgeSmall color="green" text="Admin" icon="ri:shield-star-fill" />}
      {user.verified && <BadgeSmall color="cyan" text="Verified" icon="ri:verified-badge-fill" />}
      {user.verifier && <BadgeSmall color="blue" text="Moderator" icon="ri:graduation-cap-fill" />}
      {user.spammer && <BadgeSmall color="red" text="Spammer" icon="ri:alert-fill" />}
    </div>

    <div class="flex justify-center gap-2">
      <Button
        as="a"
        href={`/u/${user.name}`}
        icon="ri:global-line"
        color="success"
        shadow
        size="sm"
        label="View public profile"
      />
      {
        Astro.locals.user && user.id !== Astro.locals.user.id && !user.admin && (
          <Button
            as="a"
            href={`/account/impersonate?targetUserId=${user.id}&redirect=/account`}
            data-astro-prefetch="tap"
            icon="ri:spy-line"
            color="gray"
            size="sm"
            label="Impersonate"
          />
        )
      }
    </div>
  </div>

  <form
    method="POST"
    action={actions.admin.user.update}
    enctype="multipart/form-data"
    class="space-y-2"
    data-astro-reload
  >
    <h2 class="font-title text-center text-3xl leading-none font-bold">Edit profile</h2>

    <input type="hidden" name="id" value={user.id} />

    <div class="grid grid-cols-2 gap-x-4 gap-y-2">
      <InputText
        label="Name"
        name="name"
        error={updateInputErrors.name}
        inputProps={{ value: user.name, required: true }}
      />

      <InputText
        label="Display Name"
        name="displayName"
        error={updateInputErrors.displayName}
        inputProps={{ value: user.displayName ?? '', maxlength: 50 }}
      />

      <InputText
        label="Link"
        name="link"
        error={updateInputErrors.link}
        inputProps={{ value: user.link ?? '', type: 'url' }}
      />

      <InputText
        label="Verified Link"
        name="verifiedLink"
        error={updateInputErrors.verifiedLink}
        inputProps={{ value: user.verifiedLink, type: 'url' }}
      />
    </div>

    <InputImageFile
      label="Profile Picture Upload"
      name="pictureFile"
      value={user.picture}
      error={updateInputErrors.pictureFile}
      square
      description="Upload a square image for best results. Supported formats: JPG, PNG, WebP, AVIF. Max size: 5MB."
    />

    <InputCardGroup
      name="type"
      label="Type"
      options={[
        { label: 'Admin', value: 'admin', icon: 'ri:shield-star-fill' },
        { label: 'Moderator', value: 'verifier', icon: 'ri:graduation-cap-fill' },
        { label: 'Spammer', value: 'spammer', icon: 'ri:alert-fill' },
        {
          label: 'Verified',
          value: 'verified',
          icon: 'ri:verified-badge-fill',
          disabled: true,
          noTransitionPersist: true,
        },
      ]}
      selectedValue={[
        user.admin ? 'admin' : null,
        user.verified ? 'verified' : null,
        user.verifier ? 'verifier' : null,
        user.spammer ? 'spammer' : null,
      ].filter((v) => v !== null)}
      required
      cardSize="sm"
      iconSize="sm"
      multiple
      error={updateInputErrors.type}
    />

    <InputSubmitButton label="Save" icon="ri:save-line" hideCancel />
  </form>

  <section class="space-y-2">
    <h2 class="font-title text-center text-3xl leading-none font-bold">Internal Notes</h2>

    {
      user.internalNotes.length === 0 ? (
        <p class="text-day-300 text-center">No internal notes yet.</p>
      ) : (
        <div class="space-y-4">
          {user.internalNotes.map((note) => (
            <div data-note-id={note.id} class="border-night-400 bg-night-600 rounded-lg border p-4 shadow-sm">
              <div class="mb-1 flex items-center justify-between gap-4">
                <div class="flex items-center gap-1">
                  {!!note.addedByUser?.picture && (
                    <MyPicture
                      src={note.addedByUser.picture}
                      alt=""
                      width={12}
                      height={12}
                      class="size-6 rounded-full"
                    />
                  )}
                  <span class="text-day-100 font-medium">
                    {/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing */}
                    {note.addedByUser ? note.addedByUser.displayName || note.addedByUser.name : 'System'}
                  </span>
                  <TimeFormatted date={note.createdAt} hourPrecision class="text-day-300 ms-1 text-sm" />
                </div>

                <div class="flex items-center">
                  <label class="text-day-300 hover:text-day-100 cursor-pointer p-1 transition-colors">
                    <input
                      type="checkbox"
                      class="peer sr-only"
                      data-edit-note-checkbox
                      data-note-id={note.id}
                    />
                    <Icon name="ri:edit-line" class="size-5" />
                  </label>

                  <form
                    method="POST"
                    action={actions.admin.user.internalNotes.delete}
                    class="contents"
                    data-astro-reload
                  >
                    <input type="hidden" name="noteId" value={note.id} />
                    <button type="submit" class="text-day-300 p-1 transition-colors hover:text-red-400">
                      <Icon name="ri:delete-bin-line" class="size-5" />
                    </button>
                  </form>
                </div>
              </div>

              <div data-note-content>
                <p class="text-day-200 wrap-anywhere whitespace-pre-wrap" set:text={note.content} />
              </div>

              <form
                method="POST"
                action={actions.admin.user.internalNotes.update}
                data-note-edit-form
                data-astro-reload
                class="mt-4 hidden space-y-4"
              >
                <input type="hidden" name="noteId" value={note.id} />
                <InputTextArea
                  label="Note Content"
                  name="content"
                  value={note.content}
                  inputProps={{ class: 'bg-night-700' }}
                />
                <InputSubmitButton label="Save" icon="ri:save-line" hideCancel />
              </form>
            </div>
          ))}
        </div>
      )
    }

    <form
      method="POST"
      action={actions.admin.user.internalNotes.add}
      class="mt-10 space-y-2"
      data-astro-reload
    >
      <h3 class="font-title mb-0 text-center text-xl leading-none font-bold">Add Note</h3>

      <input type="hidden" name="userId" value={user.id} />
      <InputTextArea
        label="Note Content"
        name="content"
        inputProps={{ placeholder: 'Add a note...', rows: 3 }}
      />
      <InputSubmitButton label="Add" icon="ri:add-line" hideCancel />
    </form>
  </section>

  <section class="space-y-2">
    <h2 class="font-title text-center text-3xl leading-none font-bold">Service Affiliations</h2>

    {
      user.serviceAffiliations.length === 0 ? (
        <p class="text-day-200 text-center">No service affiliations yet.</p>
      ) : (
        <div class="grid grid-cols-2 gap-x-4">
          {user.serviceAffiliations.map((affiliation) => {
            const roleInfo = getServiceUserRoleInfo(affiliation.role)
            return (
              <div class="bg-night-600 border-night-400 flex items-center justify-start gap-2 rounded-lg border px-3 py-2">
                <BadgeSmall color={roleInfo.color} text={roleInfo.label} icon={roleInfo.icon} />
                <span class="text-day-400 text-sm">at</span>
                <a
                  href={`/service/${affiliation.service.slug}`}
                  class="text-day-100 hover:text-day-50 flex items-center gap-1 leading-none font-medium hover:underline"
                >
                  <span>{affiliation.service.name}</span>
                  <Icon name="ri:external-link-line" class="text-day-400 size-3.5" />
                </a>
                <TimeFormatted
                  date={affiliation.createdAt}
                  hourPrecision
                  class="text-day-400 ms-auto me-2 text-sm"
                />

                <form
                  method="POST"
                  action={actions.admin.user.serviceAffiliations.remove}
                  data-astro-reload
                  class="contents"
                >
                  <input type="hidden" name="id" value={affiliation.id} />
                  <button type="submit" class="text-day-300 transition-colors hover:text-red-400">
                    <Icon name="ri:delete-bin-line" class="size-5" />
                  </button>
                </form>
              </div>
            )
          })}
        </div>
      )
    }

    <form
      method="POST"
      action={actions.admin.user.serviceAffiliations.add}
      data-astro-reload
      class="mt-10 space-y-2"
    >
      <h3 class="font-title mb-0 text-center text-xl leading-none font-bold">Add Affiliation</h3>

      <input type="hidden" name="userId" value={user.id} />

      <InputSelect
        name="serviceId"
        label="Service"
        options={allServices.map((service) => ({
          label: service.name,
          value: service.id.toString(),
        }))}
        selectProps={{ required: true }}
      />

      <InputCardGroup
        name="role"
        label="Role"
        options={serviceUserRoles.map((role) => ({
          label: role.label,
          value: role.value,
          icon: role.icon,
        }))}
        required
        cardSize="sm"
        iconSize="sm"
      />

      <InputSubmitButton label="Add Affiliation" icon="ri:link" hideCancel />
    </form>
  </section>

  <form method="POST" action={actions.admin.user.karmaTransactions.add} data-astro-reload class="space-y-2">
    <h2 class="font-title text-center text-3xl leading-none font-bold">Grant/Remove Karma</h2>

    <input type="hidden" name="userId" value={user.id} />

    <InputText
      label="Points"
      name="points"
      error={addKarmaTransactionResult?.error?.message}
      inputProps={{ type: 'number', required: true }}
    />

    <InputTextArea
      label="Description"
      name="description"
      error={addKarmaTransactionResult?.error?.message}
      inputProps={{ required: true }}
    />

    <InputSubmitButton label="Submit" icon="ri:add-line" hideCancel />
  </form>
</BaseLayout>

<script>
  document.addEventListener('astro:page-load', () => {
    document.querySelectorAll<HTMLDivElement>('[data-note-id]').forEach((noteDiv) => {
      const checkbox = noteDiv.querySelector<HTMLInputElement>('input[data-edit-note-checkbox]')
      if (!checkbox) return

      checkbox.addEventListener('change', (e) => {
        const target = e.target as HTMLInputElement
        if (!target) return

        const noteContent = noteDiv.querySelector<HTMLDivElement>('[data-note-content]')
        const editForm = noteDiv.querySelector<HTMLFormElement>('[data-note-edit-form]')

        if (noteContent && editForm) {
          if (target.checked) {
            noteContent.classList.add('hidden')
            editForm.classList.remove('hidden')
          } else {
            noteContent.classList.remove('hidden')
            editForm.classList.add('hidden')
          }
        }
      })
    })
  })
</script>
