'use client';
import { useLocale, useTranslations } from 'next-intl';
import { useParams, useRouter } from 'next/navigation';
import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useSnackbar } from 'notistack';
import { Avatar, Paper, Skeleton, Stack, Typography } from '@mui/material';
import {
  AppButton,
  AppIcon,
  EmptyState,
  RatingInput,
  ReviewTagSelector,
  RhfControlGroup,
  RhfTextField,
  StatusChip,
  SurfaceCard,
} from '@/components';
import type { StatusKind } from '@/components';
import { formatShamsiDate } from '@/utils';
import { useBookingDetail } from '@/services/bookings';
import type { BookingDetailDto } from '@/services/bookings/types';
import { useReviewEligibility, useMyReviewForBooking, useCreateReview } from '@/services/reviews';
import { REVIEW_TAG_CODES, type ModerationStatus } from '@/services/reviews/types';

/** Best-effort read of the frozen variant display name from the booking's variant snapshot. */
function variantName(snapshotJson: string): string | null {
  try {
    const parsed = JSON.parse(snapshotJson) as { displayName?: string };
    return parsed?.displayName ?? null;
  } catch {
    return null;
  }
}

const REVIEW_BODY_MAX = 2000;

interface ReviewFormValues {
  rating: number;
  body: string;
  tagCodes: string[];
}

/** moderationStatus → StatusChip kind (published=success, pending=warning, rejected=error, hidden=neutral). */
const STATUS_KIND: Record<ModerationStatus, StatusKind> = {
  pending_moderation: 'pending',
  published: 'verified',
  hidden: 'neutral',
  rejected: 'rejected',
};

/**
 * f13 — Leave a review («ثبت نظر»): the customer's one moderated review for a completed booking. The form is
 * shown only when the server says the booking can be reviewed AND it is not already reviewed; on submit it
 * flips to the persistent "under review" state (the review is `pending_moderation` and never appears publicly
 * here). One review per booking (1:1) — a returning customer sees their review's state, never a second form.
 */
