import { useState, useEffect, useCallback } from 'react';
import {
  Button, Space, Input, Select, TreeSelect, Tree, Upload, Modal, Form,
  Switch, message, Popconfirm, Empty, Card, Checkbox, Typography, Dropdown, Spin,
} from 'antd';
import {
  UploadOutlined, FolderAddOutlined, EditOutlined, DeleteOutlined,
  EllipsisOutlined, InboxOutlined, ReloadOutlined,
} from '@ant-design/icons';
import type { UploadProps } from 'antd';
import { resolveMediaUrl } from '../../utils/media';
import { mediaApi, mediaFolderApi, type MediaItem, type FolderItem } from '../../api/health/media';
import { AuthButton } from '../../components/AuthButton';
import { formatDateTime } from '../../utils/format';

// --- 工具函数 ---

const CT_OPTIONS = [
  { value: '', label: '全部类型' },
  { value: 'image/', label: '图片' },
  { value: 'video/', label: '视频' },
  { value: 'application/', label: '文档' },
];

const formatSize = (b: number) => b > 1048576 ? (b / 1048576).toFixed(1) + 'MB' : b > 1024 ? (b / 1024).toFixed(1) + 'KB' : b + 'B';
const isImage = (ct: string) => ct.startsWith('image/');

interface TreeNode { id: string; name: string; children: TreeNode[] }

function buildTree(folders: FolderItem[]): TreeNode[] {
  return folders.map((f) => ({ id: f.id, name: `${f.name} (${f.item_count})`, children: buildTree(f.children) }));
}

interface EditFormValues { filename: string; alt_text?: string; is_public: boolean }
interface FolderFormValues { name: string }

// ===========================================================================

