'use client';

/**
 * TicketDetail — full ticket view with message thread, composer, and actions.
 *
 * Fetches from GET /api/support/tickets/[id].
 * Shows: status Pill, SLABadge, category badge, SupportThread, SupportMessageComposer.
 * Actions: close (POST /api/support/tickets/[id]/close), reopen via reply.
 */

import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useT, useLocale } from '@/lib/i18n/react';
import { PageHeader } from '@/components/ui/layout/PageHeader';
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 { SupportThread } from '@/components/ui/domain/support/SupportThread';
import { SupportMessageComposer } from '@/components/ui/domain/support/SupportMessageComposer';
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from '@/components/ui/overlays/AlertDialog';
import { InlineNotice } from '@/components/ui/feedback/InlineNotice';
import { Skeleton } from '@/components/ui/feedback/Skeleton';
import { getCsrfToken } from '@/lib/csrf';
import type { SLATone } from '@/components/ui/domain/support/SLABadge';
import type { SupportMessageView, SupportAttachmentView } from '@/server/support/types';
import { ErrorBoundary } from '@/components/ui/feedback/ErrorBoundary';
import { HydratedIsland } from '@/components/HydratedIsland';
import { getStatusPillTone } from './statusPillTone';
import { ticketCategoryLabel, ticketPriorityLabel, ticketStatusLabel } from './ticketLabels';
import { formatRelative } from '@/lib/format';
import type { Locale } from '@/lib/i18n';

interface TicketData {
  id: string;
  status: string;
  category: string;
  priority: string;
  subject: string;
  createdAt: string;
  slaDeadlineAt: string | null;
}

interface TicketDetailData {
  ticket: TicketData;
  messages: SupportMessageView[];
  attachments: SupportAttachmentView[];
}

export interface TicketDetailProps {
  ticketId: string;
  locale?: Locale;
}

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

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

export function TicketDetail({ ticketId, locale }: TicketDetailProps) {
  return (
    <HydratedIsland locale={locale}>
      <TicketDetailInner ticketId={ticketId} />
    </HydratedIsland>
  );
}

