'use client';
import { useState } from 'react';
import { useParams } from 'next/navigation';
import { useLocale, useTranslations } from 'next-intl';
import { useSnackbar } from 'notistack';
import {
  Box,
  Chip,
  Collapse,
  Paper,
  Skeleton,
  Stack,
  TextField,
  ToggleButton,
  ToggleButtonGroup,
  Tooltip,
} from '@mui/material';
import { AppButton, PageHeader, StatusChip } from '@/components';
import type { StatusKind } from '@/components';
import { useThreadScroll } from '@/components/messaging';
import { AdminEmptyState, AdminErrorState, AdminMessageBubble, ConfirmDialog, RefundPanel } from '@/components/admin';
import { useAdminBackToList, useAdminCapabilities } from '@/hooks';
import { useAuth } from '@/context/auth';
import { ROUTES } from '@/constants';
import { useAdminTicket, useAssignTicket, useCloseTicket, usePostAdminMessage, useReopenTicket } from '@/services/tickets';
import { TICKET_LIFECYCLE_ENABLED } from '@/services/tickets/constants';
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' };
const REFUND_PANEL_ID = 'admin-ticket-refund-panel';

/** 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, and ui-phase-11 makes the composer itself amber-tinted in internal mode
 * so a staff member can never post an internal note publicly by mistake). Sends are optimistic
 * (`usePostAdminMessage`) — the draft clears only on confirm; the thread opens scrolled to the newest message
 * (`useThreadScroll`). When the ticket is a **refund** case linked to a booking, the admin opens the
 * `RefundPanel` inline. Close/reopen/assign-to-me (REQ-063) are gated behind `TICKET_LIFECYCLE_ENABLED` — no
 * live route yet — AND the principal's `canManageTickets` capability; the server is the real authority.
 */
export default function AdminTicketThreadPage() {
  const t = useTranslations('admin');
  const tickets = useTranslations('tickets');
  const locale = useLocale();
  const caps = useAdminCapabilities();
  const { enqueueSnackbar } = useSnackbar();
  const [authState] = useAuth();
  const meId = authState.currentUser?.id;
  const goBack = useAdminBackToList(`/${locale}${ROUTES.ADMIN_TICKETS}`);

  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 closeTicket = useCloseTicket(ticketId);
  const reopenTicket = useReopenTicket(ticketId);
  const assignTicket = useAssignTicket(ticketId);

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

  const isInternal = mode === 'internal';
  const messageCount = detail?.messages.length ?? 0;
  const lastMessage = detail?.messages[messageCount - 1];
  const { bottomRef } = useThreadScroll(messageCount, lastMessage?.isMine ?? false);

  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 onCloseConfirm = () => {
    closeTicket.mutate(undefined, {
      onSuccess: () => {
        setCloseDialogOpen(false);
        enqueueSnackbar(t('ticket_closed_ok'), { variant: 'success' });
      },
    });
  };

  const onReopenConfirm = () => {
    reopenTicket.mutate(undefined, {
      onSuccess: () => {
        setReopenDialogOpen(false);
        enqueueSnackbar(t('ticket_reopened_ok'), { variant: 'success' });
      },
    });
  };

  const onAssignMe = () => {
    if (meId == null || assignTicket.isPending) return;
    assignTicket.mutate({ ownerUserId: meId }, { onSuccess: () => enqueueSnackbar(t('ticket_assigned_me'), { variant: 'success' }) });
  };

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

  const lifecycleActions = showLifecycle && detail ? (
    <>
      {detail.status === 'open' ? (
        <AppButton variant="outlined" color="primary" startIcon="close" onClick={() => setCloseDialogOpen(true)}>
          {t('ticket_close')}
        </AppButton>
      ) : (
        <AppButton variant="outlined" color="primary" startIcon="refresh" onClick={() => setReopenDialogOpen(true)}>
          {t('ticket_reopen')}
        </AppButton>
      )}
      <Tooltip title={meId == null ? t('assign_me_loading') : ''}>
        <span>
          <AppButton
            variant="outlined"
            color="primary"
            startIcon="assign"
            onClick={onAssignMe}
            disabled={meId == null || assignTicket.isPending}
          >
            {t('ticket_assign_me')}
          </AppButton>
        </span>
      </Tooltip>
    </>
  ) : null;

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: 820, mx: 'auto', width: '100%' }}>
      <AppButton variant="text" color="primary" onClick={goBack} 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: 'var(--bal-radius-md)' }}>
            <PageHeader
              title={t('ticket_thread_title', { ref: detail.referenceCode })}
              subtitle={detail.subject ?? undefined}
              actions={lifecycleActions}
              meta={
                <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 sx={{ mt: 1.5 }}>
                <AppButton
                  variant="outlined"
                  color="primary"
                  startIcon="refunds"
                  aria-expanded={refundShown}
                  aria-controls={REFUND_PANEL_ID}
                  onClick={() => setRefundShown((v) => !v)}
                >
                  {t('refund_open')}
                </AppButton>
                <Collapse in={refundShown} unmountOnExit>
                  <Paper
                    id={REFUND_PANEL_ID}
                    elevation={0}
                    sx={{ mt: 1.5, p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 'var(--bal-radius-md)' }}
                  >
                    <RefundPanel bookingId={detail.bookingId as number} ticketId={detail.id} />
                  </Paper>
                </Collapse>
              </Box>
            ) : null}
          </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))}
              />
            ))}
            <div ref={bottomRef} />
          </Box>

          {caps.canManageTickets ? (
            <Paper
              elevation={0}
              sx={{
                p: 2,
                border: '1px solid',
                borderColor: isInternal ? 'var(--bal-warning)' : 'divider',
                borderRadius: 'var(--bal-radius-md)',
                bgcolor: isInternal ? 'var(--bal-warning-soft)' : 'background.paper',
              }}
            >
              <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' }}
                >
                  {isInternal ? t('ticket_send_internal') : t('ticket_send')}
                </AppButton>
              </Stack>
            </Paper>
          ) : null}

          <ConfirmDialog
            open={closeDialogOpen}
            title={t('ticket_close')}
            body={t('ticket_close_confirm')}
            confirmLabel={t('ticket_close')}
            cancelLabel={t('cancel')}
            onConfirm={onCloseConfirm}
            onClose={() => setCloseDialogOpen(false)}
            loading={closeTicket.isPending}
            confirmColor="primary"
          />
          <ConfirmDialog
            open={reopenDialogOpen}
            title={t('ticket_reopen')}
            body={t('ticket_reopen_confirm')}
            confirmLabel={t('ticket_reopen')}
            cancelLabel={t('cancel')}
            onConfirm={onReopenConfirm}
            onClose={() => setReopenDialogOpen(false)}
            loading={reopenTicket.isPending}
            confirmColor="primary"
          />
        </>
      )}
    </Box>
  );
}