export default function LeaveReviewPage() {
  const t = useTranslations('reviews');
  const tc = useTranslations('common');
  const locale = useLocale();
  const router = useRouter();
  const { enqueueSnackbar } = useSnackbar();

  const params = useParams<{ id: string }>();
  const rawId = Number(params.id);
  const bookingId = Number.isInteger(rawId) && rawId > 0 ? rawId : -1;

  const { data: booking } = useBookingDetail(bookingId, 'customer');
  const reviewable = booking?.status === 'completed' || booking?.status === 'closed';
  const eligibility = useReviewEligibility(bookingId);
  // Gated exactly like the booking-detail page's identical call — a review can only ever exist for a
  // completed/closed booking, so an in-flight/active booking never fires this query.
  const myReview = useMyReviewForBooking(bookingId, { enabled: reviewable });
  const createReview = useCreateReview();

  const form = useForm<ReviewFormValues>({ mode: 'onTouched', defaultValues: { rating: 0, body: '', tagCodes: [] } });
  const { control, handleSubmit } = form;
  const rating = useWatch({ control, name: 'rating' });
  const body = useWatch({ control, name: 'body' });
  const tagCodes = useWatch({ control, name: 'tagCodes' });

  const nurseName = booking?.nurseName?.trim();

  const submit = (values: ReviewFormValues) =>
    createReview.mutate(
      { bookingId, body: { rating: values.rating, body: values.body.trim() || null, tagCodes: values.tagCodes } },
      { onError: () => enqueueSnackbar(t('error_submit'), { variant: 'error' }) },
    );

  // ── Already reviewed → the persistent under-review / published state (never a second form) ───────────────
  const existing = myReview.data;
  const submittedThisSession = createReview.isSuccess;
  if ((existing && existing.status !== 'none') || submittedThisSession) {
    const status: ModerationStatus =
      existing && existing.status !== 'none' ? existing.status : 'pending_moderation';
    const shownRating = existing && existing.status !== 'none' ? (existing.rating ?? rating) : rating;
    const shownBody = existing && existing.status !== 'none' ? existing.body : body.trim() || null;
    const shownTags = existing && existing.status !== 'none' ? existing.tagCodes : tagCodes;
    return (
      <Stack sx={{ gap: 3, maxWidth: 560, mx: 'auto', width: '100%' }}>
        <PageHeading title={t('my_review_title')} subtitle={nurseName ? t('for_nurse', { name: nurseName }) : undefined} />
        {booking ? <ReviewContextRecap booking={booking} locale={locale} /> : null}
        <Paper elevation={0} sx={{ p: 2.5, border: '1px solid', borderColor: 'divider', borderRadius: 'var(--bal-radius-md)' }}>
          <Stack sx={{ gap: 1.5 }}>
            <Stack direction="row" sx={{ alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>
              <StatusChip status={STATUS_KIND[status]} label={t(`status_${status}`)} />
              {existing?.createdAt ? (
                <Typography variant="caption" sx={{ color: 'text.secondary' }}>
                  {formatShamsiDate(existing.createdAt, locale)}
                </Typography>
              ) : null}
            </Stack>
            {status === 'pending_moderation' ? (
              <Typography variant="body2" sx={{ color: 'text.secondary' }}>
                {t('under_review_body')}
              </Typography>
            ) : null}
            <RatingInput value={shownRating} readOnly size={22} ariaLabel={t('rating_label')} />
            {shownBody ? <Typography variant="body2">{shownBody}</Typography> : null}
            {shownTags.length > 0 ? (
              <Stack direction="row" sx={{ gap: 1, flexWrap: 'wrap' }}>
                {shownTags.map((code) => (
                  <StatusChip key={code} status="info" label={t.has(`tag_${code}`) ? t(`tag_${code}`) : code} />
                ))}
              </Stack>
            ) : null}
          </Stack>
        </Paper>
        <AppButton variant="outlined" color="primary" onClick={() => router.back()} sx={{ alignSelf: 'flex-start' }}>
          {tc('back')}
        </AppButton>
      </Stack>
    );
  }

  if (eligibility.isLoading || myReview.isLoading) {
    return (
      <Stack sx={{ gap: 2, maxWidth: 560, mx: 'auto', width: '100%' }}>
        <Skeleton variant="text" width="50%" height={36} />
        <Skeleton variant="rounded" height={56} />
        <Skeleton variant="rounded" height={120} />
        <Skeleton variant="rounded" height={72} />
      </Stack>
    );
  }

  // ── Not eligible → a clear, non-leaking reason (no form) ─────────────────────────────────────────────────
  if (!eligibility.data?.canReview) {
    const reason = eligibility.data?.reason ?? 'not_completed';
    return (
      <Stack sx={{ gap: 3, maxWidth: 560, mx: 'auto', width: '100%' }}>
        <PageHeading title={t('not_eligible_title')} />
        <EmptyState title={t(`reason_${reason}`)} />
        <AppButton variant="outlined" color="primary" onClick={() => router.back()} sx={{ alignSelf: 'flex-start' }}>
          {tc('back')}
        </AppButton>
      </Stack>
    );
  }

  // ── Eligible → the review form ───────────────────────────────────────────────────────────────────────────
  return (
    <FormProvider {...form}>
    <Stack component="form" noValidate onSubmit={handleSubmit(submit)} sx={{ gap: 3, maxWidth: 560, mx: 'auto', width: '100%' }}>
      <PageHeading title={t('title')} subtitle={nurseName ? t('for_nurse', { name: nurseName }) : t('subtitle')} />
      {booking ? <ReviewContextRecap booking={booking} locale={locale} /> : null}

      {/* Moderation expectation, up front — not only after submit. */}
      <Stack direction="row" sx={{ gap: 1, alignItems: 'center', p: 1.5, borderRadius: 'var(--bal-radius-md)', bgcolor: 'var(--bal-info-soft)' }}>
        <AppIcon icon="info" size={18} color="var(--bal-info)" />
        <Typography variant="body2" sx={{ color: 'var(--bal-info)' }}>
          {t('moderation_note')}
        </Typography>
      </Stack>

      <RhfControlGroup<ReviewFormValues>
        name="rating"
        label={t('rating_label')}
        rules={{ validate: (value) => Number(value ?? 0) >= 1 }}
      >
        {({ field }) => (
          <RatingInput value={Number(field.value) || 0} onChange={field.onChange} ariaLabel={t('rating_label')} />
        )}
      </RhfControlGroup>

      <RhfTextField<ReviewFormValues>
        name="body"
        label={t('body_label')}
        placeholder={t('body_placeholder')}
        transform={(raw) => raw.slice(0, REVIEW_BODY_MAX)}
        multiline
        minRows={3}
        fullWidth
      />

      <RhfControlGroup<ReviewFormValues> name="tagCodes" label={t('tags_label')}>
        {({ field }) => (
          <ReviewTagSelector
            codes={REVIEW_TAG_CODES}
            selected={(field.value as string[]) ?? []}
            onChange={field.onChange}
            labelFor={(code) => (t.has(`tag_${code}`) ? t(`tag_${code}`) : code)}
            disabled={createReview.isPending}
          />
        )}
      </RhfControlGroup>

      <Stack direction="row" sx={{ gap: 1, justifyContent: 'flex-end' }}>
        <AppButton variant="text" color="primary" onClick={() => router.back()} disabled={createReview.isPending}>
          {tc('cancel')}
        </AppButton>
        <AppButton
          type="submit"
          variant="contained"
          color="primary"
          disabled={rating < 1 || createReview.isPending}
          startIcon="star"
        >
          {createReview.isPending ? t('submitting') : t('submit')}
        </AppButton>
      </Stack>
    </Stack>
    </FormProvider>
  );
}

/** "What you're reviewing" recap — service, Shamsi visit date, nurse — off the already-cached booking. */
function ReviewContextRecap({ booking, locale }: { booking: BookingDetailDto; locale: string }) {
  const t = useTranslations('reviews');
  const service = variantName(booking.variantSnapshotJson);
  const name = booking.nurseName.trim();

  return (
    <SurfaceCard padding="sm">
      <Stack direction="row" sx={{ gap: 1.5, alignItems: 'center' }}>
        <Avatar sx={{ width: 40, height: 40, bgcolor: 'var(--bal-primary-soft)', color: 'var(--bal-primary)', fontWeight: 700 }}>
          {(name || t('recap_fallback_nurse')).charAt(0)}
        </Avatar>
        <Stack sx={{ gap: 0.25, minWidth: 0 }}>
          <Typography variant="subtitle2" sx={{ fontWeight: 700 }}>
            {service ?? t('recap_fallback_service')}
          </Typography>
          <Typography variant="caption" sx={{ color: 'text.secondary' }}>
            {name || t('recap_fallback_nurse')} · {formatShamsiDate(booking.scheduledDate, locale)}
          </Typography>
        </Stack>
      </Stack>
    </SurfaceCard>
  );
}

function PageHeading({ title, subtitle }: { title: string; subtitle?: string }) {
  return (
    <Stack sx={{ gap: 0.5 }}>
      <Typography variant="h5" component="h1">
        {title}
      </Typography>
      {subtitle ? (
        <Typography variant="body2" sx={{ color: 'text.secondary' }}>
          {subtitle}
        </Typography>
      ) : null}
    </Stack>
  );
}
