import React, { useEffect, useState, useCallback } from ‘react’;
import { Form, Input, Select, Button } from ‘antd’;
import { useAuthentication } from ‘@web/modules/authentication’;
import { useRouter } from ‘next/router’;
import { useForm, Controller } from ‘react-hook-form’;
import { yupResolver } from ‘@hookform/resolvers/yup’;
import * as yup from ‘yup’;
import { enqueueSnackbar } from ‘notistack’;
import axios from ‘axios’;
import { Api, Model } from ‘@web/domain’;
import { sendUserNotification } from ‘…/utils’;

const { Option } = Select;

const schema = yup.object().shape({
  passengerName: yup.string().required(‘Passenger name is required’),
  passengerEmail: yup
    .string()
    .email(‘Invalid email’)
    .required(‘Email is required’),
  passengerPhone: yup.string().required(‘Phone number is required’),
  vehicleBrand: yup.string().required(‘Vehicle brand is required’),
  vehicleModel: yup.string().required(‘Vehicle model is required’),
  serviceType: yup.string().required(‘Service type is required’),
  pickupAddress: yup.string().required(‘Pickup address is required’),
  dropoffAddress: yup.string().required(‘Dropoff address is required’),
  tollCharges: yup.number().min(0, ‘Toll charges must be non-negative’),
});

const BookingForm = React.memo(({
  booking,
  calculateTotalCost,
}) => {
  const { control, handleSubmit, setValue } = useForm<Model.Booking>({
    resolver: yupResolver(schema),
    defaultValues: {
      passengerName: booking?.passengerName || ‘’,
      passengerEmail: booking?.passengerEmail || ‘’,
      passengerPhone: booking?.passengerPhone || ‘’,
      vehicleBrand: booking?.vehicleBrand || ‘’,
      vehicleModel: booking?.vehicleModel || ‘’,
      serviceType: booking?.serviceType || ‘’,
      pickupAddress: booking?.pickupAddress || ‘’,
      dropoffAddress: booking?.dropoffAddress || ‘’,
      tollCharges: booking?.tollCharges || 0,
    },
  });

  const { user } = useAuthentication();
  const router = useRouter();
  const [loading, setLoading] = useState(false);
  const [tollCharges, setTollCharges] = useState(0);
  const [selectedTowTruckType, setSelectedTowTruckType] = useState(‘’);
  const [distance, setDistance] = useState(0);
  const [vehicleOptions, setVehicleOptions] = useState([]);
  const [vehicleLoading, setVehicleLoading] = useState(true);

  useEffect(() => {
    const fetchVehicleOptions = async () => {
      try {
        const { data } = await axios.get(‘/api/vehicles’);
        setVehicleOptions(data);
      } catch (error) {
        console.error(‘Error fetching vehicle options:’, error);
        enqueueSnackbar(‘Failed to fetch vehicle options’, {
          variant: ‘error’,
        });
      } finally {
        setVehicleLoading(false);
      }
    };
    fetchVehicleOptions();
  }, []);

  const handleServiceTypeChange = useCallback(
    (value: string) => {
      const vehicleOption = vehicleOptions.find(
        (option) => option.serviceType === value
      );
      setValue(‘vehicleBrand’, vehicleOption?.vehicleBrand || ‘’);
      setValue(‘vehicleModel’, vehicleOption?.vehicleModel || ‘’);
      setSelectedTowTruckType(vehicleOption?._id || ‘’);
      setDistance(vehicleOption?.distance || 0);
      calculateTotalCost(vehicleOption?._id, vehicleOption?.distance, tollCharges);
    },
    [setValue, vehicleOptions, tollCharges, calculateTotalCost]
  );

  const handleTollChargesChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = parseFloat(e.target.value) || 0; // Handle NaN
    setTollCharges(value);
    calculateTotalCost(selectedTowTruckType, distance, value);
  };

  const handleBookingRequest = useCallback(
    async (data: Model.Booking) => {
      if (!user || !user.id) {
        enqueueSnackbar(
          ‘User ID is not available. Please log in and try again.’,
          { variant: ‘error’ }
        );
        return;
      }

      setLoading(true);

      try {
        const bookingData = { …data, userId: user.id };
        await Api.Booking.createOne(bookingData);
        sendUserNotification(bookingData.userId, ‘Booking Confirmation’);
        enqueueSnackbar(‘Booking submitted successfully’, {
          variant: ‘success’,
        });
        router.push(‘/’);
      } catch (error) {
        console.error(‘Error submitting booking:’, error);
        enqueueSnackbar(‘Failed to submit booking. Please try again.’, {
          variant: ‘error’,
        });
      } finally {
        setLoading(false);
      }
    },
    [user, enqueueSnackbar, router]
  );

  return (
    <Form
      layout=“vertical”
      onFinish={handleSubmit(handleBookingRequest)}
      className=“booking-form”
    >
      <Form.Item label=“Passenger name”>
        <Controller
          name=“passengerName”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Passenger email”>
        <Controller
          name=“passengerEmail”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Passenger phone number”>
        <Controller
          name=“passengerPhone”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Vehicle brand”>
        <Controller
          name=“vehicleBrand”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Vehicle model”>
        <Controller
          name=“vehicleModel”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Service type”>
        <Controller
          name=“serviceType”
          control={control}
          rules={[{ required: true }]}
          render={({ field }) => (
            <Select
              {…field}
              onChange={handleServiceTypeChange}
              placeholder=“Select service type”
              loading={vehicleLoading}
            >
              {vehicleOptions.map((option) => (
                <Option key={option._id} value={option.serviceType}>
                  {option.serviceType}
                </Option>
              ))}
            </Select>
          )}
        />
      </Form.Item>
      <Form.Item label=“Pickup address”>
        <Controller
          name=“pickupAddress”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Dropoff address”>
        <Controller
          name=“dropoffAddress”
          control={control}
          render={({ field }) => <Input {…field} />}
        />
      </Form.Item>
      <Form.Item label=“Total cost”>
        <Input
          type=“number”
          disabled
          value={calculateTotalCost(selectedTowTruckType, distance, tollCharges)}
        />
      </Form.Item>
      <Form.Item label=“Toll charges”>
        <Controller
          name=“tollCharges”
          control={control}
          render={({ field }) => (
            <Input {…field} onChange={handleTollChargesChange} />
          )}
        />
      </Form.Item>
      <Button type=“primary” htmlType=“submit” loading={loading}>
        Submit Booking
      </Button>
    </Form>
  );
});

