import Link from 'next/link'
import { and, asc, desc, eq, isNull, ne, or, sql } from 'drizzle-orm'
import { db } from '@/db'
import { projects, ticketMessages, tickets, users, type TicketStatus } from '@/db/schema'
import { requireExpertUser } from '@/lib/role-guard'
import { loadTenantConfig } from '@/lib/tenant-config-loader'
import { buildInboxTicketTitle } from '@/lib/inbox-ticket-display'
import {
  INBOX_ALL_STATUSES,
  INBOX_ALL_UNRESPONDED_STATUS,
  normalizeInboxStatusFilter,
} from '@/lib/inbox-status-filter'
import { getI18nForUserId } from '@/lib/i18n/server'
import { formatDateTimeInUserZone } from '@/lib/user-time-zone'
import { applyTicketMessageTranslations, applyTicketTranslations } from '@/lib/content-translation-display'
import { getConfigOptionLabel } from '@/lib/config-option-labels'
import InboxEvents from './InboxEvents'
import InboxFilterForm from './InboxFilterForm'

const CONFIG_PATH = process.env.TENANT_CONFIG_PATH ?? './tenant.config.yaml'

const PRIORITY_BADGE_CLASSES: Record<string, string> = {
  critical: 'border-red-300 bg-red-50 text-red-800 dark:border-red-400/40 dark:bg-red-400/10 dark:text-red-200',
  high: 'border-orange-300 bg-orange-50 text-orange-800 dark:border-orange-400/40 dark:bg-orange-400/10 dark:text-orange-200',
  medium: 'border-yellow-300 bg-yellow-50 text-yellow-800 dark:border-yellow-400/40 dark:bg-yellow-400/10 dark:text-yellow-100',
  low: 'border-zinc-300 bg-zinc-50 text-zinc-700 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300',
}

const PRIORITY_SORT_RANK = sql<number>`
  case ${tickets.userPriority}
    when 'critical' then 4
    when 'high' then 3
    when 'medium' then 2
    when 'low' then 1
    else 0
  end
`

function firstParam(value: string | string[] | undefined): string {
  return Array.isArray(value) ? value[0] ?? '' : value ?? ''
}

