---
import { Icon } from 'astro-icon/components'
import { Markdown } from 'astro-remote'
import { z } from 'astro:content'
import { orderBy } from 'lodash-es'

import BadgeStandard from '../components/BadgeStandard.astro'
import MyPicture from '../components/MyPicture.astro'
import SortArrowIcon from '../components/SortArrowIcon.astro'
import { getAttributeCategoryInfo } from '../constants/attributeCategories'
import { getAttributeTypeInfo } from '../constants/attributeTypes'
import { getVerificationStatusInfo } from '../constants/verificationStatus'
import BaseLayout from '../layouts/BaseLayout.astro'
import { sortAttributes } from '../lib/attributes'
import { cn } from '../lib/cn'
import { formatNumber } from '../lib/numbers'
import { makeOverallScoreInfo } from '../lib/overallScore'
import { zodParseQueryParamsStoringErrors } from '../lib/parseUrlFilters'
import { prisma } from '../lib/prisma'

const { data: filters } = zodParseQueryParamsStoringErrors(
  {
    'sort-by': z.enum(['name', 'category', 'type', 'privacy', 'trust']),
    'sort-order': z.enum(['asc', 'desc']).default('asc'),
  },
  Astro
)

const attributes = await Astro.locals.banners.try(
  'Error fetching attributes',
  async () =>
    prisma.attribute.findMany({
      select: {
        id: true,
        slug: true,
        title: true,
        description: true,
        category: true,
        type: true,
        privacyPoints: true,
        trustPoints: true,
        services: {
          select: {
            service: {
              select: {
                id: true,
                slug: true,
                name: true,
                imageUrl: true,
                overallScore: true,
                verificationStatus: true,
              },
            },
          },
        },
      },
    }),
  []
)

const sortBy = filters['sort-by']
const sortedAttributes = sortBy
  ? orderBy(
      sortAttributes(attributes),
      sortBy === 'type'
        ? (attribute) => getAttributeTypeInfo(attribute.type).order
        : sortBy === 'category'
          ? (attribute) => getAttributeCategoryInfo(attribute.category).order
          : sortBy === 'name'
            ? 'title'
            : sortBy === 'privacy'
              ? 'privacyPoints'
              : 'trustPoints',
      filters['sort-order']
    )
  : sortAttributes(attributes)

const attributesWithInfo = sortedAttributes.map((attribute) => ({
  ...attribute,
  categoryInfo: getAttributeCategoryInfo(attribute.category),
  typeInfo: getAttributeTypeInfo(attribute.type),
  services: orderBy(
    attribute.services.map(({ service }) => ({
      ...service,
      verificationStatusInfo: getVerificationStatusInfo(service.verificationStatus),
      overallScoreInfo: makeOverallScoreInfo(service.overallScore),
    })),
    [
      (service) => (service.verificationStatus === 'VERIFICATION_FAILED' ? 1 : -1),
      'overallScore',
      () => Math.random(),
    ],
    ['asc', 'desc', 'asc']
  ),
}))

const makeSortUrl = (slug: NonNullable<(typeof filters)['sort-by']>) => {
  const sortOrder = filters['sort-by'] === slug ? (filters['sort-order'] === 'asc' ? 'desc' : 'asc') : 'asc'
  return `/attributes?sort-by=${slug}&sort-order=${sortOrder}`
}
---

<BaseLayout
  pageTitle="Attributes"
  description="Browse all available service attributes used to evaluate privacy and trust scores."
  ogImage={{
    template: 'generic',
    title: 'All attributes',
    description: 'Browse all available service attributes',
    icon: 'ri:list-radio',
  }}
