import { useState, useMemo, useEffect, useCallback } from 'react';
import { Card, Typography, Tag, Button, Rate, Descriptions, List, Form, Input, Modal, Spin, Empty, Breadcrumb, Image, message } from 'antd';
import { ArrowLeftOutlined, BookOutlined, EditOutlined } from '@ant-design/icons';
import { useNavigate, useParams } from 'react-router-dom';
import { request } from '../api/client';
import { useAppContext } from '../store/AppContext';
import { ROUTES } from '../router/routes.constant';

interface BookResponse {
  id: string;
  isbn: string | null;
  title: string;
  subtitle: string | null;
  publisher_id: string | null;
  publication_date: string | null;
  edition: string | null;
  language: string;
  pages: number | null;
  description: string | null;
  book_format: 'PHYSICAL' | 'DIGITAL';
  total_copies: number;
  available_copies: number;
  location: string | null;
  status: 'AVAILABLE' | 'CHECKED_OUT' | 'RESERVED' | 'MAINTENANCE' | 'LOST' | 'DAMAGED';
  created_at: string;
  updated_at: string;
}

interface BookAuthorResponse {
  id: string;
  book_id: string;
  author_id: string;
  author_order: number;
  created_at: string;
  updated_at: string;
}

interface BookCategoryResponse {
  id: string;
  book_id: string;
  category_id: string;
  created_at: string;
  updated_at: string;
}

interface ReviewResponse {
  id: string;
  book_id: string;
  member_id: string;
  rating: number;
  review_text: string | null;
  status: 'PUBLISHED' | 'PENDING' | 'HIDDEN' | 'FLAGGED';
  review_date: string;
  created_at: string;
  updated_at: string;
}

interface ReservationResponse {
  id: string;
  book_id: string;
  member_id: string;
  reservation_date: string;
  expiry_date: string | null;
  queue_position: number;
  status: 'PENDING' | 'READY' | 'FULFILLED' | 'CANCELLED' | 'EXPIRED';
  notified_date: string | null;
  created_at: string;
  updated_at: string;
}

