import { useCallback, useEffect, useRef, useState } from 'react';
import {
  Table,
  Button,
  Upload,
  Modal,
  Form,
  Input,
  Select,
  Tag,
  Space,
  message,
  Tooltip,
  Switch,
  Empty,
} from 'antd';
import type { UploadProps, UploadFile } from 'antd/es/upload/interface';
import type { ColumnsType } from 'antd/es/table';
import {
  UploadOutlined,
  DeleteOutlined,
  EditOutlined,
  LinkOutlined,
  FilePdfOutlined,
  FileTextOutlined,
  FileExcelOutlined,
  FileWordOutlined,
  FileZipOutlined,
  FileOutlined,
} from '@ant-design/icons';
import { mediaApi } from '@/lib/media-api';
import { getErrorMessage } from '@/utils/getErrorMessage';

interface DocumentRow {
  id: string;
  path: string;
  filename: string;
  originalFilename: string | null;
  title: string | null;
  description: string | null;
  mimeType: string;
  fileSize: string | null;
  pageCount: number | null;
  thumbnailPath: string | null;
  category: string | null;
  tags: string[] | null;
  isPublished: boolean;
  position: number | null;
  downloadCount: number;
  createdAt: string;
  updatedAt: string;
}

const TAG_SUGGESTIONS = ['volunteer-resource', 'training', 'handout', 'policy'];

function formatBytes(raw: string | null | undefined): string {
  if (!raw) return '—';
  const bytes = Number(raw);
  if (!Number.isFinite(bytes) || bytes <= 0) return '—';
  const units = ['B', 'KB', 'MB', 'GB'];
  let value = bytes;
  let unit = 0;
  while (value >= 1024 && unit < units.length - 1) {
    value /= 1024;
    unit += 1;
  }
  return `${value.toFixed(unit === 0 ? 0 : 1)} ${units[unit]}`;
}

function iconForMime(mime: string) {
  if (mime.includes('pdf')) return <FilePdfOutlined style={{ fontSize: 24, color: '#d4380d' }} />;
  if (mime.includes('word')) return <FileWordOutlined style={{ fontSize: 24, color: '#1677ff' }} />;
  if (mime.includes('sheet') || mime.includes('excel') || mime.includes('csv')) {
    return <FileExcelOutlined style={{ fontSize: 24, color: '#389e0d' }} />;
  }
  if (mime.includes('zip')) return <FileZipOutlined style={{ fontSize: 24, color: '#8c8c8c' }} />;
  if (mime.startsWith('text/')) return <FileTextOutlined style={{ fontSize: 24, color: '#595959' }} />;
  return <FileOutlined style={{ fontSize: 24, color: '#8c8c8c' }} />;
}

function normalizeTags(raw: unknown): string[] {
  if (!raw) return [];
  if (Array.isArray(raw)) return raw.filter((t): t is string => typeof t === 'string');
  return [];
}