export default async function InboxPage({
  searchParams,
}: {
  searchParams: Promise<Record<string, string | string[] | undefined>>
}) {
  const expert = await requireExpertUser()
  const i18n = await getI18nForUserId(expert.id)
  const t = i18n.t
  const params = await searchParams
  const selectedProject = firstParam(params.project)
  const selectedCategory = firstParam(params.category)
  const selectedPriority = firstParam(params.priority)
  const selectedStatus = normalizeInboxStatusFilter(firstParam(params.status))
  const selectedSort = firstParam(params.sort) || 'submitted'
  const tenantConfig = loadTenantConfig(CONFIG_PATH)
  const statusLabels: Record<string, string> = {
    SUBMITTED: t('inbox.statusLabels.SUBMITTED'),
    NEEDS_INFO: t('inbox.statusLabels.NEEDS_INFO'),
    TRIAGED: t('inbox.statusLabels.TRIAGED'),
    AWAITING_EXPERT: t('inbox.statusLabels.AWAITING_EXPERT'),
    EXPERT_REVIEWING: t('inbox.statusLabels.EXPERT_REVIEWING'),
    RESPONSE_DRAFTING: t('inbox.statusLabels.RESPONSE_DRAFTING'),
    RESPONSE_READY: t('inbox.statusLabels.RESPONSE_READY'),
    RESPONDED: t('inbox.statusLabels.RESPONDED'),
    CLOSED: t('inbox.statusLabels.CLOSED'),
  }
  const priorityLabels: Record<string, string> = {
    critical: t('priority.critical'),
    high: t('priority.high'),
    medium: t('priority.medium'),
    low: t('priority.low'),
  }

  const [currentUser] = await db
    .select({ timeZone: users.timeZone })
    .from(users)
    .where(eq(users.id, expert.id))
    .limit(1)

  const projectOptions = await db
    .select({ id: projects.id, name: projects.name })
    .from(projects)
    .where(and(eq(projects.tenantId, expert.tenantId), eq(projects.isActive, true)))
    .orderBy(asc(projects.name))

  const filters = [
    eq(tickets.tenantId, expert.tenantId),
    selectedProject ? eq(tickets.projectId, selectedProject) : undefined,
    selectedCategory ? eq(tickets.issueCategory, selectedCategory) : undefined,
    selectedPriority ? eq(tickets.userPriority, selectedPriority as 'critical' | 'high' | 'medium' | 'low') : undefined,
    selectedStatus === INBOX_ALL_UNRESPONDED_STATUS
      ? or(isNull(ticketMessages.role), ne(ticketMessages.role, 'expert'))
      : selectedStatus === INBOX_ALL_STATUSES
        ? undefined
        : eq(tickets.status, selectedStatus as TicketStatus),
  ].filter(Boolean)

  const orderBy =
    selectedSort === 'occurrence'
      ? [asc(tickets.dateOfOccurrence), asc(tickets.createdAt)]
      : selectedSort === 'priority'
        ? [desc(PRIORITY_SORT_RANK), asc(tickets.createdAt)]
        : [asc(tickets.createdAt)]

  const rows = await db
    .select({
      id: tickets.id,
      title: tickets.title,
      referenceNumber: tickets.referenceNumber,
      status: tickets.status,
      createdAt: tickets.createdAt,
      updatedAt: tickets.updatedAt,
      projectName: projects.name,
      department: tickets.department,
      dateOfOccurrence: tickets.dateOfOccurrence,
      issueCategory: tickets.issueCategory,
      affectedSystem: tickets.affectedSystem,
      successCriteria: tickets.successCriteria,
      actionRequested: tickets.actionRequested,
      userPriority: tickets.userPriority,
      submitterName: users.displayName,
      submitterEmail: users.email,
      lastMessageId: ticketMessages.id,
      lastMessageRole: ticketMessages.role,
      lastMessageLanguage: ticketMessages.language,
      lastMessageRaw: ticketMessages.bodyRaw,
      lastMessageSanitized: ticketMessages.bodySanitized,
    })
    .from(tickets)
    .innerJoin(users, eq(users.id, tickets.submitterId))
    .leftJoin(projects, eq(projects.id, tickets.projectId))
    .leftJoin(ticketMessages, eq(ticketMessages.id, tickets.lastMessageId))
    .where(and(...filters))
    .orderBy(...orderBy)

  const localizedRows = await applyTicketTranslations(rows, i18n.language)
  const localizedLastMessages = await applyTicketMessageTranslations(
    rows
      .filter((ticket) => ticket.lastMessageId && ticket.lastMessageLanguage && ticket.lastMessageRaw && ticket.lastMessageSanitized)
      .map((ticket) => ({
        id: ticket.lastMessageId as string,
        language: ticket.lastMessageLanguage as 'en' | 'es',
        bodyRaw: ticket.lastMessageRaw as string,
        bodySanitized: ticket.lastMessageSanitized as string,
      })),
    i18n.language,
  )
  const lastMessageById = new Map(localizedLastMessages.map((message) => [message.id, message.bodySanitized]))

  return (
    <main className="min-h-screen bg-zinc-50 px-4 py-10 text-zinc-950 dark:bg-zinc-950 dark:text-zinc-100">
      <InboxEvents />
      <div className="mx-auto max-w-5xl space-y-6">
        <div className="flex items-end justify-between gap-4">
          <div>
            <h1 className="text-2xl font-semibold text-zinc-950 dark:text-white">{t('inbox.title')}</h1>
          </div>
          <span className="rounded border border-zinc-200 bg-white px-3 py-1 text-sm text-zinc-700 dark:border-zinc-800 dark:bg-zinc-900 dark:text-zinc-300">
            {t('inbox.shown', { count: localizedRows.length })}
          </span>
        </div>

        <InboxFilterForm
          key={[selectedProject, selectedCategory, selectedPriority, selectedStatus, selectedSort].join('|')}
          selectedProject={selectedProject}
          selectedCategory={selectedCategory}
          selectedPriority={selectedPriority}
          selectedStatus={selectedStatus}
          selectedSort={selectedSort}
          projectOptions={projectOptions.map((project) => ({ label: project.name, value: project.id }))}
          categoryOptions={tenantConfig.intake.issue_categories.map((category) => ({
            label: getConfigOptionLabel(category, i18n.language),
            value: category,
          }))}
          priorityOptions={Object.entries(priorityLabels).map(([value, label]) => ({ label, value }))}
          statusOptions={Object.entries(statusLabels).map(([value, label]) => ({ label, value }))}
          labels={{
            project: t('inbox.project'),
            allProjects: t('inbox.allProjects'),
            category: t('inbox.category'),
            allCategories: t('inbox.allCategories'),
            priority: t('inbox.priority'),
            priorityHelp: t('inbox.priorityHelp'),
            allPriorities: t('inbox.allPriorities'),
            status: t('inbox.status'),
            statusHelp: t('inbox.statusHelp'),
            allUnresponded: t('inbox.allUnresponded'),
            allStatuses: t('inbox.allStatuses'),
            sort: t('inbox.sort'),
            sortHelp: t('inbox.sortHelp'),
            dateSubmitted: t('inbox.dateSubmitted'),
            dateOfOccurrence: t('inbox.dateOfOccurrence'),
            userPriority: t('inbox.userPriority'),
            applyFilters: t('inbox.applyFilters'),
            reset: t('inbox.reset'),
          }}
        />

        <div className="overflow-hidden rounded-lg border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-900">
          {localizedRows.length === 0 ? (
            <div className="px-6 py-12 text-center">
              <h2 className="text-sm font-medium text-zinc-950 dark:text-white">{t('inbox.clearTitle')}</h2>
              <p className="mt-1 text-sm text-zinc-600 dark:text-zinc-400">{t('inbox.clearBody')}</p>
            </div>
          ) : (
            <ul className="divide-y divide-zinc-200 dark:divide-zinc-800">
              {localizedRows.map((ticket) => {
                const lastMessage = ticket.lastMessageId ? (lastMessageById.get(ticket.lastMessageId) ?? ticket.lastMessageSanitized) : null
                return (
                <li key={ticket.id}>
                  <Link
                    href={`/tickets/${ticket.id}`}
                    className="grid gap-3 px-5 py-4 transition hover:bg-zinc-100 md:grid-cols-[1fr_auto] md:items-center dark:hover:bg-zinc-800/70"
                  >
                    <div className="min-w-0">
                      <div className="flex flex-wrap items-center gap-2">
                        <p className="text-xs font-mono text-zinc-500 dark:text-zinc-400">{ticket.referenceNumber}</p>
                        {ticket.issueCategory && (
                          <span className="rounded border border-sky-200 bg-sky-50 px-2 py-0.5 text-xs font-medium text-sky-800 dark:border-sky-400/30 dark:bg-sky-400/10 dark:text-sky-200">
                            {getConfigOptionLabel(ticket.issueCategory, i18n.language)}
                          </span>
                        )}
                        {ticket.userPriority && (
                          <span
                            data-testid={`priority-badge-${ticket.userPriority}`}
                            className={`rounded border px-2 py-0.5 text-xs font-semibold ${PRIORITY_BADGE_CLASSES[ticket.userPriority] ?? PRIORITY_BADGE_CLASSES.low}`}
                          >
                            {priorityLabels[ticket.userPriority] ?? ticket.userPriority}
                          </span>
                        )}
                        <span className="rounded border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-800 dark:border-emerald-400/30 dark:bg-emerald-400/10 dark:text-emerald-200">
                          {statusLabels[ticket.status] ?? ticket.status}
                        </span>
                      </div>
                      <h2 className="mt-1 truncate text-base font-semibold text-zinc-950 dark:text-white">
                        {buildInboxTicketTitle({ ...ticket, lastMessage })}
                      </h2>
                      <p className="mt-1 truncate text-sm text-zinc-600 dark:text-zinc-400">
                        {ticket.submitterName ?? ticket.submitterEmail}
                        {ticket.projectName ? ` · ${ticket.projectName}` : ''}
                        {lastMessage ? ` · ${lastMessage}` : ''}
                      </p>
                    </div>
                    <time className="text-sm text-zinc-600 dark:text-zinc-400" dateTime={ticket.createdAt.toISOString()}>
                      {formatDateTimeInUserZone(ticket.createdAt, currentUser?.timeZone)}
                    </time>
                  </Link>
                </li>
                )
              })}
            </ul>
          )}
        </div>
      </div>
    </main>
  )
}