export default function BookDetailPage() {
  const { bookId } = useParams<{ bookId: string }>();
  const navigate = useNavigate();
  const { currentUser } = useAppContext();
  const [messageApi, contextHolder] = message.useMessage();
  const [form] = Form.useForm();

  const [book, setBook] = useState<BookResponse | null>(null);
  const [bookAuthors, setBookAuthors] = useState<BookAuthorResponse[]>([]);
  const [bookCategories, setBookCategories] = useState<BookCategoryResponse[]>([]);
  const [reviews, setReviews] = useState<ReviewResponse[]>([]);
  const [relatedBooks, setRelatedBooks] = useState<BookResponse[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const [reviewModalVisible, setReviewModalVisible] = useState<boolean>(false);
  const [submittingReview, setSubmittingReview] = useState<boolean>(false);
  const [reserving, setReserving] = useState<boolean>(false);

  const availabilityText = useMemo(() => {
    return book ? `${book.available_copies} of ${book.total_copies} copies available` : '';
  }, [book]);

  const averageRating = useMemo(() => {
    if (reviews.length === 0) return 0;
    const sum = reviews.reduce((acc, r) => acc + r.rating, 0);
    return parseFloat((sum / reviews.length).toFixed(1));
  }, [reviews]);

  const reviewCount = useMemo(() => reviews.length, [reviews]);

  const canReserve = useMemo(() => {
    return !!(currentUser && book && book.available_copies === 0);
  }, [currentUser, book]);

  const canAddReview = useMemo(() => {
    return !!(currentUser);
  }, [currentUser]);

  const fetchBookDetails = useCallback(async () => {
    if (!bookId) return;
    try {
      setLoading(true);
      const { data: bookData } = await request<BookResponse>({
        method: 'GET',
        path: '/books/{book_id}',
        pathParams: { book_id: bookId }
      });
      setBook(bookData);
    } catch (error) {
      messageApi.error('Failed to load book details');
    } finally {
      setLoading(false);
    }
  }, [bookId, messageApi]);

  const fetchBookAuthors = useCallback(async () => {
    if (!bookId) return;
    try {
      const { data } = await request<BookAuthorResponse[]>({
        method: 'GET',
        path: '/book-authors',
        query: { book_id: bookId, limit: 50 }
      });
      setBookAuthors(data);
    } catch (error) {
      messageApi.error('Failed to load book authors');
    }
  }, [bookId, messageApi]);

  const fetchBookCategories = useCallback(async () => {
    if (!bookId) return;
    try {
      const { data } = await request<BookCategoryResponse[]>({
        method: 'GET',
        path: '/book-categories',
        query: { book_id: bookId, limit: 50 }
      });
      setBookCategories(data);
    } catch (error) {
      messageApi.error('Failed to load book categories');
    }
  }, [bookId, messageApi]);

  const fetchBookReviews = useCallback(async () => {
    if (!bookId) return;
    try {
      const { data } = await request<ReviewResponse[]>({
        method: 'GET',
        path: '/engagement/reviews',
        query: { book_id: bookId, status: 'PUBLISHED', limit: 50 }
      });
      setReviews(data);
    } catch (error) {
      messageApi.error('Failed to load reviews');
    }
  }, [bookId, messageApi]);

  const fetchRelatedBooks = useCallback(async () => {
    try {
      const { data } = await request<BookResponse[]>({
        method: 'GET',
        path: '/books',
        query: { limit: 6 }
      });
      setRelatedBooks(data);
    } catch (error) {
      messageApi.error('Failed to load related books');
    }
  }, [messageApi]);

  useEffect(() => {
    fetchBookDetails();
    fetchBookAuthors();
    fetchBookCategories();
    fetchBookReviews();
    fetchRelatedBooks();
  }, [fetchBookDetails, fetchBookAuthors, fetchBookCategories, fetchBookReviews, fetchRelatedBooks]);

  const openReviewModal = useCallback(() => {
    setReviewModalVisible(true);
  }, []);

  const closeReviewModal = useCallback(() => {
    setReviewModalVisible(false);
    form.resetFields();
  }, [form]);

  const reserveBook = useCallback(async () => {
    if (!bookId || !currentUser) return;

    Modal.confirm({
      title: 'Reserve Book',
      content: 'Are you sure you want to reserve this book?',
      onOk: async () => {
        try {
          setReserving(true);
          await request<ReservationResponse>({
            method: 'POST',
            path: '/circulation/reservations',
            body: {
              book_id: bookId,
              member_id: currentUser.id,
              reservation_date: new Date().toISOString(),
              queue_position: 1,
              status: 'PENDING'
            }
          });
          messageApi.success('Book reserved successfully! You will be notified when it becomes available.');
          await fetchBookDetails();
        } catch (error) {
          messageApi.error('Failed to reserve book. Please try again.');
        } finally {
          setReserving(false);
        }
      }
    });
  }, [bookId, currentUser, messageApi, fetchBookDetails]);

  const submitReview = useCallback(async () => {
    if (!bookId || !currentUser) return;

    try {
      const values = await form.validateFields();
      
      if (!values.rating) {
        messageApi.error('Please select a star rating');
        return;
      }

      if (values.review_text && values.review_text.length > 1000) {
        messageApi.error('Review must be 1000 characters or less');
        return;
      }

      setSubmittingReview(true);
      await request<ReviewResponse>({
        method: 'POST',
        path: '/engagement/reviews',
        body: {
          book_id: bookId,
          member_id: currentUser.id,
          rating: values.rating,
          review_text: values.review_text || null,
          status: 'PUBLISHED',
          review_date: new Date().toISOString()
        }
      });
      
      messageApi.success('Review submitted successfully!');
      setReviewModalVisible(false);
      form.resetFields();
      await fetchBookReviews();
    } catch (error) {
      messageApi.error('Failed to submit review. Please try again.');
    } finally {
      setSubmittingReview(false);
    }
  }, [bookId, currentUser, form, messageApi, fetchBookReviews]);

  const navigateBackToCatalog = useCallback(() => {
    navigate(ROUTES.CATALOG || '/catalog');
  }, [navigate]);

  const navigateToAuthor = useCallback((authorId: string) => {
    navigate(`/authors/${authorId}`);
  }, [navigate]);

  const navigateToBook = useCallback((id: string) => {
    navigate(`/books/${id}`);
  }, [navigate]);

  if (loading) {
    return (
      <div style={{ minHeight: '100vh', height: '100%', width: '100%', display: 'flex', flexDirection: 'column' }}>
        {contextHolder}
        <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '400px' }}>
          <Spin size="large" tip="Loading book details..." />
        </div>
      </div>
    );
  }

  if (!book) {
    return (
      <div style={{ minHeight: '100vh', height: '100%', width: '100%', display: 'flex', flexDirection: 'column' }}>
        {contextHolder}
        <Empty description="Book not found" />
      </div>
    );
  }

  return (
    <div style={{ minHeight: '100vh', height: '100%', width: '100%', display: 'flex', flexDirection: 'column' }}>
      {contextHolder}
      <div style={{ minHeight: '100vh', width: '100%', padding: '24px', maxWidth: '1200px', margin: '0 auto' }}>
        <Breadcrumb
          style={{ marginBottom: '16px' }}
          items={[
            { title: 'Catalog', href: '/catalog' },
            { title: 'Book Details' }
          ]}
        />

        <Button
          type="link"
          icon={<ArrowLeftOutlined />}
          onClick={navigateBackToCatalog}
          style={{ marginBottom: '16px', paddingLeft: '0' }}
        >
          Back to Catalog
        </Button>

        <div style={{ marginBottom: '32px', display: 'flex', flexDirection: 'row', gap: '32px' }}>
          <div style={{ width: '300px', minWidth: '200px', flexShrink: 0 }}>
            <Image
              src="/placeholder-book-cover.png"
              alt="Book cover"
              width="100%"
              height={400}
              fallback="/placeholder-book-cover.png"
              style={{ borderRadius: '8px', objectFit: 'cover' }}
            />
          </div>

          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' }}>
            <Typography.Title level={2} style={{ marginBottom: '4px' }}>
              {book.title}
            </Typography.Title>

            {book.subtitle && (
              <Typography.Text type="secondary" style={{ fontSize: '16px', display: 'block', marginBottom: '12px' }}>
                {book.subtitle}
              </Typography.Text>
            )}

            <div style={{ marginBottom: '12px', display: 'flex', flexDirection: 'row', gap: '8px' }}>
              {bookAuthors.map((ba) => (
                <Button
                  key={ba.id}
                  type="link"
                  onClick={() => navigateToAuthor(ba.author_id)}
                  style={{ padding: '0', height: 'auto' }}
                >
                  Author {ba.author_id}
                </Button>
              ))}
            </div>

            <div style={{ marginBottom: '12px' }}>
              <Rate disabled allowHalf value={averageRating} />
              <Typography.Text type="secondary" style={{ marginLeft: '8px' }}>
                ({reviewCount} reviews)
              </Typography.Text>
            </div>

            <div>
              <Tag color={book.status === 'AVAILABLE' ? 'green' : 'red'} style={{ marginBottom: '16px', fontSize: '14px', padding: '4px 12px' }}>
                {book.status}
              </Tag>
              <Typography.Text style={{ marginLeft: '8px', fontSize: '14px' }}>
                {availabilityText}
              </Typography.Text>
            </div>

            <Descriptions
              column={2}
              size="small"
              bordered
              style={{ marginBottom: '16px' }}
            >
              <Descriptions.Item label="ISBN">{book.isbn || 'N/A'}</Descriptions.Item>
              <Descriptions.Item label="Publisher">{book.publisher_id || 'N/A'}</Descriptions.Item>
              <Descriptions.Item label="Publication Date">{book.publication_date || 'N/A'}</Descriptions.Item>
              <Descriptions.Item label="Edition">{book.edition || 'N/A'}</Descriptions.Item>
              <Descriptions.Item label="Language">{book.language}</Descriptions.Item>
              <Descriptions.Item label="Pages">{book.pages || 'N/A'}</Descriptions.Item>
              <Descriptions.Item label="Format">{book.book_format}</Descriptions.Item>
              <Descriptions.Item label="Shelf Location">{book.location || 'N/A'}</Descriptions.Item>
            </Descriptions>

            <div style={{ marginBottom: '16px', display: 'flex', flexDirection: 'row', gap: '8px' }}>
              <Typography.Text strong style={{ marginRight: '8px' }}>Categories:</Typography.Text>
              {bookCategories.map((bc) => (
                <Tag key={bc.id} color="blue">
                  {bc.category_id}
                </Tag>
              ))}
            </div>

            {canReserve && (
              <Button
                type="primary"
                size="large"
                icon={<BookOutlined />}
                loading={reserving}
                onClick={reserveBook}
                style={{ marginTop: '16px' }}
              >
                Reserve This Book
              </Button>
            )}
          </div>
        </div>

        <Card title="Description" style={{ marginBottom: '32px' }}>
          <Typography.Paragraph>
            {book.description || 'No description available.'}
          </Typography.Paragraph>
        </Card>

        <Card title="Reviews" style={{ marginBottom: '32px' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
            <Typography.Title level={4} style={{ margin: 0 }}>
              Reviews
            </Typography.Title>
            {canAddReview && (
              <Button type="primary" icon={<EditOutlined />} onClick={openReviewModal}>
                Add Review
              </Button>
            )}
          </div>

          {reviews.length === 0 ? (
            <Empty description="No reviews yet. Be the first to review this book!" />
          ) : (
            <List
              itemLayout="vertical"
              pagination={{ pageSize: 5 }}
              dataSource={reviews}
              renderItem={(item) => (
                <List.Item>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
                    <Rate disabled allowHalf={false} value={item.rating} />
                    <Typography.Paragraph>{item.review_text}</Typography.Paragraph>
                    <Typography.Text type="secondary">
                      {new Date(item.review_date).toLocaleDateString()}
                    </Typography.Text>
                  </div>
                </List.Item>
              )}
            />
          )}
        </Card>

        <Card title="Related Books" style={{ marginBottom: '32px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '16px' }}>
            {relatedBooks.map((relBook) => (
              <Card
                key={relBook.id}
                hoverable
                size="small"
                style={{ cursor: 'pointer' }}
                onClick={() => navigateToBook(relBook.id)}
              >
                <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
                  <Typography.Text strong ellipsis>
                    {relBook.title}
                  </Typography.Text>
                  <Tag style={{ marginTop: '8px' }}>
                    {relBook.status}
                  </Tag>
                </div>
              </Card>
            ))}
          </div>
        </Card>
      </div>

      <Modal
        title="Write a Review"
        open={reviewModalVisible}
        onOk={submitReview}
        onCancel={closeReviewModal}
        okText="Submit Review"
        cancelText="Cancel"
        destroyOnClose
        confirmLoading={submittingReview}
      >
        <Form form={form} layout="vertical">
          <Form.Item
            name="rating"
            label="Rating"
            rules={[{ required: true, message: 'Please select a rating' }]}
          >
            <Rate allowHalf={false} />
          </Form.Item>

          <Form.Item
            name="review_text"
            label="Review"
            rules={[{ max: 1000, message: 'Review must be 1000 characters or less' }]}
          >
            <Input.TextArea
              rows={6}
              maxLength={1000}
              showCount
              placeholder="Share your thoughts about this book..."
            />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}