function TicketDetailInner({ ticketId }: TicketDetailProps) {
  const t = useT('support');
  const tkt = t('ticket') as unknown as Record<string, string>;
  const tCloseErrors = t('close_errors') as unknown as Record<string, string>;
  const { locale } = useLocale();
  const qc = useQueryClient();

  const [closeDialogOpen, setCloseDialogOpen] = useState(false);

  const { data, isLoading, isError } = useQuery<TicketDetailData>({
    queryKey: ['support-ticket', ticketId],
    queryFn: async () => {
      const res = await fetch(`/api/support/tickets/${ticketId}`);
      const json = (await res.json()) as { ok: boolean } & TicketDetailData;
      if (!json.ok) throw new Error('fetch failed');
      return { ticket: json.ticket, messages: json.messages, attachments: json.attachments };
    },
  });

  const replyMutation = useMutation({
    mutationFn: async ({ body, attachmentIds }: { body: string; attachmentIds: string[] }) => {
      const res = await fetch(`/api/support/tickets/${ticketId}/messages`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify({ body, attachmentIds }),
      });
      const json = (await res.json()) as { ok: boolean };
      if (!json.ok) throw new Error('reply failed');
    },
    onSuccess: () => void qc.invalidateQueries({ queryKey: ['support-ticket', ticketId] }),
  });

  const closeMutation = useMutation({
    mutationFn: async () => {
      const res = await fetch(`/api/support/tickets/${ticketId}/close`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
      });
      const json = (await res.json()) as { ok: boolean; code?: string };
      if (!json.ok) {
        const err = Object.assign(new Error('close failed'), { code: json.code });
        throw err;
      }
    },
    onSuccess: () => {
      setCloseDialogOpen(false);
      void qc.invalidateQueries({ queryKey: ['support-ticket', ticketId] });
    },
  });

  if (isLoading) {
    return (
      <div className="flex flex-col gap-4 px-4 pb-8">
        <Skeleton className="h-12 w-3/4 rounded-lg" />
        <Skeleton className="h-4 w-1/2 rounded-md" />
        <Skeleton className="h-40 w-full rounded-lg" />
      </div>
    );
  }

  if (isError || !data) {
    return (
      <div className="flex flex-col gap-4 px-4 py-8">
        <InlineNotice tone="danger" description={tkt.error_generic ?? ''} />
        <Button variant="secondary" onClick={() => (window.location.href = '/support/tickets')}>
          {tkt.back_to_list ?? ''}
        </Button>
      </div>
    );
  }

  const { ticket, messages, attachments } = data;
  const closeErrCode = (closeMutation.error as { code?: string } | null)?.code ?? '';
  const closeErrMsg =
    (
      {
        ILLEGAL_TRANSITION: tCloseErrors.illegal_transition,
        NOT_FOUND: tCloseErrors.not_found,
      } as Record<string, string>
    )[closeErrCode] ?? tCloseErrors.generic;
  const slaTone = getSLATone(ticket);
  const canClose = ticket.status === 'resolved';
  const isOpenStatus = OPEN_STATUSES.has(ticket.status);
  const statusLabel = ticketStatusLabel(ticket.status, locale);
  const categoryLabel = ticketCategoryLabel(ticket.category, locale);
  const priorityLabel = ticketPriorityLabel(ticket.priority, locale);

  return (
    <ErrorBoundary>
      <div className="flex flex-col gap-6 px-4 pb-8">
        <PageHeader
          title={ticket.subject}
          subtitle={(tkt.detail_title ?? '#').replace('{shortId}', ticketId.slice(0, 8))}
          actions={
            canClose ? (
              <Button variant="secondary" size="sm" onClick={() => setCloseDialogOpen(true)}>
                {tkt.close ?? ''}
              </Button>
            ) : undefined
          }
        />

        {/* Metadata row with section labels */}
        <dl className="flex flex-wrap gap-x-4 gap-y-3">
          <div className="flex flex-col gap-1">
            <dt className="text-text-secondary text-xs font-medium">{tkt.detail_status ?? ''}</dt>
            <dd>
              <Pill tone={getStatusPillTone(ticket.status)} size="sm">
                {statusLabel}
              </Pill>
            </dd>
          </div>
          <div className="flex flex-col gap-1">
            <dt className="text-text-secondary text-xs font-medium">{tkt.detail_category ?? ''}</dt>
            <dd>
              <Badge tone="neutral" size="sm">
                {categoryLabel}
              </Badge>
            </dd>
          </div>
          <div className="flex flex-col gap-1">
            <dt className="text-text-secondary text-xs font-medium">{tkt.detail_priority ?? ''}</dt>
            <dd>
              <Badge tone="neutral" size="sm">
                {priorityLabel}
              </Badge>
            </dd>
          </div>
          <div className="flex flex-col gap-1">
            <dt className="text-text-secondary text-xs font-medium">
              {tkt.detail_opened_at ?? ''}
            </dt>
            <dd>
              <time
                dateTime={ticket.createdAt}
                className="text-text-primary text-sm"
                suppressHydrationWarning
              >
                {formatRelative(ticket.createdAt, locale)}
              </time>
            </dd>
          </div>
          {slaTone && isOpenStatus && ticket.status !== 'awaiting_user' && (
            <div className="flex flex-col gap-1">
              <dt className="text-text-secondary text-xs font-medium">{tkt.detail_sla ?? 'SLA'}</dt>
              <dd>
                <SLABadge tone={slaTone} />
              </dd>
            </div>
          )}
        </dl>

        {ticket.status === 'awaiting_user' && (
          <InlineNotice tone="warning" description={tkt.composer_awaiting_user_notice ?? ''} />
        )}

        {ticket.status === 'resolved' && (
          <InlineNotice tone="success" description={tkt.resolved_notice ?? ''} />
        )}

        {ticket.status === 'closed' && (
          <InlineNotice tone="info" description={tkt.composer_closed_notice ?? ''} />
        )}

        {closeMutation.isError && (
          <div role="alert">
            <InlineNotice tone="danger" description={closeErrMsg} />
          </div>
        )}

        <section
          className="border-border-default bg-surface-base relative overflow-hidden rounded-3xl border"
          data-fx="ticket-tear"
        >
          <div className="border-border-subtle flex items-center gap-2 border-b border-dashed px-4 py-3">
            <span className="bg-surface-page border-border-default absolute -start-3 top-12 size-6 rounded-full border" />
            <span className="bg-surface-page border-border-default absolute -end-3 top-12 size-6 rounded-full border" />
            <Pill tone={getStatusPillTone(ticket.status)} size="sm">
              {statusLabel}
            </Pill>
            <span className="text-text-secondary text-xs">{categoryLabel}</span>
          </div>

          <div aria-live="polite" aria-label={tkt.thread_label ?? ''} className="px-4 pt-4">
            <SupportThread messages={messages} attachments={attachments} viewerRole="customer" />
          </div>

          <div className="border-border-subtle border-t border-dashed px-4 pt-3 pb-4">
            <SupportMessageComposer
              ticketStatus={ticket.status}
              parentId={ticketId}
              parentType="ticket"
              onSubmit={async (body, attachmentIds) => {
                await replyMutation.mutateAsync({ body, attachmentIds });
              }}
            />
          </div>
        </section>

        <AlertDialog open={closeDialogOpen} onOpenChange={setCloseDialogOpen}>
          <AlertDialogContent>
            <AlertDialogHeader>
              <AlertDialogTitle>{tkt.close_confirm_title ?? ''}</AlertDialogTitle>
              <AlertDialogDescription>{tkt.close_confirm_body ?? ''}</AlertDialogDescription>
            </AlertDialogHeader>
            <AlertDialogFooter>
              <AlertDialogCancel>{tkt.cancel ?? ''}</AlertDialogCancel>
              <AlertDialogAction onClick={() => closeMutation.mutate()}>
                {tkt.close_confirm_ok ?? ''}
              </AlertDialogAction>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialog>
      </div>
    </ErrorBoundary>
  );
}