export default function DocumentsTab() {
  const [documents, setDocuments] = useState<DocumentRow[]>([]);
  const [loading, setLoading] = useState(false);
  const [uploadModalOpen, setUploadModalOpen] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [editingDoc, setEditingDoc] = useState<DocumentRow | null>(null);
  const [uploadForm] = Form.useForm();
  const [editForm] = Form.useForm();
  const pendingFile = useRef<File | null>(null);

  const fetchDocuments = useCallback(async () => {
    setLoading(true);
    try {
      const { data } = await mediaApi.get<{ items: DocumentRow[] }>('/documents', {
        params: { published: 'false' },
      });
      const items = (data.items || []).map((d) => ({
        ...d,
        tags: normalizeTags(d.tags),
      }));
      setDocuments(items);
    } catch (error: unknown) {
      message.error(getErrorMessage(error, 'Failed to load documents'));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const handleUpload = async () => {
    if (!pendingFile.current) {
      message.warning('Please select a file first');
      return;
    }

    try {
      const values = await uploadForm.validateFields();
      setUploading(true);

      const formData = new FormData();
      formData.append('file', pendingFile.current);
      if (values.title) formData.append('title', values.title);
      if (values.tags && values.tags.length > 0) {
        formData.append('tags', JSON.stringify(values.tags));
      }
      if (values.category) formData.append('category', values.category);
      if (values.description) formData.append('description', values.description);

      await mediaApi.post('/documents/upload', formData, {
        headers: { 'Content-Type': 'multipart/form-data' },
      });

      message.success('Document uploaded');
      setUploadModalOpen(false);
      uploadForm.resetFields();
      pendingFile.current = null;
      await fetchDocuments();
    } catch (error: unknown) {
      if (error instanceof Error && 'errorFields' in error) return;
      message.error(getErrorMessage(error, 'Upload failed'));
    } finally {
      setUploading(false);
    }
  };

  const handleEdit = (doc: DocumentRow) => {
    setEditingDoc(doc);
    editForm.setFieldsValue({
      title: doc.title || '',
      description: doc.description || '',
      tags: doc.tags || [],
      category: doc.category || '',
      isPublished: doc.isPublished,
      position: doc.position ?? 0,
    });
  };

  const handleSaveEdit = async () => {
    if (!editingDoc) return;
    try {
      const values = await editForm.validateFields();
      await mediaApi.put(`/documents/${editingDoc.id}`, values);
      message.success('Document updated');
      setEditingDoc(null);
      editForm.resetFields();
      await fetchDocuments();
    } catch (error: unknown) {
      if (error instanceof Error && 'errorFields' in error) return;
      message.error(getErrorMessage(error, 'Update failed'));
    }
  };

  const handleDelete = (doc: DocumentRow) => {
    Modal.confirm({
      title: 'Delete this document?',
      content: doc.title || doc.originalFilename || doc.filename,
      okText: 'Delete',
      okType: 'danger',
      onOk: async () => {
        try {
          await mediaApi.delete(`/documents/${doc.id}`);
          message.success('Document deleted');
          await fetchDocuments();
        } catch (error: unknown) {
          message.error(getErrorMessage(error, 'Delete failed'));
        }
      },
    });
  };

  const handleCopyLink = (doc: DocumentRow) => {
    const url = `${window.location.origin}/media/api/documents/${doc.id}/download`;
    navigator.clipboard.writeText(url).then(
      () => message.success('Download URL copied to clipboard'),
      () => message.error('Failed to copy URL'),
    );
  };

  const uploadProps: UploadProps = {
    beforeUpload: (file) => {
      pendingFile.current = file;
      if (!uploadForm.getFieldValue('title')) {
        uploadForm.setFieldsValue({ title: file.name });
      }
      return false;
    },
    onRemove: () => {
      pendingFile.current = null;
    },
    maxCount: 1,
    fileList: pendingFile.current
      ? [{ uid: '-1', name: pendingFile.current.name, status: 'done' } as UploadFile]
      : [],
  };

  const columns: ColumnsType<DocumentRow> = [
    {
      title: '',
      dataIndex: 'mimeType',
      width: 56,
      render: (mime: string) => iconForMime(mime),
    },
    {
      title: 'Title',
      dataIndex: 'title',
      render: (_: unknown, row) => (
        <div>
          <div style={{ fontWeight: 500 }}>{row.title || row.originalFilename || row.filename}</div>
          <div style={{ fontSize: 12, color: '#8c8c8c' }}>
            {row.originalFilename || row.filename}
          </div>
        </div>
      ),
    },
    {
      title: 'Size',
      dataIndex: 'fileSize',
      width: 90,
      render: (size: string | null) => formatBytes(size),
    },
    {
      title: 'Type',
      dataIndex: 'mimeType',
      width: 140,
      render: (mime: string) => <code style={{ fontSize: 11 }}>{mime}</code>,
    },
    {
      title: 'Tags',
      dataIndex: 'tags',
      render: (tags: string[] | null) =>
        tags && tags.length > 0 ? (
          <Space wrap size={4}>
            {tags.map((t) => (
              <Tag key={t} color={t === 'volunteer-resource' ? 'purple' : 'blue'}>
                {t}
              </Tag>
            ))}
          </Space>
        ) : (
          <span style={{ color: '#bfbfbf' }}>—</span>
        ),
    },
    {
      title: 'Downloads',
      dataIndex: 'downloadCount',
      width: 100,
      align: 'right',
    },
    {
      title: 'Status',
      dataIndex: 'isPublished',
      width: 100,
      render: (published: boolean) =>
        published ? <Tag color="green">Published</Tag> : <Tag>Draft</Tag>,
    },
    {
      title: 'Actions',
      key: 'actions',
      width: 150,
      render: (_: unknown, row) => (
        <Space size={4}>
          <Tooltip title="Copy download URL">
            <Button size="small" icon={<LinkOutlined />} onClick={() => handleCopyLink(row)} />
          </Tooltip>
          <Tooltip title="Edit">
            <Button size="small" icon={<EditOutlined />} onClick={() => handleEdit(row)} />
          </Tooltip>
          <Tooltip title="Delete">
            <Button
              size="small"
              danger
              icon={<DeleteOutlined />}
              onClick={() => handleDelete(row)}
            />
          </Tooltip>
        </Space>
      ),
    },
  ];

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
        <div style={{ color: '#999', fontSize: 13 }}>
          {documents.length} document{documents.length !== 1 ? 's' : ''}
        </div>
        <Button type="primary" icon={<UploadOutlined />} onClick={() => setUploadModalOpen(true)}>
          Upload
        </Button>
      </div>

      <Table<DocumentRow>
        rowKey="id"
        columns={columns}
        dataSource={documents}
        loading={loading}
        pagination={{ pageSize: 50, showSizeChanger: true, pageSizeOptions: [25, 50, 100] }}
        locale={{ emptyText: <Empty description="No documents uploaded yet" /> }}
      />

      <Modal
        title="Upload Document"
        open={uploadModalOpen}
        onCancel={() => {
          if (uploading) return;
          setUploadModalOpen(false);
          uploadForm.resetFields();
          pendingFile.current = null;
        }}
        onOk={handleUpload}
        confirmLoading={uploading}
        okText="Upload"
        destroyOnClose
      >
        <Form form={uploadForm} layout="vertical">
          <Form.Item label="File" required>
            <Upload.Dragger {...uploadProps}>
              <p className="ant-upload-drag-icon">
                <UploadOutlined />
              </p>
              <p className="ant-upload-text">Click or drag file to upload</p>
              <p className="ant-upload-hint" style={{ fontSize: 12 }}>
                PDF, DOC/DOCX, XLSX, CSV, TXT, MD, ZIP
              </p>
            </Upload.Dragger>
          </Form.Item>
          <Form.Item name="title" label="Title">
            <Input placeholder="Optional — defaults to filename" />
          </Form.Item>
          <Form.Item name="tags" label="Tags" tooltip="Tag with 'volunteer-resource' to surface in the volunteer dashboard">
            <Select
              mode="tags"
              placeholder="Select or type tags"
              options={TAG_SUGGESTIONS.map((t) => ({ value: t, label: t }))}
            />
          </Form.Item>
          <Form.Item name="category" label="Category">
            <Input placeholder="Optional" />
          </Form.Item>
          <Form.Item name="description" label="Description">
            <Input.TextArea rows={2} placeholder="Optional" />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title="Edit Document"
        open={!!editingDoc}
        onCancel={() => {
          setEditingDoc(null);
          editForm.resetFields();
        }}
        onOk={handleSaveEdit}
        okText="Save"
        destroyOnClose
      >
        <Form form={editForm} layout="vertical">
          <Form.Item name="title" label="Title">
            <Input />
          </Form.Item>
          <Form.Item name="description" label="Description">
            <Input.TextArea rows={2} />
          </Form.Item>
          <Form.Item name="tags" label="Tags">
            <Select
              mode="tags"
              options={TAG_SUGGESTIONS.map((t) => ({ value: t, label: t }))}
            />
          </Form.Item>
          <Form.Item name="category" label="Category">
            <Input />
          </Form.Item>
          <Form.Item name="position" label="Position">
            <Input type="number" />
          </Form.Item>
          <Form.Item name="isPublished" label="Published" valuePropName="checked">
            <Switch />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
