import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Calendar } from '@/components/ui/calendar';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter,
} from '@/components/ui/dialog';
import { CalendarIcon, CalendarClock } from 'lucide-react';
import { differenceInDays, format } from 'date-fns';
import { toast } from 'sonner';
import { useAuth } from '@/hooks/useAuth';
import { useCourseAvailability } from '@/hooks/useCourseAvailability';

const csrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? '';

interface RequestDateChangeProps {
  order: any;
  onSubmitted?: () => void;
}

/**
 * Self-contained "Request Date Change" affordance — a button plus an
 * availability-aware date picker that files a *pending* date-change request
 * (an admin still has to approve it).
 *
 * The calendar disables any day the assigned trainer(s)/venue(s) aren't
 * actually available (weekends, bank holidays, leave, clashes — via
 * useCourseAvailability), so a customer or company manager can never request a
 * date the course couldn't run on. Shared by the customer/company portals
 * (through BookingActions) and the admin Bookings screen so every entry point
 * enforces the same rules.
 */
export const RequestDateChange = ({ order, onSubmitted }: RequestDateChangeProps) => {
  const { user } = useAuth();
  const [open, setOpen] = useState(false);
  const [requestedDate, setRequestedDate] = useState<Date | undefined>();
  const [reason, setReason] = useState('');

  // VT e-learning orders have no schedule, so there's nothing to reschedule.
  const isOnlineOrder = !order.start_date;
  const daysUntilCourse = isOnlineOrder
    ? Number.POSITIVE_INFINITY
    : differenceInDays(new Date(order.start_date + 'T00:00:00'), new Date());
  const hasPendingDateChange = !!order.pending_date_change;
  const canRequestDateChange = !isOnlineOrder
    && ['pending', 'paid', 'confirmed'].includes(order.status)
    && daysUntilCourse >= 1
    && !hasPendingDateChange;

  // Drive the picker off the same availability model the public booking page
  // uses, so trainers/venues/holidays/clashes are all respected.
  const courseInfo = order.courses || order.course;
  const { isDateAvailable } = useCourseAvailability(
    courseInfo?.id ?? order.course_id,
    Number(courseInfo?.days ?? 1),
    String(courseInfo?.category ?? ''),
  );

  const dateChangeMutation = useMutation({
    mutationFn: async () => {
      const res = await fetch('/api/admin/date-change-requests', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken() },
        body: JSON.stringify({
          order_id: order.id,
          requested_date: format(requestedDate!, 'yyyy-MM-dd'),
          reason,
          trainer_id: order.trainer_id,
          requested_by: user?.id,
        }),
      });
      if (!res.ok) throw new Error('Failed to submit request');

      await fetch('/api/functions/notify-date-change', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken() },
        body: JSON.stringify({
          order_id: order.id,
          requested_date: format(requestedDate!, 'yyyy-MM-dd'),
          reason,
          requester_name: order.customer_name,
        }),
      });
    },
    onSuccess: () => {
      toast.success('Date change request submitted — an admin will review it.');
      setOpen(false);
      setRequestedDate(undefined);
      setReason('');
      onSubmitted?.();
    },
    onError: (err: Error) => toast.error(err.message || 'Failed to submit request'),
  });

  if (!canRequestDateChange && !hasPendingDateChange) return null;

  return (
    <>
      {hasPendingDateChange && (
        <Badge
          variant="outline"
          className="bg-amber-500/10 text-amber-600 border-amber-500/30 gap-1"
          title={`Requested ${order.pending_date_change.requested_date}`}
        >
          <CalendarClock className="w-3 h-3" /> Change Pending Approval
        </Badge>
      )}
      {canRequestDateChange && (
        <Button variant="outline" size="sm" onClick={() => setOpen(true)}>
          <CalendarClock className="w-3.5 h-3.5 mr-1.5" /> Request Date Change
        </Button>
      )}

      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <CalendarClock className="w-5 h-5 text-primary" /> Request Date Change
            </DialogTitle>
          </DialogHeader>
          <div className="space-y-4">
            <div className="bg-muted/50 rounded-lg p-3 text-sm">
              <p className="font-medium">{order.courses?.title || order.course?.title}</p>
              <p className="text-muted-foreground">
                Current date: {order.start_date
                  ? format(new Date(order.start_date + 'T00:00:00'), 'EEE d MMM yyyy')
                  : '—'}
              </p>
            </div>
            <div>
              <Label>Preferred New Date</Label>
              <Popover>
                <PopoverTrigger asChild>
                  <Button variant="outline" className="w-full justify-start text-left font-normal mt-1">
                    <CalendarIcon className="mr-2 h-4 w-4" />
                    {requestedDate ? format(requestedDate, 'EEE d MMM yyyy') : 'Select a date'}
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-auto p-0">
                  <Calendar
                    mode="single"
                    selected={requestedDate}
                    onSelect={setRequestedDate}
                    disabled={(d) => !isDateAvailable(d)}
                    initialFocus
                  />
                </PopoverContent>
              </Popover>
              <p className="text-xs text-muted-foreground mt-1.5">
                Only dates the trainer and venue are available are selectable.
              </p>
            </div>
            <div>
              <Label>Reason</Label>
              <Textarea
                value={reason}
                onChange={(e) => setReason(e.target.value)}
                placeholder="Why do you need to change the date?"
                rows={2}
              />
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
            <Button
              disabled={dateChangeMutation.isPending || !requestedDate}
              onClick={() => dateChangeMutation.mutate()}
            >
              {dateChangeMutation.isPending ? 'Submitting...' : 'Submit Request'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
};

export default RequestDateChange;
