import { useState, useEffect, useCallback, useMemo } from 'react';
import { Row, Col, Card, Statistic, Table, Tag, Select, Button, Space, Spin, Typography, theme } from 'antd';
import {
  FileTextOutlined,
  TagOutlined,
  WarningOutlined,
  ClockCircleOutlined,
  LockOutlined,
  ReloadOutlined,
} from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import { useOutletContext, useNavigate } from 'react-router-dom';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import { api } from '@/lib/api';
import type { AppOutletContext } from '@/types/api';

dayjs.extend(relativeTime);

interface PageMeta {
  path: string;
  title: string;
  tags: string[];
  description: string;
  status: string;
  lastModified: string | null;
  wordCount: number;
  hasAccessPolicy: boolean;
}

interface Warning {
  type: string;
  paths: string[];
}

interface MetadataResponse {
  totalPages: number;
  pages: PageMeta[];
  warnings: Warning[];
}

type FilterMode = 'all' | 'no-tags' | 'no-description' | 'stale';

const TAG_COLORS = [
  'blue', 'green', 'purple', 'cyan', 'magenta', 'orange', 'gold', 'lime', 'geekblue', 'volcano',
];

function tagColor(tag: string): string {
  let hash = 0;
  for (let i = 0; i < tag.length; i++) {
    hash = ((hash << 5) - hash + tag.charCodeAt(i)) | 0;
  }
  return TAG_COLORS[Math.abs(hash) % TAG_COLORS.length] ?? 'blue';
}

