'use client';

/**
 * TicketList — customer view of all their support tickets.
 *
 * Fetches from GET /api/support/tickets.
 * Filterable by status group via SegmentedControl tabs.
 * Each row: status Pill, category badge, subject, timestamp.
 */

import { useMemo } from 'react';
import { useUrlFilterState } from '@/lib/url/useUrlFilterState';
import { makeTicketListCodec, type TicketListUrlState } from '@/lib/url/codecs/ticketListCodec';
import { HISTORY } from '@/lib/url/historyPolicy';
import { useQuery } from '@tanstack/react-query';
import { useT, useLocale } from '@/lib/i18n/react';
import { SegmentedControl } from '@/components/ui/primitives/SegmentedControl';
import { Button } from '@/components/ui/primitives/Button';
import { Badge } from '@/components/ui/primitives/Badge';
import { Pill } from '@/components/ui/primitives/Pill';
import { SLABadge } from '@/components/ui/domain/support/SLABadge';
import { EmptyState } from '@/components/ui/feedback/EmptyState';
import { Skeleton } from '@/components/ui/feedback/Skeleton';
import { InlineNotice } from '@/components/ui/feedback/InlineNotice';
import type { SLATone } from '@/components/ui/domain/support/SLABadge';
import { ErrorBoundary } from '@/components/ui/feedback/ErrorBoundary';
import { HydratedIsland } from '@/components/HydratedIsland';
import { getStatusPillTone } from './statusPillTone';
import { ticketCategoryLabel, ticketStatusLabel } from './ticketLabels';
import { formatRelative } from '@/lib/format';
import type { Locale } from '@/lib/i18n';

type StatusFilter = 'all' | 'open' | 'resolved' | 'closed';

interface TicketRow {
  id: string;
  status: string;
  category: string;
  subject: string;
  createdAt: string;
  updatedAt: string;
  slaDeadlineAt: string | null;
}

const OPEN_STATUSES = new Set([
  'open',
  'ai_handling',
  'awaiting_user',
  'escalated',
  'awaiting_agent',
  'human_handling',
  'reopened',
]);

const RESOLVED_STATUSES = new Set(['resolved']);
const CLOSED_STATUSES = new Set(['closed']);

function matchesFilter(ticket: TicketRow, filter: StatusFilter): boolean {
  if (filter === 'all') return true;
  if (filter === 'open') return OPEN_STATUSES.has(ticket.status);
  if (filter === 'resolved') return RESOLVED_STATUSES.has(ticket.status);
  if (filter === 'closed') return CLOSED_STATUSES.has(ticket.status);
  return true;
}

function getSLATone(ticket: TicketRow): SLATone | null {
  if (!ticket.slaDeadlineAt) return null;
  const deadline = new Date(ticket.slaDeadlineAt).getTime();
  const now = Date.now();
  const diff = deadline - now;
  if (diff < 0) return 'breached';
  if (diff < 2 * 60 * 60 * 1000) return 'warning';
  return 'healthy';
}

async function fetchTickets(status?: string): Promise<{ ok: boolean; tickets: TicketRow[] }> {
  const params = status ? `?status=${encodeURIComponent(status)}` : '';
  const res = await fetch(`/api/support/tickets${params}`);
  return res.json() as Promise<{ ok: boolean; tickets: TicketRow[] }>;
}

export function TicketList({ locale }: { locale?: Locale }) {
  return (
    <HydratedIsland locale={locale}>
      <TicketListInner />
    </HydratedIsland>
  );
}

function TicketListInner() {
  const t = useT('support');
  const tkt = t('ticket') as unknown as Record<string, string>;
  const { locale } = useLocale();
  const codec = useMemo(() => makeTicketListCodec('/support/tickets'), []);
  const { state: urlState, setUrlState } = useUrlFilterState<TicketListUrlState>({
    initial: { status: 'all' },
    codec,
  });
  const filter: StatusFilter = urlState.status;

  const { data, isLoading, isError } = useQuery({
    queryKey: ['support-tickets'],
    queryFn: () => fetchTickets(),
  });

  const tickets = (data?.tickets ?? []).filter((tk) => matchesFilter(tk, filter));

  const filterOptions = [
    { value: 'all', label: tkt.list_filter_all ?? 'All' },
    { value: 'open', label: tkt.list_filter_open ?? 'Open' },
    { value: 'resolved', label: tkt.list_filter_resolved ?? 'Resolved' },
    { value: 'closed', label: tkt.list_filter_closed ?? 'Closed' },
  ];

  return (
    <ErrorBoundary>
      <div className="flex flex-col gap-4 pb-8">
        <div className="flex items-center justify-end px-4">
          <Button
            variant="primary"
            size="sm"
            onClick={() => (window.location.href = '/support/tickets/new')}
          >
            {tkt.list_empty_cta ?? ''}
          </Button>
        </div>

        <div className="px-4">
          <SegmentedControl
            value={filter}
            onChange={(v) => setUrlState({ status: v as StatusFilter }, HISTORY.tweak)}
            options={filterOptions}
            aria-label={tkt.list_filter_aria ?? tkt.list_title ?? ''}
            size="sm"
          />
        </div>

        {isLoading && (
          <ul className="flex flex-col gap-3 px-4" aria-busy="true">
            {(['skeleton-1', 'skeleton-2', 'skeleton-3'] as const).map((skeletonKey) => (
              <li key={skeletonKey}>
                <Skeleton className="h-16 w-full rounded-lg" />
              </li>
            ))}
          </ul>
        )}

        {isError && (
          <div className="px-4">
            <InlineNotice tone="danger" description={tkt.error_generic ?? ''} />
          </div>
        )}

        {!isLoading && !isError && tickets.length === 0 && (
          <EmptyState
            title={tkt.list_empty_title ?? ''}
            description={tkt.list_empty_body ?? ''}
            action={
              <Button
                variant="primary"
                onClick={() => (window.location.href = '/support/tickets/new')}
              >
                {tkt.list_empty_cta ?? ''}
              </Button>
            }
          />
        )}

        {!isLoading && !isError && tickets.length > 0 && (
          <ul className="flex flex-col gap-3 px-4">
            {tickets.map((ticket) => {
              const slaTone = getSLATone(ticket);
              return (
                <li key={ticket.id}>
                  <a
                    href={`/support/tickets/${ticket.id}`}
                    className="border-border bg-surface-base flex flex-col gap-2 rounded-lg border p-4 transition-shadow hover:shadow-sm"
                  >
                    <div className="flex flex-wrap items-center gap-2">
                      <Pill tone={getStatusPillTone(ticket.status)} size="sm">
                        {ticketStatusLabel(ticket.status, locale)}
                      </Pill>
                      <Badge tone="neutral" size="sm">
                        {ticketCategoryLabel(ticket.category, locale)}
                      </Badge>
                      {slaTone &&
                        OPEN_STATUSES.has(ticket.status) &&
                        ticket.status !== 'awaiting_user' && <SLABadge tone={slaTone} />}
                    </div>
                    <p className="text-text-primary text-sm font-medium">{ticket.subject}</p>
                    <time
                      dateTime={ticket.updatedAt}
                      className="text-text-secondary text-xs"
                      suppressHydrationWarning
                    >
                      {formatRelative(ticket.updatedAt, locale)}
                    </time>
                  </a>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </ErrorBoundary>
  );
}