export default BookingForm;
'use client';

import React, { useCallback, useEffect, useState, useMemo } from 'react';
import {
  CreditCardOutlined,
  EditOutlined,
  MailOutlined,
} from '@ant-design/icons';
import { Api, Model } from '@web/domain';
import { PageLayout } from '@web/layouts/Page.layout';
import { useAuthentication } from '@web/modules/authentication';
import {
  Button,
  Card,
  Col,
  DatePicker,
  Form,
  Input,
  Row,
  Select,
  Space,
  Typography,
} from 'antd';
import dayjs from 'dayjs';
import { useParams } from 'next/navigation';
import { useRouter } from 'next/router';
import { useSnackbar } from 'notistack';
import { calculateCost } from '../utils/calculateCost';
import { calculateTotalCost } from '../utils/calculateTotalCost';
import {
  sendUserNotification,
  sendDriverNotification,
} from '../utils/notifications';

const { Title, Text } = Typography;

const BookingConfirmationPage = () => {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    phone: '',
    serviceType: 'standard',
    distance: 0,
    cost: 0,
  });
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const router = useRouter();
  const params = useParams();
  const authentication = useAuthentication();
  const userId = authentication.user?.id;
  const { enqueueSnackbar } = useSnackbar();
  const [booking, setBooking] = useState<Model.Booking | null>(null);
  const [isEditing, setIsEditing] = useState(false);
  const [form] = Form.useForm();
  const [loading, setLoading] = useState(false);

  const memoizedCalculateCost = useMemo(
    () => calculateCost(formData.distance),
    [formData.distance]
  );

  const handleInputChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const { name, value } = e.target;
      setFormData((prevData) => ({
        ...prevData,
        [name]: value,
      }));
    },
    []
  );

  const handleDistanceChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const distance = parseFloat(e.target.value);
      setFormData((prevData) => ({
        ...prevData,
        distance,
        cost: calculateCost(distance),
      }));
    },
    []
  );

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setIsSubmitting(true);
    setErrorMessage('');

    try {
      await Api.Booking.createOne(formData);
      router.push('/thank-you');
    } catch (error) {
      setErrorMessage('There was an issue with your booking. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };

  useEffect(() => {
    if (!params.bookingId) return;

    const fetchBooking = async () => {
      try {
        const bookingData = await Api.Booking.findOne(params.bookingId, {
          includes: ['user'],
        });
        setBooking(bookingData);
        form.setFieldsValue({
          serviceType: bookingData.serviceType,
          name: bookingData.name,
          email: bookingData.email,
          phone: bookingData.phone,
          vehicleBrand: bookingData.vehicleBrand,
          vehicleModel: bookingData.vehicleModel,
          dateTime: dayjs(bookingData.dateTime),
          distance: bookingData.distance,
        });
        setIsEditing(true);
      } catch (error) {
        enqueueSnackbar('Failed to fetch booking details', {
          variant: 'error',
        });
      }
    };

    fetchBooking();
  }, [params.bookingId, form, enqueueSnackbar]);

  const handleEdit = async (values: any) => {
    try {
      const updatedBooking = await Api.Booking.updateOne(params.bookingId, {
        ...values,
        dateTime: values.dateTime.toISOString(),
      });
      setBooking(updatedBooking);
      setIsEditing(false);
      enqueueSnackbar('Booking details updated successfully', {
        variant: 'success',
      });
    } catch (error) {
      enqueueSnackbar('Failed to update booking details', { variant: 'error' });
    }
  };

  const handleEmailSend = async () => {
    try {
      await Api.Notification.createOneByUserId(userId, {
        title: 'Booking Confirmation',
        message: `Your booking details: ${JSON.stringify(booking, null, 2)}`,
        userId: userId,
      });
      enqueueSnackbar('Booking details sent via email', { variant: 'success' });
    } catch (error) {
      enqueueSnackbar('Failed to send booking details via email', {
        variant: 'error',
      });
    }
  };

  const handleProceedToPayment = () => {
    router.push('/payment');
  };

  useEffect(() => {
    const initMap = () => {
      if (!window.google) return;
      const map = new google.maps.Map(document.getElementById('map'), {
        center: { lat: -34.397, lng: 150.644 },
        zoom: 8,
      });
    };
    initMap();
  }, []);

  return (
    <PageLayout layout="narrow">
      <Title level={2}>Booking Confirmation</Title>
      <Text>Review and confirm your booking details below:</Text>
      <Card style={{ marginTop: 20 }}>
        {isEditing ? (
          <Form form={form} onFinish={handleEdit} layout="vertical">
            <Form.Item
              name="serviceType"
              label="Service Type"
              rules={[
                { required: true, message: 'Please select the service type!' },
              ]}
            >
              <Select>
                <Select.Option value="standard">Standard</Select.Option>
                <Select.Option value="premium">Premium</Select.Option>
              </Select>
            </Form.Item>
            <Form.Item
              name="name"
              label="Name"
              rules={[{ required: true, message: 'Please input your name!' }]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name="email"
              label="Email"
              rules={[
                { required: true, message: 'Please input your email!' },
                { type: 'email', message: 'Please enter a valid email!' },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name="phone"
              label="Phone"
              rules={[
                { required: true, message: 'Please input your phone number!' },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name="vehicleBrand"
              label="Vehicle Brand"
              rules={[
                { required: true, message: 'Please input your vehicle brand!' },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name="vehicleModel"
              label="Vehicle Model"
              rules={[
                { required: true, message: 'Please input your vehicle model!' },
              ]}
            >
              <Input />
            </Form.Item>
            <Form.Item
              name="dateTime"
              label="Date and Time"
              rules={[
                { required: true, message: 'Please select date and time!' },
              ]}
            >
              <DatePicker showTime />
            </Form.Item>
            <Form.Item
              name="distance"
              label="Distance (in km)"
              rules={[
                { required: true, message: 'Please input the distance!' },
              ]}
            >
              <Input type="number" onChange={handleDistanceChange} />
            </Form.Item>
            <Form.Item name="cost" label="Estimated Cost">
              <Input readOnly value={memoizedCalculateCost} />
            </Form.Item>
            <div id="map" style={{ height: '400px', width: '100%' }}></div>
            <Form.Item>
              <Button type="primary" htmlType="submit">
                Save
              </Button>
              <Button
                type="default"
                onClick={() => setIsEditing(false)}
                style={{ marginLeft: 10 }}
              >
                Cancel
              </Button>
            </Form.Item>
          </Form>
        ) : (
          <div>
            <Row gutter={[16, 16]}>
              <Col span={12}>
                <Text strong>Service Type:</Text> {booking?.serviceType}
              </Col>
              <Col span={12}>
                <Text strong>Name:</Text> {booking?.name}
              </Col>
              <Col span={12}>
                <Text strong>Email:</Text> {booking?.email}
              </Col>
              <Col span={12}>
                <Text strong>Phone:</Text> {booking?.phone}
              </Col>
              <Col span={12}>
                <Text strong>Vehicle Brand:</Text> {booking?.vehicleBrand}
              </Col>
              <Col span={12}>
                <Text strong>Vehicle Model:</Text> {booking?.vehicleModel}
              </Col>
              <Col span={12}>
                <Text strong>Date and Time:</Text>{' '}
                {dayjs(booking?.dateTime).format('YYYY-MM-DD HH:mm')}
              </Col>
              <Col span={12}>
                <Text strong>Distance:</Text> {booking?.distance} km
              </Col>
              <Col span={12}>
                <Text strong>Estimated Cost:</Text> $
                {booking?.cost?.toFixed(2)}
              </Col>
            </Row>
            <Button
              type="primary"
              icon={<EditOutlined />}
              onClick={() => setIsEditing(true)}
              style={{ marginTop: 20 }}
            >
              Edit
            </Button>
          </div>
        )}
      </Card>
      <Space style={{ marginTop: 20 }}>
        <Button
          type="primary"
          icon={<MailOutlined />}
          onClick={handleEmailSend}
        >
          Send Email
        </Button>
        <Button
          type="primary"
          icon={<CreditCardOutlined />}
          onClick={handleProceedToPayment}
        >
          Proceed to Payment
        </Button>
      </Space>
    </PageLayout>
  );
};

export default BookingConfirmationPage;