export default function DocsMetadataPage() {
  const { setPageHeader } = useOutletContext<AppOutletContext>();
  const navigate = useNavigate();
  const { token } = theme.useToken();

  const [loading, setLoading] = useState(true);
  const [data, setData] = useState<MetadataResponse | null>(null);
  const [filter, setFilter] = useState<FilterMode>('all');

  const fetchMetadata = useCallback(async () => {
    setLoading(true);
    try {
      const { data: res } = await api.get<MetadataResponse>('/docs/metadata');
      setData(res);
    } catch {
      // silently fail
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    setPageHeader({ title: 'Documentation Metadata' });
    fetchMetadata();
  }, [setPageHeader, fetchMetadata]);

  const staleDays = 30;

  const stats = useMemo(() => {
    if (!data) return { total: 0, noTags: 0, noDesc: 0, stale: 0, restricted: 0 };
    const now = dayjs();
    const noTags = data.pages.filter(p => !p.tags || p.tags.length === 0).length;
    const noDesc = data.pages.filter(p => !p.description).length;
    const stale = data.pages.filter(p => {
      if (!p.lastModified) return true;
      return now.diff(dayjs(p.lastModified), 'day') > staleDays;
    }).length;
    const restricted = data.pages.filter(p => p.hasAccessPolicy).length;
    return { total: data.totalPages, noTags, noDesc, stale, restricted };
  }, [data]);

  const filteredPages = useMemo(() => {
    if (!data) return [];
    const now = dayjs();
    switch (filter) {
      case 'no-tags':
        return data.pages.filter(p => !p.tags || p.tags.length === 0);
      case 'no-description':
        return data.pages.filter(p => !p.description);
      case 'stale':
        return data.pages.filter(p => {
          if (!p.lastModified) return true;
          return now.diff(dayjs(p.lastModified), 'day') > staleDays;
        });
      default:
        return data.pages;
    }
  }, [data, filter]);

  const columns: ColumnsType<PageMeta> = [
    {
      title: 'Path',
      dataIndex: 'path',
      key: 'path',
      ellipsis: true,
      sorter: (a, b) => a.path.localeCompare(b.path),
      render: (path: string) => (
        <Typography.Link
          onClick={() => navigate('/app/docs', { state: { openFile: path } })}
          style={{ fontFamily: 'monospace', fontSize: 12 }}
        >
          {path}
        </Typography.Link>
      ),
    },
    {
      title: 'Title',
      dataIndex: 'title',
      key: 'title',
      ellipsis: true,
      sorter: (a, b) => (a.title || '').localeCompare(b.title || ''),
    },
    {
      title: 'Tags',
      dataIndex: 'tags',
      key: 'tags',
      width: 240,
      filters: (() => {
        if (!data) return [];
        const allTags = new Set<string>();
        data.pages.forEach(p => (p.tags || []).forEach(t => allTags.add(t)));
        return Array.from(allTags).sort().map(t => ({ text: t, value: t }));
      })(),
      onFilter: (value, record) => (record.tags || []).includes(value as string),
      render: (tags: string[]) =>
        tags && tags.length > 0 ? (
          <Space size={[0, 4]} wrap>
            {tags.map(t => (
              <Tag key={t} color={tagColor(t)}>
                {t}
              </Tag>
            ))}
          </Space>
        ) : (
          <Typography.Text type="secondary" style={{ fontSize: 12 }}>
            --
          </Typography.Text>
        ),
    },
    {
      title: 'Words',
      dataIndex: 'wordCount',
      key: 'wordCount',
      width: 90,
      align: 'right',
      sorter: (a, b) => a.wordCount - b.wordCount,
      render: (count: number) => count.toLocaleString(),
    },
    {
      title: 'Last Modified',
      dataIndex: 'lastModified',
      key: 'lastModified',
      width: 140,
      sorter: (a, b) => {
        const da = a.lastModified ? dayjs(a.lastModified).unix() : 0;
        const db = b.lastModified ? dayjs(b.lastModified).unix() : 0;
        return da - db;
      },
      render: (val: string | null) =>
        val ? (
          <Typography.Text title={dayjs(val).format('YYYY-MM-DD HH:mm')}>
            {dayjs(val).fromNow()}
          </Typography.Text>
        ) : (
          <Typography.Text type="secondary">--</Typography.Text>
        ),
    },
    {
      title: 'Access',
      dataIndex: 'hasAccessPolicy',
      key: 'hasAccessPolicy',
      width: 70,
      align: 'center',
      filters: [
        { text: 'Restricted', value: true },
        { text: 'Public', value: false },
      ],
      onFilter: (value, record) => record.hasAccessPolicy === value,
      render: (restricted: boolean) =>
        restricted ? (
          <LockOutlined style={{ color: token.colorWarning }} title="Access policy applied" />
        ) : null,
    },
  ];

  if (loading && !data) {
    return (
      <div style={{ textAlign: 'center', padding: 80 }}>
        <Spin size="large" />
      </div>
    );
  }

  return (
    <div>
      <Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
        <Col xs={12} sm={8} md={4}>
          <Card size="small">
            <Statistic
              title="Total Pages"
              value={stats.total}
              prefix={<FileTextOutlined />}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card size="small">
            <Statistic
              title="No Tags"
              value={stats.noTags}
              prefix={<TagOutlined />}
              valueStyle={stats.noTags > 0 ? { color: token.colorWarning } : undefined}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card size="small">
            <Statistic
              title="No Description"
              value={stats.noDesc}
              prefix={<WarningOutlined />}
              valueStyle={stats.noDesc > 0 ? { color: token.colorWarning } : undefined}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card size="small">
            <Statistic
              title={`Stale (>${staleDays}d)`}
              value={stats.stale}
              prefix={<ClockCircleOutlined />}
              valueStyle={stats.stale > 0 ? { color: token.colorError } : undefined}
            />
          </Card>
        </Col>
        <Col xs={12} sm={8} md={4}>
          <Card size="small">
            <Statistic
              title="Restricted"
              value={stats.restricted}
              prefix={<LockOutlined />}
            />
          </Card>
        </Col>
      </Row>

      <Space style={{ marginBottom: 16 }}>
        <Select<FilterMode>
          value={filter}
          onChange={setFilter}
          style={{ width: 180 }}
          options={[
            { label: 'Show All', value: 'all' },
            { label: 'Missing Tags', value: 'no-tags' },
            { label: 'Missing Description', value: 'no-description' },
            { label: `Stale (>${staleDays} days)`, value: 'stale' },
          ]}
        />
        <Button icon={<ReloadOutlined />} onClick={fetchMetadata} loading={loading}>
          Refresh
        </Button>
      </Space>

      <Table<PageMeta>
        columns={columns}
        dataSource={filteredPages}
        rowKey="path"
        loading={loading}
        size="small"
        pagination={{ pageSize: 50, showSizeChanger: true, pageSizeOptions: ['25', '50', '100'] }}
        scroll={{ x: 800 }}
      />

      {data?.warnings && data.warnings.length > 0 && (
        <Card
          size="small"
          title={<><WarningOutlined style={{ color: token.colorWarning }} /> Warnings</>}
          style={{ marginTop: 24 }}
        >
          {data.warnings.map((w, i) => (
            <div key={i} style={{ marginBottom: 8 }}>
              <Typography.Text strong>{w.type}:</Typography.Text>{' '}
              <Typography.Text type="secondary">
                {w.paths.length} page{w.paths.length !== 1 ? 's' : ''} — {w.paths.slice(0, 5).join(', ')}
                {w.paths.length > 5 ? ` (+${w.paths.length - 5} more)` : ''}
              </Typography.Text>
            </div>
          ))}
        </Card>
      )}
    </div>
  );
}
