import { useCallback, useEffect, useState, type ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  Button,
  Card,
  Input,
  Popconfirm,
  Popover,
  Space,
  Spin,
  Table,
  Tag,
  Tooltip,
  Typography,
  message,
} from 'antd';
import {
  DeleteOutlined,
  EyeOutlined,
  FolderOpenOutlined,
  QrcodeOutlined,
  ReloadOutlined,
  ScanOutlined,
  SearchOutlined,
  UserOutlined,
} from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { inboxApi, type InboxBarcode, type InboxFile } from '../api/inbox';

const { Title } = Typography;

function formatDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function renderBarcodes(barcodes: InboxBarcode[]): ReactNode {
  if (!barcodes || barcodes.length === 0) {
    return <Typography.Text type="secondary">—</Typography.Text>;
  }
  return (
    <Space size={[4, 4]} wrap>
      {barcodes.map((b, idx) => {
        const label = b.templateName ?? b.value;
        const color = b.templateName ? 'green' : 'default';
        return (
          <Tooltip
            key={`${b.page}-${idx}`}
            title={
              <div>
                <div>Seite {b.page}</div>
                <div style={{ fontFamily: 'monospace' }}>{b.value}</div>
                {!b.templateName && <div>Keine passende Vorlage</div>}
              </div>
            }
          >
            <Tag icon={<QrcodeOutlined />} color={color}>
              S.{b.page}: {label}
            </Tag>
          </Tooltip>
        );
      })}
    </Space>
  );
}

