import { Fragment } from 'react'
import type { Metadata } from 'next'

import { PermissionGate } from '@/components/console/permission-gate'
import {
  Badge,
  PageHeader,
  Panel,
  PanelBody,
  PanelHeader,
  StatCard,
} from '@/components/ui/display'
import { getCurrentUser } from '@/lib/auth/current-user'
import { prisma } from '@/lib/db'
import { getI18n, localised } from '@/lib/i18n/server'
import { formatNumber } from '@/lib/i18n/translate'

export const metadata: Metadata = { title: 'Roles & permissions' }
export const dynamic = 'force-dynamic'

/**
 * The permission matrix (§34).
 *
 * Shown in full rather than summarised, because the value of publishing an access model
 * is that someone can check it. The note under the table says plainly that this view is
 * documentation — the enforcement happens server-side on every request.
 */
export default async function RolesPage() {
  const user = await getCurrentUser()
  const { t, locale } = await getI18n()

  if (!user?.permissions.has('roles.read')) return <PermissionGate />

  const [roles, permissions] = await Promise.all([
    prisma.role.findMany({
      orderBy: { level: 'desc' },
      include: {
        permissions: { select: { permission: { select: { key: true } } } },
        _count: { select: { users: true } },
      },
    }),
    prisma.permission.findMany({ orderBy: [{ resource: 'asc' }, { key: 'asc' }] }),
  ])

  const grantedByRole = new Map(
    roles.map((role) => [role.id, new Set(role.permissions.map((link) => link.permission.key))]),
  )

  const byResource = permissions.reduce<Record<string, typeof permissions>>(
    (accumulator, permission) => {
      const bucket = accumulator[permission.resource] ?? []
      bucket.push(permission)
      accumulator[permission.resource] = bucket
      return accumulator
    },
    {},
  )

  return (
    <>
      <PageHeader title={t('roles.title')} subtitle={t('roles.subtitle')} />

      <div className="grid gap-3 sm:grid-cols-3">
        <StatCard label={t('roles.title')} value={formatNumber(locale, roles.length)} />
        <StatCard label={t('roles.permission')} value={formatNumber(locale, permissions.length)} />
        <StatCard
          label={t('users.title')}
          value={formatNumber(locale, roles.reduce((sum, role) => sum + role._count.users, 0))}
        />
      </div>

      <div className="mt-6 grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
        {roles.map((role) => (
          <Panel key={role.id} className="p-4">
            <div className="flex items-start justify-between gap-2">
              <h2 className="text-sm font-semibold text-text">{localised(role, 'name', locale)}</h2>
              <Badge tone="muted">{role.level}</Badge>
            </div>
            <p className="mt-1.5 text-xs leading-relaxed text-text-muted">
              {localised(role, 'description', locale)}
            </p>
            <div className="mt-3 flex flex-wrap gap-2">
              <Badge tone="brand">
                {t('roles.permissionCount', { count: role.permissions.length })}
              </Badge>
              <Badge tone="info">{t('roles.userCount', { count: role._count.users })}</Badge>
            </div>
          </Panel>
        ))}
      </div>

      <Panel className="mt-6">
        <PanelHeader title={t('roles.title')} subtitle={t('roles.matrixNote')} />
        <PanelBody>
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <caption className="sr-only">{t('roles.title')}</caption>
              <thead>
                <tr className="border-b border-border">
                  <th
                    scope="col"
                    className="sticky start-0 bg-surface px-3 py-2 text-start text-[11px] font-semibold uppercase tracking-wide text-text-faint"
                  >
                    {t('roles.permission')}
                  </th>
                  {roles.map((role) => (
                    <th
                      key={role.id}
                      scope="col"
                      className="px-2 py-2 text-center text-[10px] font-semibold uppercase tracking-wide text-text-faint"
                    >
                      <span className="block max-w-20 truncate" title={localised(role, 'name', locale)}>
                        {localised(role, 'name', locale)}
                      </span>
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {Object.entries(byResource).map(([resource, items]) => (
                  <Fragment key={resource}>
                    <tr className="bg-surface-2/40">
                      <th
                        scope="rowgroup"
                        colSpan={roles.length + 1}
                        className="px-3 py-1.5 text-start text-[10px] font-semibold uppercase tracking-[0.14em] text-brand"
                      >
                        {resource}
                      </th>
                    </tr>
                    {items.map((permission) => (
                      <tr key={permission.id} className="border-b border-border/50">
                        <th
                          scope="row"
                          className="sticky start-0 bg-surface px-3 py-2 text-start font-normal"
                        >
                          <span className="block font-mono text-[11px] text-text">
                            {permission.key}
                          </span>
                          <span className="block text-[10px] text-text-faint">
                            {localised(permission, 'description', locale)}
                          </span>
                        </th>
                        {roles.map((role) => {
                          const granted = grantedByRole.get(role.id)?.has(permission.key) ?? false
                          return (
                            <td key={role.id} className="px-2 py-2 text-center">
                              <span
                                aria-label={
                                  granted ? t('roles.granted') : t('roles.notGranted')
                                }
                                title={granted ? t('roles.granted') : t('roles.notGranted')}
                                className={
                                  granted
                                    ? 'inline-block size-2.5 rounded-full bg-brand'
                                    : 'inline-block size-2.5 rounded-full border border-border-strong'
                                }
                              />
                            </td>
                          )
                        })}
                      </tr>
                    ))}
                  </Fragment>
                ))}
              </tbody>
            </table>
          </div>

          <p className="mt-4 rounded-lg border border-border bg-surface-2/40 px-3.5 py-3 text-xs leading-relaxed text-text-muted">
            {t('roles.matrixNote')}
          </p>
        </PanelBody>
      </Panel>
    </>
  )
}