export default function MediaLibrary() {
  const [items, setItems] = useState<MediaItem[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const pageSize = 24;
  const [loading, setLoading] = useState(false);
  const [keyword, setKeyword] = useState('');
  const [contentType, setContentType] = useState('');
  const [folderId, setFolderId] = useState<string | undefined>();
  const [folders, setFolders] = useState<FolderItem[]>([]);
  const [foldersLoading, setFoldersLoading] = useState(false);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [uploadOpen, setUploadOpen] = useState(false);
  const [editOpen, setEditOpen] = useState(false);
  const [moveOpen, setMoveOpen] = useState(false);
  const [folderOpen, setFolderOpen] = useState(false);
  const [editingItem, setEditingItem] = useState<MediaItem | null>(null);
  const [movingItem, setMovingItem] = useState<MediaItem | null>(null);
  const [editingFolder, setEditingFolder] = useState<FolderItem | null>(null);
  const [uploadForm] = Form.useForm();
  const [editForm] = Form.useForm<EditFormValues>();
  const [folderForm] = Form.useForm<FolderFormValues>();
  const [submitting, setSubmitting] = useState(false);

  const fetchMedia = useCallback(async () => {
    setLoading(true);
    try {
      const r = await mediaApi.list({ page, page_size: pageSize, folder_id: folderId, content_type: contentType || undefined, keyword: keyword || undefined });
      setItems(r.data);
      setTotal(r.total);
    } catch { message.error('加载媒体列表失败'); } finally { setLoading(false); }
  }, [page, pageSize, folderId, contentType, keyword]);

  const fetchFolders = useCallback(async () => {
    setFoldersLoading(true);
    try { setFolders(await mediaFolderApi.tree()); }
    catch { message.error('加载文件夹失败'); } finally { setFoldersLoading(false); }
  }, []);

  useEffect(() => { fetchMedia(); }, [fetchMedia]);
  useEffect(() => { fetchFolders(); }, [fetchFolders]);

  const resetPage = () => { setPage(1); setSelectedIds(new Set()); };
  const handleFolderSelect = (keys: React.Key[]) => { setFolderId(keys.length ? (keys[0] as string) : undefined); resetPage(); };

  const handleUpload: UploadProps['customRequest'] = async (opts) => {
    const { file, onSuccess, onError } = opts;
    try {
      const fid = uploadForm.getFieldValue('folder_id') as string | undefined;
      const pub = uploadForm.getFieldValue('is_public') as boolean;
      const fd = new FormData();
      fd.append('file', file as File);
      if (fid) fd.append('folder_id', fid);
      fd.append('is_public', String(pub ?? false));
      await mediaApi.upload(fd);
      onSuccess?.(null);
      message.success('上传成功');
      fetchMedia(); fetchFolders();
    } catch (e) { onError?.(e as Error); message.error('上传失败'); }
  };

  const openEdit = (item: MediaItem) => {
    setEditingItem(item);
    editForm.setFieldsValue({ filename: item.filename, alt_text: item.alt_text, is_public: item.is_public });
    setEditOpen(true);
  };

  const handleEditSubmit = async (v: EditFormValues) => {
    if (!editingItem) return;
    setSubmitting(true);
    try { await mediaApi.update(editingItem.id, { ...v, version: editingItem.version }); message.success('更新成功'); setEditOpen(false); fetchMedia(); }
    catch { message.error('更新失败'); } finally { setSubmitting(false); }
  };

  const handleMove = async (targetId: string | undefined) => {
    if (!movingItem) return;
    try { await mediaApi.move(movingItem.id, { folder_id: targetId, version: movingItem.version }); message.success('移动成功'); setMoveOpen(false); fetchMedia(); fetchFolders(); }
    catch { message.error('移动失败'); }
  };

  const handleDelete = async (item: MediaItem) => {
    try { await mediaApi.delete(item.id, item.version); message.success('删除成功'); fetchMedia(); fetchFolders(); }
    catch { message.error('删除失败'); }
  };

  const handleBatchDelete = async () => {
    if (!selectedIds.size) return;
    try { await mediaApi.batchDelete([...selectedIds]); message.success(`已删除 ${selectedIds.size} 个文件`); setSelectedIds(new Set()); fetchMedia(); fetchFolders(); }
    catch { message.error('批量删除失败'); }
  };

  const openCreateFolder = () => { setEditingFolder(null); folderForm.resetFields(); setFolderOpen(true); };
  const openRenameFolder = (f: FolderItem) => { setEditingFolder(f); folderForm.setFieldsValue({ name: f.name }); setFolderOpen(true); };

  const handleFolderSubmit = async (v: FolderFormValues) => {
    setSubmitting(true);
    try {
      if (editingFolder) { await mediaFolderApi.update(editingFolder.id, { name: v.name, version: editingFolder.version }); message.success('文件夹已重命名'); }
      else { await mediaFolderApi.create({ name: v.name, parent_id: folderId }); message.success('文件夹已创建'); }
      setFolderOpen(false); fetchFolders();
    } catch { message.error(editingFolder ? '重命名失败' : '创建失败'); } finally { setSubmitting(false); }
  };

  const handleDeleteFolder = async (f: FolderItem) => {
    try { await mediaFolderApi.delete(f.id, f.version); message.success('文件夹已删除'); if (folderId === f.id) setFolderId(undefined); fetchFolders(); fetchMedia(); }
    catch { message.error('删除文件夹失败（可能不为空）'); }
  };

  const toggleSelect = (id: string) => setSelectedIds((prev) => { const n = new Set(prev); if (n.has(id)) { n.delete(id); } else { n.add(id); } return n; });

  const renderCard = (item: MediaItem) => {
    const sel = selectedIds.has(item.id);
    const actions = [
      { key: 'edit', label: '编辑信息', onClick: () => openEdit(item) },
      { key: 'move', label: '移动到...', onClick: () => { setMovingItem(item); setMoveOpen(true); } },
      { key: 'delete', label: '删除', danger: true as const, onClick: () => handleDelete(item) },
    ];
    return (
      <Card key={item.id} hoverable size="small" style={{ borderColor: sel ? 'var(--ant-color-primary)' : undefined }}
        styles={{ body: { padding: 0 } }}
        cover={
          <div onClick={() => toggleSelect(item.id)} style={{ height: 140, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--ant-color-fill-quaternary, #f5f5f5)', overflow: 'hidden', position: 'relative', cursor: 'pointer' }}>
            {isImage(item.content_type) ? (
              <img src={resolveMediaUrl(item.thumbnail_path || item.storage_path)} alt={item.alt_text || item.filename} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
            ) : (
              <InboxOutlined style={{ fontSize: 36, color: 'var(--ant-color-text-quaternary)' }} />
            )}
            {sel && <div style={{ position: 'absolute', top: 4, left: 4 }}><Checkbox checked /></div>}
            <div style={{ position: 'absolute', top: 4, right: 4, opacity: 0, transition: 'opacity 0.2s' }}>
              <Dropdown menu={{ items: actions }} trigger={['click']}>
                <Button type="text" size="small" icon={<EllipsisOutlined />} />
              </Dropdown>
            </div>
          </div>
        }>
        <div style={{ padding: '6px 8px' }}>
          <Typography.Text ellipsis style={{ fontSize: 12, display: 'block' }} title={item.filename}>{item.filename}</Typography.Text>
          <Typography.Text type="secondary" style={{ fontSize: 11 }}>{formatSize(item.file_size)} · {formatDateTime(item.created_at)}</Typography.Text>
        </div>
      </Card>
    );
  };

  const treeData = [{ id: '__all__', name: '全部文件', children: buildTree(folders) }];
  const pageCount = Math.ceil(total / pageSize);

  return (
    <div style={{ display: 'flex', height: 'calc(100vh - 64px)', overflow: 'hidden' }}>
      {/* 左侧 — 文件夹树 */}
      <div style={{ width: 260, borderRight: '1px solid var(--ant-color-border-secondary, #f0f0f0)', display: 'flex', flexDirection: 'column', background: 'var(--ant-color-bg-container, #fff)', flexShrink: 0 }}>
        <div style={{ padding: '12px 12px 8px', borderBottom: '1px solid var(--ant-color-border-secondary, #f0f0f0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
          <Typography.Text strong style={{ fontSize: 13 }}>文件夹</Typography.Text>
          <AuthButton code="health.media.manage">
            <Button type="text" size="small" icon={<FolderAddOutlined />} onClick={openCreateFolder} title="新建文件夹" />
          </AuthButton>
        </div>
        <div style={{ flex: 1, overflow: 'auto', padding: '8px 4px' }}>
          {foldersLoading ? <div style={{ textAlign: 'center', padding: 20 }}><Spin size="small" /></div> : (
            <Tree defaultExpandAll selectedKeys={folderId ? [folderId] : ['__all__']} treeData={treeData}
              fieldNames={{ title: 'name', key: 'id', children: 'children' }} onSelect={handleFolderSelect}
              titleRender={(node: TreeNode) => {
                if (node.id === '__all__') return <span>{node.name}</span>;
                const matched = folders.find((f) => f.id === node.id);
                return (
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%' }}>
                    <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' }}>{node.name}</span>
                    {matched && <span style={{ marginLeft: 4 }}>
                      <AuthButton code="health.media.manage">
                        <Space size={4}>
                          <Button type="text" size="small" icon={<EditOutlined />} onClick={(e) => { e.stopPropagation(); openRenameFolder(matched); }} />
                          <Popconfirm title="确定删除此文件夹？" description="仅空文件夹可删除" onConfirm={() => handleDeleteFolder(matched)}>
                            <Button type="text" size="small" icon={<DeleteOutlined />} danger onClick={(e) => e.stopPropagation()} />
                          </Popconfirm>
                        </Space>
                      </AuthButton>
                    </span>}
                  </div>
                );
              }}
            />
          )}
        </div>
      </div>

      {/* 右侧 — 媒体列表 */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        {/* 工具栏 */}
        <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--ant-color-border-secondary, #f0f0f0)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 12, flexWrap: 'wrap', background: 'var(--ant-color-bg-container, #fff)' }}>
          <Space>
            <AuthButton code="health.media.manage">
              <Button type="primary" icon={<UploadOutlined />} onClick={() => { uploadForm.resetFields(); uploadForm.setFieldsValue({ is_public: false }); setUploadOpen(true); }}>上传文件</Button>
            </AuthButton>
            {selectedIds.size > 0 && <>
              <AuthButton code="health.media.manage">
                <Popconfirm title={`确定删除选中的 ${selectedIds.size} 个文件？`} onConfirm={handleBatchDelete}>
                  <Button danger icon={<DeleteOutlined />}>批量删除 ({selectedIds.size})</Button>
                </Popconfirm>
              </AuthButton>
              <Button size="small" onClick={() => setSelectedIds(new Set())}>取消选择</Button>
            </>}
          </Space>
          <Space>
            <Input.Search placeholder="搜索文件名" allowClear style={{ width: 200 }} onSearch={(v) => { setKeyword(v); resetPage(); }} />
            <Select value={contentType} onChange={(v) => { setContentType(v); resetPage(); }} style={{ width: 120 }} options={CT_OPTIONS} />
            <Button icon={<ReloadOutlined />} onClick={() => { fetchMedia(); fetchFolders(); }} />
          </Space>
        </div>

        {/* 媒体网格 */}
        <div style={{ flex: 1, overflow: 'auto', padding: 16 }}>
          {loading ? <div style={{ textAlign: 'center', padding: 60 }}><Spin size="large" /></div>
            : items.length === 0 ? <Empty description="暂无文件" />
            : <>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(160px, 1fr))', gap: 12 }}>
                {items.map(renderCard)}
              </div>
              {pageCount > 1 && (
                <div style={{ textAlign: 'center', padding: '16px 0', display: 'flex', justifyContent: 'center', gap: 8, alignItems: 'center' }}>
                  <Button size="small" disabled={page <= 1} onClick={() => setPage((p) => p - 1)}>上一页</Button>
                  <Typography.Text>{page} / {pageCount} (共 {total} 个)</Typography.Text>
                  <Button size="small" disabled={page >= pageCount} onClick={() => setPage((p) => p + 1)}>下一页</Button>
                </div>
              )}
            </>}
        </div>
      </div>

      {/* 上传弹窗 */}
      <Modal title="上传文件" open={uploadOpen} onCancel={() => setUploadOpen(false)} footer={null} destroyOnHidden>
        <Form form={uploadForm} layout="vertical" style={{ marginTop: 16 }}>
          <Form.Item name="folder_id" label="目标文件夹">
            <TreeSelect allowClear placeholder="根目录" treeDefaultExpandAll fieldNames={{ label: 'name', value: 'id', children: 'children' }} treeData={buildTree(folders)} style={{ width: '100%' }} />
          </Form.Item>
          <Form.Item name="is_public" label="公开访问" valuePropName="checked"><Switch /></Form.Item>
          <Upload.Dragger multiple customRequest={handleUpload} showUploadList={false} accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx">
            <p className="ant-upload-drag-icon"><InboxOutlined /></p>
            <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
            <p className="ant-upload-hint">支持图片、视频、文档等常见格式</p>
          </Upload.Dragger>
        </Form>
      </Modal>

      {/* 编辑弹窗 */}
      <Modal title="编辑文件信息" open={editOpen} onCancel={() => setEditOpen(false)} onOk={() => editForm.submit()} confirmLoading={submitting} destroyOnHidden>
        <Form form={editForm} onFinish={handleEditSubmit} layout="vertical" style={{ marginTop: 16 }}>
          <Form.Item name="filename" label="文件名" rules={[{ required: true, message: '请输入文件名' }]}><Input placeholder="文件名" /></Form.Item>
          <Form.Item name="alt_text" label="替代文本"><Input.TextArea rows={2} placeholder="描述图片内容（用于无障碍访问）" /></Form.Item>
          <Form.Item name="is_public" label="公开访问" valuePropName="checked"><Switch /></Form.Item>
        </Form>
      </Modal>

      {/* 移动弹窗 */}
      <Modal title="移动到文件夹" open={moveOpen} onCancel={() => setMoveOpen(false)} footer={null} destroyOnHidden>
        <div style={{ marginTop: 16 }}>
          <Typography.Paragraph type="secondary">选择目标文件夹：</Typography.Paragraph>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            <Button onClick={() => handleMove(undefined)} block type={movingItem?.folder_id ? 'default' : 'primary'}>根目录</Button>
            {folders.map((f) => <Button key={f.id} onClick={() => handleMove(f.id)} block type={movingItem?.folder_id === f.id ? 'primary' : 'default'}>{f.name}</Button>)}
          </div>
        </div>
      </Modal>

      {/* 文件夹创建/重命名弹窗 */}
      <Modal title={editingFolder ? '重命名文件夹' : '新建文件夹'} open={folderOpen} onCancel={() => setFolderOpen(false)} onOk={() => folderForm.submit()} confirmLoading={submitting} destroyOnHidden>
        <Form form={folderForm} onFinish={handleFolderSubmit} layout="vertical" style={{ marginTop: 16 }}>
          <Form.Item name="name" label="文件夹名称" rules={[{ required: true, message: '请输入文件夹名称' }]}><Input placeholder="输入名称" maxLength={50} /></Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
