import { useState, useMemo, useEffect, useCallback } from 'react';
import { Layout, Card, Table, Typography, Alert, Modal, Button, Breadcrumb, Tag, message } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { request } from '../api/client';
import { useNavigate } from 'react-router-dom';
import { useAppContext } from '../store/AppContext';
import { ROUTES } from '../router/routes.constant';

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 MemberReservationsPage() {
  const [messageApi, contextHolder] = message.useMessage();
  const navigate = useNavigate();
  const { currentUser } = useAppContext();

  const [activeReservations, setActiveReservations] = useState<ReservationResponse[]>([]);
  const [pastReservations, setPastReservations] = useState<ReservationResponse[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const [cancelModalVisible, setCancelModalVisible] = useState<boolean>(false);
  const [selectedReservationId, setSelectedReservationId] = useState<string | null>(null);
  const [cancelLoading, setCancelLoading] = useState<boolean>(false);

  const activeCount = useMemo(() => activeReservations.length, [activeReservations]);

  const fetchActiveReservations = useCallback(async () => {
    if (!currentUser?.memberId) return;
    try {
      const pendingResult = await request<ReservationResponse[]>({
        method: 'GET',
        path: '/circulation/reservations',
        query: {
          member_id: currentUser.memberId,
          reservation_status: 'PENDING',
          limit: 50
        }
      });

      const readyResult = await request<ReservationResponse[]>({
        method: 'GET',
        path: '/circulation/reservations',
        query: {
          member_id: currentUser.memberId,
          reservation_status: 'READY',
          limit: 50
        }
      });

      const combined = [...(pendingResult.data || []), ...(readyResult.data || [])];
      setActiveReservations(combined);
    } catch (error) {
      messageApi.error('Failed to load active reservations');
    }
  }, [currentUser, messageApi]);

  const fetchPastReservations = useCallback(async () => {
    if (!currentUser?.memberId) return;
    try {
      const result = await request<ReservationResponse[]>({
        method: 'GET',
        path: '/circulation/reservations',
        query: {
          member_id: currentUser.memberId,
          limit: 50
        }
      });

      const past = (result.data || []).filter(
        (r) => r.status === 'FULFILLED' || r.status === 'CANCELLED' || r.status === 'EXPIRED'
      );
      setPastReservations(past);
    } catch (error) {
      messageApi.error('Failed to load past reservations');
    }
  }, [currentUser, messageApi]);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      await Promise.all([fetchActiveReservations(), fetchPastReservations()]);
      setLoading(false);
    };
    fetchData();
  }, [fetchActiveReservations, fetchPastReservations]);

  const openCancelModal = useCallback((reservationId: string) => {
    setCancelModalVisible(true);
    setSelectedReservationId(reservationId);
  }, []);

  const closeCancelModal = useCallback(() => {
    setCancelModalVisible(false);
    setSelectedReservationId(null);
  }, []);

  const cancelReservation = useCallback(async () => {
    if (!selectedReservationId) return;

    setCancelLoading(true);
    try {
      await request<ReservationResponse>({
        method: 'POST',
        path: '/circulation/reservations/{reservation_id}/cancel',
        pathParams: { reservation_id: selectedReservationId }
      });

      messageApi.success('Reservation cancelled successfully');
      setCancelModalVisible(false);
      setSelectedReservationId(null);
      await Promise.all([fetchActiveReservations(), fetchPastReservations()]);
    } catch (error) {
      messageApi.error('Failed to cancel reservation. Please try again.');
    } finally {
      setCancelLoading(false);
    }
  }, [selectedReservationId, messageApi, fetchActiveReservations, fetchPastReservations]);

  const navigateToDashboard = useCallback(() => {
    navigate(ROUTES.MEMBER_DASHBOARD || '/member/dashboard');
  }, [navigate]);

  const handleRowClick = useCallback(
    (record: ReservationResponse) => {
      navigate(`/catalog/${record.book_id}`);
    },
    [navigate]
  );

  const getStatusColor = (status: string): string => {
    switch (status) {
      case 'PENDING':
        return 'blue';
      case 'READY':
        return 'green';
      case 'FULFILLED':
        return 'success';
      case 'CANCELLED':
        return 'default';
      case 'EXPIRED':
        return 'red';
      default:
        return 'default';
    }
  };

  const activeColumns = useMemo(
    () => [
      {
        title: 'Book Title',
        dataIndex: 'book_id',
        key: 'book_id'
      },
      {
        title: 'Reservation Date',
        dataIndex: 'reservation_date',
        key: 'reservation_date',
        render: (date: string) => new Date(date).toLocaleDateString()
      },
      {
        title: 'Queue Position',
        dataIndex: 'queue_position',
        key: 'queue_position'
      },
      {
        title: 'Status',
        dataIndex: 'status',
        key: 'status',
        render: (status: string) => <Tag color={getStatusColor(status)}>{status}</Tag>
      },
      {
        title: 'Expiry Date',
        dataIndex: 'expiry_date',
        key: 'expiry_date',
        render: (date: string | null) => (date ? new Date(date).toLocaleDateString() : '-')
      },
      {
        title: 'Actions',
        key: 'actions',
        render: (_: unknown, record: ReservationResponse) => (
          <Button
            type="link"
            danger
            onClick={(e) => {
              e.stopPropagation();
              openCancelModal(record.id);
            }}
          >
            Cancel
          </Button>
        )
      }
    ],
    [openCancelModal]
  );

  const pastColumns = useMemo(
    () => [
      {
        title: 'Book Title',
        dataIndex: 'book_id',
        key: 'book_id'
      },
      {
        title: 'Reservation Date',
        dataIndex: 'reservation_date',
        key: 'reservation_date',
        render: (date: string) => new Date(date).toLocaleDateString()
      },
      {
        title: 'Status',
        dataIndex: 'status',
        key: 'status',
        render: (status: string) => <Tag color={getStatusColor(status)}>{status}</Tag>
      },
      {
        title: 'Resolution Date',
        dataIndex: 'updated_at',
        key: 'updated_at',
        render: (date: string) => new Date(date).toLocaleDateString()
      }
    ],
    []
  );

  return (
    <div
      style={{
        minHeight: '100vh',
        height: '100%',
        width: '100%',
        display: 'flex',
        flexDirection: 'column'
      }}
    >
      {contextHolder}
      <Layout style={{ minHeight: '100vh', width: '100%', padding: '24px', background: '#f5f5f5' }}>
        <div style={{ marginBottom: '24px' }}>
          <Button
            type="link"
            icon={<ArrowLeftOutlined />}
            onClick={navigateToDashboard}
            style={{ marginBottom: '16px' }}
          >
            Back to Dashboard
          </Button>
          <Breadcrumb
            style={{ marginBottom: '16px' }}
            items={[
              { title: 'Home', href: '/member/dashboard' },
              { title: 'My Reservations' }
            ]}
          />
          <Typography.Title level={2} style={{ marginBottom: '8px' }}>
            My Reservations
          </Typography.Title>
          <Typography.Text type="secondary">
            Manage your book reservations and track their status
          </Typography.Text>
        </div>

        <Alert
          type="info"
          showIcon
          message="Reservation Rules"
          description="When a reserved book becomes available, you have a 3-day pickup window to collect it. If not picked up within this period, the reservation will expire and the book will be offered to the next person in the queue. You may have a maximum of 5 active reservations at any time."
          style={{ marginBottom: '24px' }}
        />

        <Card bordered style={{ marginBottom: '24px' }}>
          <Typography.Title level={4} style={{ marginBottom: '16px' }}>
            Active Reservations
          </Typography.Title>
          <Table
            columns={activeColumns}
            dataSource={activeReservations}
            rowKey="id"
            pagination={false}
            loading={loading}
            locale={{ emptyText: 'No active reservations' }}
            onRow={(record) => ({
              onClick: () => handleRowClick(record),
              style: { cursor: 'pointer' }
            })}
          />
        </Card>

        <Card bordered style={{ marginBottom: '24px' }}>
          <Typography.Title level={4} style={{ marginBottom: '16px' }}>
            Past Reservations
          </Typography.Title>
          <Table
            columns={pastColumns}
            dataSource={pastReservations}
            rowKey="id"
            pagination={{ pageSize: 10 }}
            loading={loading}
            locale={{ emptyText: 'No past reservations' }}
          />
        </Card>

        <Modal
          title="Cancel Reservation"
          open={cancelModalVisible}
          onOk={cancelReservation}
          onCancel={closeCancelModal}
          okText="Yes, Cancel"
          cancelText="No, Keep It"
          okButtonProps={{ danger: true, loading: cancelLoading }}
          centered
        >
          <Typography.Text>
            Are you sure you want to cancel this reservation? This action cannot be undone. You will
            lose your position in the queue and will need to create a new reservation if you change
            your mind.
          </Typography.Text>
        </Modal>
      </Layout>
    </div>
  );
}