'use client';
import { useState } from 'react';
import { useParams, useRouter } from 'next/navigation';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Collapse,
  Paper,
  Skeleton,
  Stack,
  TextField,
  ToggleButton,
  ToggleButtonGroup,
  Typography,
} from '@mui/material';
import { AppButton, StatusChip } from '@/components';
import type { StatusKind } from '@/components';
import { AdminEmptyState, AdminErrorState, AdminMessageBubble, RefundPanel } from '@/components/admin';
import { useAdminCapabilities } from '@/hooks';
import { ROUTES } from '@/constants';
import { useAdminTicket, usePostAdminMessage } from '@/services/tickets';
import type { TicketAuthorRole, TicketStatus } from '@/services/tickets/types';

/** Status → chip color: an open ticket is pending work, a closed one is neutral (mirrors the queue). */
const STATUS_KIND: Record<TicketStatus, StatusKind> = { open: 'pending', closed: 'neutral' };

/** The `tickets` author-label key. `admin` has no `author_admin` key — staff read as "support" (`author_support`). */
function authorLabelKey(role: TicketAuthorRole): string {
  return `author_${role === 'admin' ? 'support' : role}`;
}

/** A client id so the optimistic bubble reconciles to the server message by identity (never double-rendered). */
function makeClientMessageId(): string {
  return crypto?.randomUUID?.() ?? String(Date.now());
}

/**
 * The admin ticket thread (f15) — the full conversation **including internal notes** (the admin lens carries
 * `isInternal`; the user app never does). Staff read the whole thread and reply as **either** a participant-
 * visible reply **or** a staff-only internal note (the composer toggles `isInternal`; `AdminMessageBubble`
 * renders internal notes distinctly). Sends are optimistic (`usePostAdminMessage`) — the draft clears only on
 * confirm. When the ticket is a **refund** case linked to a booking, the admin opens the `RefundPanel` inline
 * (it always initiates from a ticket, never a standalone form). Composer + refund are gated on the principal's
 * capabilities; the server is the real authority.
 */
export default function AdminTicketThreadPage() {
  const t = useTranslations('admin');
  const tickets = useTranslations('tickets');
  const locale = useLocale();
  const router = useRouter();
  const caps = useAdminCapabilities();
  const { enqueueSnackbar } = useSnackbar();

  const params = useParams<{ id: string }>();
  const parsed = Number(params?.id);
  const ticketId = Number.isFinite(parsed) && parsed > 0 ? parsed : 0;

  const { data: detail, isLoading, isError, refetch } = useAdminTicket(ticketId || null);
  const post = usePostAdminMessage(ticketId);

  const [mode, setMode] = useState<'reply' | 'internal'>('reply');
  const [body, setBody] = useState('');
  const [refundShown, setRefundShown] = useState(false);

  const isInternal = mode === 'internal';

  const send = () => {
    const trimmed = body.trim();
    if (!trimmed || post.isPending) return;
    post.mutate(
      { body: trimmed, isInternal, clientMessageId: makeClientMessageId() },
      {
        onSuccess: () => {
          setBody('');
          enqueueSnackbar(t('ticket_sent'), { variant: 'success' });
        },
      },
    );
  };

  const showRefund = !!detail && detail.category === 'refund' && detail.bookingId != null && caps.canRefund;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: 820, mx: 'auto', width: '100%' }}>
      <AppButton
        variant="text"
        color="primary"
        onClick={() => router.push(`/${locale}${ROUTES.ADMIN_TICKETS}`)}
        sx={{ alignSelf: 'flex-start' }}
      >
        {t('back')}
      </AppButton>

      {isLoading ? (
        <Stack sx={{ gap: 1.5 }}>
          <Skeleton variant="rounded" height={96} />
          <Skeleton variant="rounded" height={56} sx={{ width: '70%' }} />
          <Skeleton variant="rounded" height={56} sx={{ width: '70%', alignSelf: 'flex-end' }} />
        </Stack>
      ) : isError ? (
        <AdminErrorState message={t('error_generic')} retryLabel={t('retry')} onRetry={() => refetch()} />
      ) : !detail ? (
        <AdminEmptyState icon="support" title={t('ticket_empty')} />
      ) : (
        <>
          <Paper elevation={0} sx={{ p: 2.5, border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
            <Stack sx={{ gap: 1.5 }}>
              <Typography variant="h6" component="h1" sx={{ fontWeight: 800 }} dir="ltr">
                {t('ticket_thread_title', { ref: detail.referenceCode })}
              </Typography>
              {detail.subject ? (
                <Typography variant="body2" sx={{ color: 'text.secondary' }}>
                  {detail.subject}
                </Typography>
              ) : null}
              <Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap', alignItems: 'center' }}>
                <Chip size="small" label={t(`tcat_${detail.category}`)} />
                <StatusChip status={STATUS_KIND[detail.status]} label={t(`tstatus_${detail.status}`)} />
                {detail.bookingId != null ? (
                  <Chip size="small" variant="outlined" label={t('refund_linked_booking', { id: detail.bookingId })} />
                ) : null}
                {detail.refundId != null ? (
                  <Chip size="small" variant="outlined" label={t('ticket_linked_refund', { id: detail.refundId })} />
                ) : null}
              </Stack>

              {showRefund ? (
                <Box>
                  <AppButton
                    variant="outlined"
                    color="primary"
                    startIcon="refunds"
                    onClick={() => setRefundShown((v) => !v)}
                  >
                    {t('refund_open')}
                  </AppButton>
                  <Collapse in={refundShown} unmountOnExit>
                    <Paper elevation={0} sx={{ mt: 1.5, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
                      <RefundPanel bookingId={detail.bookingId as number} ticketId={detail.id} />
                    </Paper>
                  </Collapse>
                </Box>
              ) : null}
            </Stack>
          </Paper>

          <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5, maxHeight: 520, overflowY: 'auto', p: 0.5 }}>
            {detail.messages.map((m) => (
              <AdminMessageBubble
                key={m.clientMessageId ?? String(m.id)}
                message={m}
                authorLabel={tickets(authorLabelKey(m.authorRole))}
              />
            ))}
          </Box>

          {caps.canManageTickets ? (
            <Paper elevation={0} sx={{ p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2 }}>
              <Stack sx={{ gap: 1.5 }}>
                <ToggleButtonGroup
                  size="small"
                  exclusive
                  value={mode}
                  onChange={(_e, next: 'reply' | 'internal' | null) => next && setMode(next)}
                >
                  <ToggleButton value="reply">{t('ticket_public_reply')}</ToggleButton>
                  <ToggleButton value="internal">{t('ticket_internal_note')}</ToggleButton>
                </ToggleButtonGroup>
                <TextField
                  multiline
                  minRows={2}
                  maxRows={6}
                  size="small"
                  placeholder={isInternal ? t('ticket_composer_internal_ph') : t('ticket_composer_public_ph')}
                  value={body}
                  onChange={(e) => setBody(e.target.value)}
                />
                <AppButton
                  variant="contained"
                  color="primary"
                  startIcon="send"
                  onClick={send}
                  disabled={post.isPending || body.trim().length === 0}
                  sx={{ alignSelf: 'flex-start' }}
                >
                  {t('ticket_send')}
                </AppButton>
              </Stack>
            </Paper>
          ) : null}
        </>
      )}
    </Box>
  );
}
