import { useState, useMemo, useEffect, useCallback } from 'react';
import { Table, Button, Input, Modal, Form, Select, Card, Typography, Breadcrumb, message } from 'antd';
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
import { request } from '../api/client';
import { useNavigate } from 'react-router-dom';

interface CategoryResponse {
  id: string;
  name: string;
  description: string | null;
  parent_category_id: string | null;
  created_at: string;
  updated_at: string;
}

interface CategoryCreate {
  name: string;
  description?: string | null;
  parent_category_id?: string | null;
}

interface CategoryUpdate {
  name?: string | null;
  description?: string | null;
  parent_category_id?: string | null;
}

export default function CategoriesListPage() {
  const [messageApi, contextHolder] = message.useMessage();
  const navigate = useNavigate();
  const [addForm] = Form.useForm();
  const [editForm] = Form.useForm();

  const [categories, setCategories] = useState<CategoryResponse[]>([]);
  const [searchText, setSearchText] = useState<string>('');
  const [isAddModalVisible, setIsAddModalVisible] = useState<boolean>(false);
  const [isEditModalVisible, setIsEditModalVisible] = useState<boolean>(false);
  const [isDeleteModalVisible, setIsDeleteModalVisible] = useState<boolean>(false);
  const [selectedCategoryId, setSelectedCategoryId] = useState<string | null>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [pagination, setPagination] = useState({ limit: 20, offset: 0 });

  const selectedCategory = useMemo(() => {
    return categories.find(c => c.id === selectedCategoryId);
  }, [categories, selectedCategoryId]);

  const parentCategoryOptions = useMemo(() => {
    return categories
      .filter(c => c.id !== selectedCategoryId)
      .map(c => ({ label: c.name, value: c.id }));
  }, [categories, selectedCategoryId]);

  const fetchCategories = useCallback(async () => {
    setLoading(true);
    try {
      const result = await request<CategoryResponse[]>({
        method: 'GET',
        path: '/categories',
        query: {
          limit: pagination.limit,
          offset: pagination.offset,
          search: searchText || undefined
        }
      });
      setCategories(result.data);
    } catch (error) {
      messageApi.error('Failed to load categories');
    } finally {
      setLoading(false);
    }
  }, [pagination.limit, pagination.offset, searchText, messageApi]);

  useEffect(() => {
    fetchCategories();
  }, [fetchCategories]);

  const onSearchChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchText(e.target.value);
    setPagination(prev => ({ ...prev, offset: 0 }));
  }, []);

  const onPaginationChange = useCallback((page: number, pageSize: number) => {
    setPagination({ limit: pageSize, offset: (page - 1) * pageSize });
  }, []);

  const openAddModal = useCallback(() => {
    setIsAddModalVisible(true);
    setSelectedCategoryId(null);
    addForm.resetFields();
  }, [addForm]);

  const closeAddModal = useCallback(() => {
    setIsAddModalVisible(false);
    addForm.resetFields();
  }, [addForm]);

  const openEditModal = useCallback((record: CategoryResponse) => {
    setIsEditModalVisible(true);
    setSelectedCategoryId(record.id);
    editForm.setFieldsValue({
      name: record.name,
      description: record.description,
      parent_category_id: record.parent_category_id
    });
  }, [editForm]);

  const closeEditModal = useCallback(() => {
    setIsEditModalVisible(false);
    setSelectedCategoryId(null);
    editForm.resetFields();
  }, [editForm]);

  const openDeleteModal = useCallback((record: CategoryResponse) => {
    setIsDeleteModalVisible(true);
    setSelectedCategoryId(record.id);
  }, []);

  const closeDeleteModal = useCallback(() => {
    setIsDeleteModalVisible(false);
    setSelectedCategoryId(null);
  }, []);

  const handleAddCategory = useCallback(async () => {
    try {
      const values = await addForm.validateFields();
      const body: CategoryCreate = {
        name: values.name,
        description: values.description || null,
        parent_category_id: values.parent_category_id || null
      };
      await request<CategoryResponse>({
        method: 'POST',
        path: '/categories',
        body
      });
      messageApi.success('Category created successfully');
      closeAddModal();
      fetchCategories();
    } catch (error) {
      messageApi.error('Failed to create category');
    }
  }, [addForm, messageApi, closeAddModal, fetchCategories]);

  const handleEditCategory = useCallback(async () => {
    if (!selectedCategoryId) return;
    try {
      const values = await editForm.validateFields();
      const body: CategoryUpdate = {
        name: values.name,
        description: values.description || null,
        parent_category_id: values.parent_category_id || null
      };
      await request<CategoryResponse>({
        method: 'PUT',
        path: '/categories/{category_id}',
        pathParams: { category_id: selectedCategoryId },
        body
      });
      messageApi.success('Category updated successfully');
      closeEditModal();
      fetchCategories();
    } catch (error) {
      messageApi.error('Failed to update category');
    }
  }, [selectedCategoryId, editForm, messageApi, closeEditModal, fetchCategories]);

  const handleDeleteCategory = useCallback(async () => {
    if (!selectedCategoryId) return;
    try {
      await request({
        method: 'DELETE',
        path: '/categories/{category_id}',
        pathParams: { category_id: selectedCategoryId }
      });
      messageApi.success('Category deleted successfully');
      closeDeleteModal();
      fetchCategories();
    } catch (error) {
      messageApi.error('Failed to delete category. It may have books assigned.');
    }
  }, [selectedCategoryId, messageApi, closeDeleteModal, fetchCategories]);

  const navigateToDashboard = useCallback(() => {
    navigate('/admin/dashboard');
  }, [navigate]);

  const navigateToBooks = useCallback(() => {
    navigate('/admin/books');
  }, [navigate]);

  const getParentCategoryName = useCallback((parentId: string | null) => {
    if (!parentId) return '-';
    const parent = categories.find(c => c.id === parentId);
    return parent ? parent.name : '-';
  }, [categories]);

  const columns = useMemo(() => [
    {
      title: 'Name',
      dataIndex: 'name',
      key: 'name',
      sorter: (a: CategoryResponse, b: CategoryResponse) => a.name.localeCompare(b.name)
    },
    {
      title: 'Description',
      dataIndex: 'description',
      key: 'description',
      ellipsis: true,
      render: (text: string | null) => text || '-'
    },
    {
      title: 'Parent Category',
      dataIndex: 'parent_category_id',
      key: 'parent_category_id',
      render: (parentId: string | null) => getParentCategoryName(parentId)
    },
    {
      title: 'Created',
      dataIndex: 'created_at',
      key: 'created_at',
      render: (date: string) => new Date(date).toLocaleDateString()
    },
    {
      title: 'Actions',
      key: 'actions',
      render: (_: unknown, record: CategoryResponse) => (
        <>
          <Button
            type="link"
            icon={<EditOutlined />}
            size="small"
            onClick={() => openEditModal(record)}
          >
            Edit
          </Button>
          <Button
            type="link"
            danger
            icon={<DeleteOutlined />}
            size="small"
            onClick={() => openDeleteModal(record)}
          >
            Delete
          </Button>
        </>
      )
    }
  ], [getParentCategoryName, openEditModal, openDeleteModal]);

  return (
    <div style={{ minHeight: '100vh', height: '100%', width: '100%', display: 'flex', flexDirection: 'column', padding: '24px', background: '#f5f5f5' }}>
      {contextHolder}
      <div style={{ marginBottom: '24px', display: 'flex', flexDirection: 'column', gap: '4px' }}>
        <Breadcrumb style={{ marginBottom: '16px' }}>
          <Breadcrumb.Item>
            <span style={{ cursor: 'pointer' }} onClick={navigateToDashboard}>Dashboard</span>
          </Breadcrumb.Item>
          <Breadcrumb.Item>Categories Management</Breadcrumb.Item>
        </Breadcrumb>
        <Typography.Title level={2} style={{ marginBottom: '0' }}>
          Categories Management
        </Typography.Title>
        <Typography.Text type="secondary">
          Manage hierarchical book categories. Create, edit, and organize categories for the library catalog.
        </Typography.Text>
      </div>

      <Card bordered={false} style={{ borderRadius: '6px' }}>
        <div style={{ marginBottom: '16px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: '12px' }}>
          <Input.Search
            placeholder="Search categories by name..."
            allowClear
            style={{ width: 300 }}
            value={searchText}
            onChange={onSearchChange}
          />
          <Button type="primary" icon={<PlusOutlined />} onClick={openAddModal}>
            Add Category
          </Button>
        </div>

        <Table
          columns={columns}
          dataSource={categories}
          rowKey="id"
          loading={loading}
          pagination={{
            pageSize: pagination.limit,
            current: Math.floor(pagination.offset / pagination.limit) + 1,
            total: categories.length,
            showSizeChanger: true,
            showTotal: (total) => `Total ${total} items`,
            onChange: onPaginationChange
          }}
        />
      </Card>

      <Modal
        title="Add New Category"
        open={isAddModalVisible}
        onOk={handleAddCategory}
        onCancel={closeAddModal}
        okText="Create"
        cancelText="Cancel"
        destroyOnClose
      >
        <Form form={addForm} layout="vertical">
          <Form.Item
            name="name"
            label="Category Name"
            rules={[{ required: true, message: 'Please enter category name' }]}
          >
            <Input placeholder="Enter category name" />
          </Form.Item>
          <Form.Item name="description" label="Description">
            <Input.TextArea placeholder="Enter category description (optional)" rows={3} />
          </Form.Item>
          <Form.Item name="parent_category_id" label="Parent Category">
            <Select
              placeholder="Select parent category (optional)"
              allowClear
              showSearch
              optionFilterProp="label"
              options={parentCategoryOptions}
              style={{ width: '100%' }}
            />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title="Edit Category"
        open={isEditModalVisible}
        onOk={handleEditCategory}
        onCancel={closeEditModal}
        okText="Save"
        cancelText="Cancel"
        destroyOnClose
      >
        <Form form={editForm} layout="vertical">
          <Form.Item
            name="name"
            label="Category Name"
            rules={[{ required: true, message: 'Please enter category name' }]}
          >
            <Input placeholder="Enter category name" />
          </Form.Item>
          <Form.Item name="description" label="Description">
            <Input.TextArea placeholder="Enter category description (optional)" rows={3} />
          </Form.Item>
          <Form.Item name="parent_category_id" label="Parent Category">
            <Select
              placeholder="Select parent category (optional)"
              allowClear
              showSearch
              optionFilterProp="label"
              options={parentCategoryOptions}
              style={{ width: '100%' }}
            />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title="Delete Category"
        open={isDeleteModalVisible}
        onOk={handleDeleteCategory}
        onCancel={closeDeleteModal}
        okText="Delete"
        okButtonProps={{ danger: true }}
        cancelText="Cancel"
      >
        <Typography.Text>
          Are you sure you want to delete this category? This action cannot be undone. Categories with assigned books cannot be deleted.
        </Typography.Text>
      </Modal>
    </div>
  );
}