function DocumentPreviewPopover({ record, children }: { record: InboxFile; children: ReactNode }) {
  const [blobUrl, setBlobUrl] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  const handleOpenChange = async (open: boolean) => {
    if (open && !blobUrl && !loading) {
      setLoading(true);
      try {
        const blob = await inboxApi.thumbnailBlob(record.id, 1);
        setBlobUrl(URL.createObjectURL(blob));
      } catch {
        // error handling handled implicitly
      } finally {
        setLoading(false);
      }
    }
  };

  useEffect(() => {
    return () => {
      if (blobUrl) {
        URL.revokeObjectURL(blobUrl);
      }
    };
  }, [blobUrl]);

  const content = (
    <div style={{ width: 250, minHeight: 150, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      {loading ? (
        <Spin />
      ) : blobUrl ? (
        <img src={blobUrl} alt="Vorschau" style={{ maxWidth: '100%', maxHeight: 350, objectFit: 'contain' }} />
      ) : (
        <Typography.Text type="secondary">Vorschau nicht verfügbar</Typography.Text>
      )}
    </div>
  );

  return (
    <Popover content={content} title="Vorschau (Seite 1)" onOpenChange={handleOpenChange} placement="right" mouseEnterDelay={0.5}>
      <span style={{ cursor: 'pointer', textDecoration: 'underline dashed #ccc', display: 'inline-block' }}>{children}</span>
    </Popover>
  );
}

export default function InboxPage() {
  const navigate = useNavigate();
  const [files, setFiles] = useState<InboxFile[]>([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState('');
  const [rescanning, setRescanning] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const data = await inboxApi.list();
      setFiles(data);
    } catch {
      message.error('Dateien konnten nicht geladen werden');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const handleRescan = async () => {
    setRescanning(true);
    const hide = message.loading('Rescan läuft – das kann je nach Anzahl der Dokumente dauern …', 0);
    try {
      const { scanned, failed } = await inboxApi.rescan();
      hide();
      if (failed > 0) {
        message.warning(`Rescan abgeschlossen: ${scanned} ok, ${failed} fehlgeschlagen`);
      } else {
        message.success(`Rescan abgeschlossen: ${scanned} Dokument(e) neu gescannt`);
      }
      await load();
    } catch {
      hide();
      message.error('Rescan fehlgeschlagen');
    } finally {
      setRescanning(false);
    }
  };

  const handleDelete = async (id: string) => {
    try {
      await inboxApi.remove(id);
      message.success('Dokument gelöscht');
      await load();
    } catch {
      message.error('Löschen fehlgeschlagen');
    }
  };

  const filtered = files.filter((f) =>
    search ? f.name.toLowerCase().includes(search.toLowerCase()) : true,
  );

  const columns: ColumnsType<InboxFile> = [
    {
      title: 'Dateiname',
      dataIndex: 'name',
      key: 'name',
      sorter: (a, b) => a.name.localeCompare(b.name),
      render: (name: string, record) => (
        <DocumentPreviewPopover record={record}>
          <Typography.Text>{name}</Typography.Text>
        </DocumentPreviewPopover>
      ),
    },
    {
      title: 'Quelle',
      dataIndex: 'source',
      key: 'source',
      width: 160,
      filters: [
        { text: 'Gemeinsam', value: 'all' },
        { text: 'Persönlich', value: 'user' },
      ],
      onFilter: (value, record) => record.source === value,
      render: (src: InboxFile['source']) =>
        src === 'user' ? (
          <Tag icon={<UserOutlined />} color="purple">
            Persönlich
          </Tag>
        ) : (
          <Tag icon={<FolderOpenOutlined />} color="blue">
            Gemeinsam
          </Tag>
        ),
    },
    {
      title: 'QR-Code / Vorlage',
      key: 'barcodes',
      width: 260,
      render: (_, record) => renderBarcodes(record.barcodes),
    },
    {
      title: 'Seiten',
      dataIndex: 'pageCount',
      key: 'pageCount',
      width: 100,
      sorter: (a, b) => a.pageCount - b.pageCount,
      render: (n: number) => (n > 0 ? n : <Typography.Text type="secondary">—</Typography.Text>),
    },
    {
      title: 'Empfangen',
      dataIndex: 'createdAt',
      key: 'createdAt',
      width: 180,
      defaultSortOrder: 'descend',
      sorter: (a, b) => a.createdAt.localeCompare(b.createdAt),
      render: (iso: string) => formatDate(iso),
    },
    {
      title: 'Aktionen',
      key: 'actions',
      width: 140,
      render: (_, record) => (
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
          <Tooltip title="Vorschau öffnen">
            <Button
              type="link"
              icon={<EyeOutlined />}
              onClick={() => navigate(`/inbox/${encodeURIComponent(record.id)}`)}
            >
              Vorschau
            </Button>
          </Tooltip>
          <Popconfirm
            title="Dokument löschen?"
            description="Datei und Datenbank-Eintrag werden dauerhaft entfernt."
            okText="Löschen"
            cancelText="Abbrechen"
            okButtonProps={{ danger: true }}
            onConfirm={() => handleDelete(record.id)}
          >
            <Button type="link" danger icon={<DeleteOutlined />}>
              Löschen
            </Button>
          </Popconfirm>
        </div>
      ),
    },
  ];

  return (
    <div>
      <div
        style={{
          display: 'flex',
          justifyContent: 'space-between',
          alignItems: 'center',
          marginBottom: 16,
        }}
      >
        <div>
          <Title level={3} style={{ margin: 0 }}>
            Eingangsbox
          </Title>
          <Typography.Text type="secondary">
            Dateien aus <code>/mnt/scans/all</code> und Ihrem persönlichen
            Scan-Ordner.
          </Typography.Text>
        </div>
        <Space>
          <Input
            prefix={<SearchOutlined />}
            placeholder="Suchen …"
            style={{ width: 260 }}
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            allowClear
          />
          <Button icon={<ReloadOutlined />} onClick={load}>
            Aktualisieren
          </Button>
          <Popconfirm
            title="Alle Dokumente neu scannen?"
            description="Alle PDFs in der Eingangsbox werden erneut auf QR-Codes geprüft. Das kann je nach Anzahl der Dokumente einige Zeit dauern."
            okText="Rescan starten"
            cancelText="Abbrechen"
            onConfirm={handleRescan}
          >
            <Button icon={<ScanOutlined />} loading={rescanning}>
              Rescan
            </Button>
          </Popconfirm>
        </Space>
      </div>

      <Card>
        <Table<InboxFile>
          rowKey="id"
          columns={columns}
          dataSource={filtered}
          loading={loading}
          pagination={{
            pageSize: 25,
            showSizeChanger: true,
            showTotal: (t) => `${t} Dateien`,
          }}
          locale={{ emptyText: 'Keine Dateien vorhanden' }}
        />
      </Card>
    </div>
  );
}