>
  <h1 class="font-title mb-2 text-center text-3xl font-bold text-white">Service attributes</h1>

  <p class="text-center text-balance text-zinc-300">
    Characteristics or features of services that affect their scores.
  </p>
  <p class="mb-8 text-center">
    <a
      href="/about#service-attributes"
      class="mt-2 inline-flex items-center text-sm text-zinc-400 hover:text-zinc-200"
    >
      <Icon name="ri:information-line" class="mr-1 size-4" />
      Learn more about attributes
    </a>
  </p>

  <!-- Mobile view -->
  <div class="grid grid-cols-1 gap-4 md:hidden">
    {
      attributesWithInfo.map((attribute) => (
        <div class="space-y-2 rounded-lg border border-zinc-600 bg-zinc-800 p-4">
          <div class="flex flex-col items-center space-y-2">
            <h3 class={cn('text-center text-lg font-bold', attribute.typeInfo.classNames.text)}>
              {attribute.title}
            </h3>
            <div class="flex space-x-2">
              <BadgeStandard
                text={attribute.categoryInfo.label}
                icon={attribute.categoryInfo.icon}
                class={attribute.categoryInfo.classNames.icon}
              />
              <BadgeStandard
                text={attribute.typeInfo.label}
                icon={attribute.typeInfo.icon}
                class={attribute.typeInfo.classNames.icon}
              />
            </div>
          </div>

          <div
            class={cn(
              'prose prose-sm prose-invert mx-auto max-w-lg text-sm',
              attribute.typeInfo.classNames.text
            )}
          >
            <Markdown content={attribute.description} />
          </div>

          <div class="grid grid-cols-2 gap-2">
            <div class="flex flex-col items-center text-zinc-200">
              <span
                class={cn('text-base', attribute.typeInfo.classNames.textLight, {
                  'text-red-400': attribute.privacyPoints < 0,
                  'text-green-400': attribute.privacyPoints > 0,
                  'opacity-50': attribute.privacyPoints === 0,
                })}
              >
                {formatNumber(attribute.privacyPoints, { showSign: true })}
              </span>
              <span
                class={cn('text-2xs font-bold text-white uppercase', attribute.typeInfo.classNames.textLight)}
              >
                Privacy
              </span>
            </div>

            <div class="flex flex-col items-center text-zinc-200">
              <span
                class={cn('text-base', attribute.typeInfo.classNames.textLight, {
                  'text-red-400': attribute.trustPoints < 0,
                  'text-green-400': attribute.trustPoints > 0,
                  'opacity-50': attribute.trustPoints === 0,
                })}
              >
                {formatNumber(attribute.trustPoints, { showSign: true })}
              </span>
              <span
                class={cn('text-2xs font-bold text-white uppercase', attribute.typeInfo.classNames.textLight)}
              >
                Trust
              </span>
            </div>
          </div>

          {attribute.services.length > 0 && (
            <details class="pt-2">
              <summary class="flex cursor-pointer items-center text-sm text-zinc-300">
                Show services
                <Icon name="ri:arrow-down-s-line" class="ml-1 size-4" />
              </summary>
              <ul class="mt-2 grid max-h-64 grid-cols-1 overflow-y-auto rounded bg-zinc-700">
                {attribute.services.map((service) => (
                  <li>
                    <a
                      href={`/service/${service.slug}`}
                      class="flex items-center gap-2 rounded-md p-2 transition-colors hover:bg-zinc-800"
                    >
                      {service.imageUrl ? (
                        <MyPicture
                          src={service.imageUrl}
                          alt={service.name}
                          width={24}
                          height={24}
                          class="size-6 shrink-0 rounded-xs object-contain"
                        />
                      ) : (
                        <div class="flex size-6 shrink-0 items-center justify-center rounded-xs bg-zinc-800 text-zinc-500">
                          <Icon name="ri:image-line" class="size-4" />
                        </div>
                      )}

                      <div
                        class={cn(
                          'mt-1 flex-1 truncate text-xs text-zinc-300',
                          service.verificationStatus === 'VERIFICATION_FAILED' && 'text-red-200'
                        )}
                      >
                        {service.name}
                      </div>

                      {service.verificationStatus !== 'APPROVED' && (
                        <Icon
                          name={service.verificationStatusInfo.icon}
                          class={cn(
                            'inline-block size-4 shrink-0',
                            service.verificationStatusInfo.classNames.icon
                          )}
                        />
                      )}

                      <span
                        class={cn(
                          'inline-flex h-5 w-5 items-center justify-center rounded-xs text-xs font-bold',
                          service.overallScoreInfo.classNameBg
                        )}
                      >
                        {service.overallScoreInfo.formattedScore}
                      </span>
                    </a>
                  </li>
                ))}
              </ul>
            </details>
          )}
        </div>
      ))
    }
  </div>

  <!-- Desktop view -->
  <div
    class="-m-2 hidden grid-cols-[minmax(auto,calc(var(--spacing)*64))_auto_auto_1fr_auto_auto_auto] gap-x-4 md:grid"
  >
    <div class="col-span-full grid grid-cols-subgrid p-2">
      <a href={makeSortUrl('name')}>
        Name <SortArrowIcon active={filters['sort-by'] === 'name'} sortOrder={filters['sort-order']} />
      </a>
      <a href={makeSortUrl('category')}>
        Category <SortArrowIcon
          active={filters['sort-by'] === 'category'}
          sortOrder={filters['sort-order']}
        />
      </a>
      <a href={makeSortUrl('type')}>
        Type <SortArrowIcon active={filters['sort-by'] === 'type'} sortOrder={filters['sort-order']} />
      </a>
      <div>Description</div>
      <a href={makeSortUrl('privacy')}>
        Privacy <SortArrowIcon active={filters['sort-by'] === 'privacy'} sortOrder={filters['sort-order']} />
      </a>
      <a href={makeSortUrl('trust')}>
        Trust <SortArrowIcon active={filters['sort-by'] === 'trust'} sortOrder={filters['sort-order']} />
      </a>
      <div></div>
    </div>

    {
      attributesWithInfo.map((attribute) => (
        <div class="group col-span-full grid grid-cols-subgrid hover:bg-zinc-800">
          <input type="checkbox" id={`show-services-${attribute.id}`} class="peer/show-services hidden" />

          <label
            for={`show-services-${attribute.id}`}
            class="col-span-full grid cursor-pointer list-none grid-cols-subgrid items-center rounded-sm p-2 peer-checked/show-services:[&_[data-expand-icon]]:rotate-180"
            aria-label={`Show services for ${attribute.title}`}
          >
            <h3 class={cn('text-lg font-bold', attribute.typeInfo.classNames.text)}>{attribute.title}</h3>

            <BadgeStandard
              text={attribute.categoryInfo.label}
              icon={attribute.categoryInfo.icon}
              class={attribute.categoryInfo.classNames.icon}
            />

            <BadgeStandard
              text={attribute.typeInfo.label}
              icon={attribute.typeInfo.icon}
              class={attribute.typeInfo.classNames.icon}
            />

            <div
              class={cn(
                'prose prose-sm prose-invert text-sm text-pretty',
                attribute.typeInfo.classNames.text
              )}
            >
              <Markdown content={attribute.description} />
            </div>

            <div
              class={cn('text-center text-base', attribute.typeInfo.classNames.text, {
                'text-red-400': attribute.privacyPoints < 0,
                'text-green-400': attribute.privacyPoints > 0,
                'text-zinc-400': attribute.privacyPoints === 0,
              })}
            >
              {formatNumber(attribute.privacyPoints, { showSign: true })}
            </div>

            <div
              class={cn('text-center text-base', attribute.typeInfo.classNames.text, {
                'text-red-400': attribute.trustPoints < 0,
                'text-green-400': attribute.trustPoints > 0,
                'text-zinc-400': attribute.trustPoints === 0,
              })}
            >
              {formatNumber(attribute.trustPoints, { showSign: true })}
            </div>

            <div class="flex items-center justify-center">
              <Icon name="ri:arrow-down-s-line" class="size-6" data-expand-icon />
            </div>
          </label>

          {attribute.services.length > 0 && (
            <div class="col-span-full hidden rounded bg-zinc-700/80 peer-checked/show-services:block">
              <ul class="grid max-h-64 grid-cols-[repeat(auto-fill,minmax(calc(var(--spacing)*64),1fr))] gap-x-4 overflow-y-auto mask-y-from-[calc(100%-var(--spacing)*8)] px-3 py-3">
                {attribute.services.map((service) => (
                  <li>
                    <a
                      href={`/service/${service.slug}`}
                      class="flex items-center gap-2 rounded-md p-2 transition-colors hover:bg-zinc-800"
                    >
                      {service.imageUrl ? (
                        <MyPicture
                          src={service.imageUrl}
                          alt={service.name}
                          width={24}
                          height={24}
                          class="size-6 shrink-0 rounded-xs object-contain"
                        />
                      ) : (
                        <div class="flex size-6 shrink-0 items-center justify-center rounded-xs bg-zinc-800 text-zinc-500">
                          <Icon name="ri:image-line" class="size-4" />
                        </div>
                      )}

                      <div
                        class={cn(
                          'mt-1 flex-1 truncate text-xs text-zinc-300',
                          service.verificationStatus === 'VERIFICATION_FAILED' && 'text-red-200'
                        )}
                      >
                        {service.name}
                      </div>

                      {service.verificationStatus !== 'APPROVED' && (
                        <Icon
                          name={service.verificationStatusInfo.icon}
                          class={cn(
                            'inline-block size-4 shrink-0',
                            service.verificationStatusInfo.classNames.icon
                          )}
                        />
                      )}

                      <span
                        class={cn(
                          'inline-flex h-5 w-5 items-center justify-center rounded-xs text-xs font-bold',
                          service.overallScoreInfo.classNameBg
                        )}
                      >
                        {service.overallScoreInfo.formattedScore}
                      </span>
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>
      ))
    }
  </div>
</BaseLayout>
