import React, { useCallback, useEffect, useRef, useState } from 'react';
import {
  Alert,
  Badge,
  Button,
  Card,
  Col,
  Input,
  Modal,
  Popconfirm,
  Row,
  Select,
  Space,
  Switch,
  Table,
  Tag,
  Tooltip,
  Typography,
  message,
} from 'antd';
import {
  DatabaseOutlined,
  DeleteOutlined,
  PlayCircleOutlined,
  PlusOutlined,
  ReloadOutlined,
  SendOutlined,
} from '@ant-design/icons';
import { useSearchParams, useNavigate } from 'react-router-dom';
import { customRequest } from 'helpers/http';

const { Title, Text } = Typography;

// ─── Types ────────────────────────────────────────────────────────────────────

interface JobItem {
  id: string;
  name: string;
  module: string | null;
  state: string;
  runs: { queued: number; success: number; running: number; failed: number };
  nextRunAt: string | null;
  lastRunAt: string | null;
  lastFinishedAt: string | null;
  failReason: string | null;
  failedAt: string | null;
  repeatInterval: string | null;
  data: Record<string, any> | null;
  lockedAt: string | null;
  disabled: boolean;
}

interface Overview {
  running: number;
  scheduled: number;
  queued: number;
  completed: number;
  failed: number;
  repeating: number;
  paused: number;
  active: number;
}

interface MetricsOverview {
  totalRuns: { last24h: number; total: number };
  successRate: { last24h: number; total: number };
  failed: { last24h: number; total: number };
  duration: {
    last24h: { avg: number; p95: number };
    total: { avg: number; p95: number };
  };
  running: number;
  queued: number;
}

interface JobsResponse {
  overview: Overview;
  modules: string[];
  jobs: JobItem[];
  total: number;
  totalPages: number;
}

// ─── State badge helpers ───────────────────────────────────────────────────────

const STATE_COLOR: Record<string, string> = {
  running: 'processing',
  scheduled: 'default',
  queued: 'warning',
  completed: 'success',
  failed: 'error',
  repeating: 'purple',
  paused: 'default',
};

function StateTag({ state }: { state: string }) {
  return <Badge status={STATE_COLOR[state] as any} text={state} />;
}

/** 圆圈指示器：有数量时显示彩色圆圈+内嵌数字，无数量时显示灰色空心圆 */
function RunDot({
  count,
  color,
  label,
  onClick,
}: {
  count: number;
  color: string;
  label: string;
  onClick?: () => void;
}) {
  const size = 28;
  const hasCount = count > 0;
  const clickable = hasCount && !!onClick;
  return (
    <Tooltip title={`${label}: ${count}`}>
      <span
        onClick={clickable ? onClick : undefined}
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          justifyContent: 'center',
          verticalAlign: 'middle',
          width: size,
          height: size,
          borderRadius: '50%',
          border: `2.5px solid ${hasCount ? color : '#d9d9d9'}`,
          fontSize: 11,
          fontWeight: 600,
          color: hasCount ? color : '#d9d9d9',
          cursor: clickable ? 'pointer' : 'default',
          lineHeight: 1,
        }}
      >
        {hasCount ? count : ''}
      </span>
    </Tooltip>
  );
}

// ─── Duration formatter ───────────────────────────────────────────────────────

function formatDuration(ms: number): string {
  if (ms <= 0) return '—';
  if (ms < 1000) return `${Math.round(ms)}ms`;
  const sec = ms / 1000;
  if (sec < 60) return `${sec.toFixed(1)}s`;
  const m = Math.floor(sec / 60);
  const s = Math.round(sec % 60);
  return `${m}m ${s}s`;
}

// ─── AgendaJobsPage ───────────────────────────────────────────────────────────

export default function AgendaJobsPage() {
  const navigate = useNavigate();
  const [jobs, setJobs] = useState<JobItem[]>([]);
  const [overview, setOverview] = useState<Overview | null>(null);
  const [metricsOverview, setMetricsOverview] =
    useState<MetricsOverview | null>(null);
  const [modules, setModules] = useState<string[]>([]);
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(false);

  // AI Create modal
  const [aiModalOpen, setAiModalOpen] = useState(false);
  const [aiPrompt, setAiPrompt] = useState('');
  const [aiSent, setAiSent] = useState(false);

  // Filters — synced with URL search params
  const [searchParams, setSearchParams] = useSearchParams();
  const filterState = searchParams.get('state') || undefined;
  const filterToggle = searchParams.get('toggle') || undefined;
  const filterName = searchParams.get('name') || undefined;
  const filterModule = searchParams.get('module') || undefined;
  const page = Number(searchParams.get('page')) || 1;
  const PAGE_SIZE = 20;

  const updateParams = useCallback(
    (updates: Record<string, string | undefined>) => {
      setSearchParams(
        (prev) => {
          const next = new URLSearchParams(prev);
          for (const [k, v] of Object.entries(updates)) {
            if (v) next.set(k, v);
            else next.delete(k);
          }
          return next;
        },
        { replace: true },
      );
    },
    [setSearchParams],
  );

  const setFilterState = useCallback(
    (v: string | undefined) => updateParams({ state: v, page: undefined }),
    [updateParams],
  );
  const setFilterToggle = useCallback(
    (v: string | undefined) => updateParams({ toggle: v, page: undefined }),
    [updateParams],
  );
  const setFilterName = useCallback(
    (v: string | undefined) => updateParams({ name: v, page: undefined }),
    [updateParams],
  );
  const setFilterModule = useCallback(
    (v: string | undefined) => updateParams({ module: v, page: undefined }),
    [updateParams],
  );
  const setPage = useCallback(
    (p: number) => updateParams({ page: p > 1 ? String(p) : undefined }),
    [updateParams],
  );

  // Auto-refresh
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const fetchJobs = useCallback(async () => {
    setLoading(true);
    try {
      const params: Record<string, any> = {
        skip: (page - 1) * PAGE_SIZE,
        limit: PAGE_SIZE,
      };
      if (filterState) params.state = filterState;
      if (filterToggle) params.toggle = filterToggle;
      if (filterName) params.q = filterName;
      if (filterModule) params.module = filterModule;

      const [res, metrics] = await Promise.all([
        customRequest<JobsResponse>('agenda/jobs', 'GET', params),
        customRequest<MetricsOverview>('agenda/overview', 'GET'),
      ]);
      setJobs(res.jobs);
      setOverview(res.overview);
      setModules(res.modules);
      setTotal(res.total);
      setMetricsOverview(metrics);
    } catch (e: any) {
      message.error(e?.message ?? 'Failed to fetch jobs');
    } finally {
      setLoading(false);
    }
  }, [page, filterState, filterToggle, filterName, filterModule]);

  // Initial fetch + auto-refresh every 5s
  useEffect(() => {
    fetchJobs();
    timerRef.current = setInterval(fetchJobs, 5000);
    return () => {
      if (timerRef.current) clearInterval(timerRef.current);
    };
  }, [fetchJobs]);

  // ─── Row actions ───────────────────────────────────────────────────────────

  async function handleAction(
    action: 'requeue' | 'delete' | 'disable' | 'enable',
    ids: string[],
  ) {
    try {
      const res = await customRequest<{ affected: number }>(
        `agenda/${action}`,
        'POST',
        { jobIds: ids },
      );
      message.success(`操作成功，影响 ${res.affected} 条任务`);
      fetchJobs();
    } catch (e: any) {
      message.error(e?.message ?? '操作失败');
    }
  }

  // ─── Metrics cards helpers ───────────────────────────────────────────────

  const metricsCardStyle = (key?: string): React.CSSProperties => ({
    cursor: key ? 'pointer' : 'default',
    borderColor: key && filterState === key ? '#1677ff' : undefined,
    height: '100%',
  });

  const handleMetricClick = (state: string) => {
    setFilterState(filterState === state ? undefined : state);
  };

  // ─── Table columns ─────────────────────────────────────────────────────────

  const columns = [
    {
      title: '',
      key: 'toggle',
      width: 50,
      render: (_: any, record: JobItem) => (
        <Popconfirm
          title={record.disabled ? '确定恢复此任务？' : '确定暂停此任务？'}
          okText="确认"
          cancelText="取消"
          onConfirm={() =>
            handleAction(record.disabled ? 'enable' : 'disable', [record.id])
          }
        >
          <Switch size="small" checked={!record.disabled} />
        </Popconfirm>
      ),
    },
    {
      title: 'Name',
      dataIndex: 'name',
      key: 'name',
      render: (_: string, record: JobItem) => (
        <div>
          <a
            onClick={() => navigate(`show/${encodeURIComponent(record.name)}`)}
            style={{
              display: 'block',
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
            }}
            title={record.name}
          >
            {record.name}
          </a>
          {record.module && (
            <Tag color="cyan" style={{ marginTop: 4 }}>
              {record.module}
            </Tag>
          )}
        </div>
      ),
    },
    {
      title: 'State',
      dataIndex: 'state',
      key: 'state',
      width: 100,
      render: (state: string) => <StateTag state={state} />,
    },
    {
      title: 'Runs',
      key: 'runs',
      width: 170,
      render: (_: any, record: JobItem) => {
        const go = (status: string) =>
          navigate(`show/${encodeURIComponent(record.name)}?status=${status}`);
        return (
          <Space size={6}>
            <RunDot
              count={record.runs.queued}
              color="#faad14"
              label="Queued"
              onClick={() => go('queued')}
            />
            <RunDot
              count={record.runs.success}
              color="#006d32"
              label="Success"
              onClick={() => go('success')}
            />
            <RunDot
              count={record.runs.running}
              color="#52c41a"
              label="Running"
              onClick={() => go('running')}
            />
            <RunDot
              count={record.runs.failed}
              color="#ff4d4f"
              label="Failed"
              onClick={() => go('failed')}
            />
          </Space>
        );
      },
    },
    {
      title: 'Schedule',
      dataIndex: 'repeatInterval',
      key: 'repeatInterval',
      width: 110,
      render: (v: string | null) => (v ? <Tag color="purple">{v}</Tag> : '—'),
    },
    {
      title: 'Last Run',
      dataIndex: 'lastRunAt',
      key: 'lastRunAt',
      width: 120,
      render: (v: string | null) =>
        v ? (
          <Tooltip title={new Date(v).toLocaleString()}>
            <span>
              {new Date(v).toLocaleString(undefined, {
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
              })}
            </span>
          </Tooltip>
        ) : (
          '—'
        ),
    },
    {
      title: 'Next Run',
      dataIndex: 'nextRunAt',
      key: 'nextRunAt',
      width: 120,
      render: (v: string | null) =>
        v ? (
          <Tooltip title={new Date(v).toLocaleString()}>
            <span>
              {new Date(v).toLocaleString(undefined, {
                month: '2-digit',
                day: '2-digit',
                hour: '2-digit',
                minute: '2-digit',
              })}
            </span>
          </Tooltip>
        ) : (
          '—'
        ),
    },
    {
      title: 'Actions',
      key: 'actions',
      render: (_: any, record: JobItem) => (
        <Space>
          <Popconfirm
            title="确定立即执行此任务？"
            okText="确认"
            cancelText="取消"
            onConfirm={() => handleAction('requeue', [record.id])}
          >
            <Tooltip title="Trigger: 立即执行一次">
              <Button size="small" icon={<PlayCircleOutlined />} />
            </Tooltip>
          </Popconfirm>
          <Popconfirm
            title="确定删除此任务？"
            description="删除后无法恢复，请谨慎操作。"
            okText="确认删除"
            cancelText="取消"
            okButtonProps={{ danger: true }}
            onConfirm={() => handleAction('delete', [record.id])}
          >
            <Tooltip title="Delete">
              <Button size="small" danger icon={<DeleteOutlined />} />
            </Tooltip>
          </Popconfirm>
        </Space>
      ),
    },
  ];

  // ─── Render ────────────────────────────────────────────────────────────────

  return (
    <div style={{ background: '#f0f2f5', minHeight: 'calc(100vh - 64px)' }}>
      {/* Header */}
      <Card style={{ marginBottom: 16 }}>
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <Title level={4} style={{ margin: 0 }}>
            Cron Jobs
          </Title>
          <Space>
            <Tooltip title="查看 AgendaJob 表原始数据">
              <Button
                icon={<DatabaseOutlined />}
                onClick={() => navigate('/admin/data-mngt/agenda-job')}
              >
                任务原始表
              </Button>
            </Tooltip>
            <Button
              type="primary"
              icon={<PlusOutlined />}
              onClick={() => {
                setAiModalOpen(true);
                setAiSent(false);
                setAiPrompt('');
              }}
            >
              AI创建任务
            </Button>
            <Button icon={<ReloadOutlined />} onClick={fetchJobs}></Button>
          </Space>
        </div>
      </Card>

      {/* Metrics cards */}
      {metricsOverview && (
        <Row gutter={12} style={{ marginBottom: 16 }}>
          {/* Total Runs */}
          <Col flex="1">
            <Card size="small" style={metricsCardStyle()}>
              <Text type="secondary" style={{ fontSize: 14 }}>
                Total Runs
              </Text>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span
                  style={{ fontSize: 24, fontWeight: 600, lineHeight: 1.3 }}
                >
                  {metricsOverview.totalRuns.last24h}
                </span>
                <Text type="secondary" style={{ fontSize: 12 }}>
                  24H
                </Text>
              </div>
              <Text type="secondary" style={{ fontSize: 12 }}>
                Total: {metricsOverview.totalRuns.total}
              </Text>
            </Card>
          </Col>

          {/* Success Rate */}
          <Col flex="1">
            <Card size="small" style={metricsCardStyle()}>
              <Text type="secondary" style={{ fontSize: 14 }}>
                Success Rate
              </Text>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span
                  style={{
                    fontSize: 24,
                    fontWeight: 600,
                    lineHeight: 1.3,
                    color: '#52c41a',
                  }}
                >
                  {metricsOverview.successRate.last24h}%
                </span>
                <Text type="secondary" style={{ fontSize: 12 }}>
                  24H
                </Text>
              </div>
              <Text type="secondary" style={{ fontSize: 12 }}>
                Total: {metricsOverview.successRate.total}%
              </Text>
            </Card>
          </Col>

          {/* Failed — clickable */}
          <Col flex="1">
            <Card
              size="small"
              hoverable
              onClick={() => handleMetricClick('failed')}
              style={metricsCardStyle('failed')}
            >
              <Text type="secondary" style={{ fontSize: 14 }}>
                Failed
              </Text>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span
                  style={{
                    fontSize: 24,
                    fontWeight: 600,
                    lineHeight: 1.3,
                    color: '#ff4d4f',
                  }}
                >
                  {metricsOverview.failed.last24h}
                </span>
                <Text type="secondary" style={{ fontSize: 12 }}>
                  24H
                </Text>
              </div>
              <Text type="secondary" style={{ fontSize: 12 }}>
                Total: {metricsOverview.failed.total}
              </Text>
            </Card>
          </Col>

          {/* Duration P95 */}
          <Col flex="1">
            <Tooltip
              title={
                <>
                  <div>
                    Avg (24H):{' '}
                    {formatDuration(metricsOverview.duration.last24h.avg)}
                  </div>
                  <div>
                    Avg (Total):{' '}
                    {formatDuration(metricsOverview.duration.total.avg)}
                  </div>
                </>
              }
            >
              <Card size="small" style={metricsCardStyle()}>
                <Text type="secondary" style={{ fontSize: 14 }}>
                  Duration (P95)
                </Text>
                <div
                  style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}
                >
                  <span
                    style={{ fontSize: 24, fontWeight: 600, lineHeight: 1.3 }}
                  >
                    {formatDuration(metricsOverview.duration.last24h.p95)}
                  </span>
                  <Text type="secondary" style={{ fontSize: 12 }}>
                    24H
                  </Text>
                </div>
                <Text type="secondary" style={{ fontSize: 12 }}>
                  Total: {formatDuration(metricsOverview.duration.total.p95)}
                </Text>
              </Card>
            </Tooltip>
          </Col>

          {/* Running — clickable */}
          <Col flex="1">
            <Card
              size="small"
              hoverable
              onClick={() => handleMetricClick('running')}
              style={metricsCardStyle('running')}
            >
              <Text type="secondary" style={{ fontSize: 14 }}>
                Running
              </Text>
              <div
                style={{
                  fontSize: 24,
                  fontWeight: 600,
                  lineHeight: 1.3,
                  color: '#1677ff',
                }}
              >
                {metricsOverview.running}
              </div>
            </Card>
          </Col>

          {/* Queued — clickable */}
          <Col flex="1">
            <Card
              size="small"
              hoverable
              onClick={() => handleMetricClick('queued')}
              style={metricsCardStyle('queued')}
            >
              <Text type="secondary" style={{ fontSize: 14 }}>
                Queued
              </Text>
              <div
                style={{
                  fontSize: 24,
                  fontWeight: 600,
                  lineHeight: 1.3,
                  color: '#faad14',
                }}
              >
                {metricsOverview.queued}
              </div>
            </Card>
          </Col>
        </Row>
      )}

      {/* Filters */}
      <Card style={{ marginBottom: 16 }}>
        <Space wrap>
          <Space size={0}>
            {[
              {
                key: undefined,
                label: 'All',
                count: overview ? overview.active + overview.paused : 0,
              },
              { key: 'active', label: 'Active', count: overview?.active ?? 0 },
              { key: 'paused', label: 'Paused', count: overview?.paused ?? 0 },
            ].map(({ key, label, count }) => {
              const selected = filterToggle === key;
              return (
                <Button
                  key={label}
                  type={selected ? 'primary' : 'default'}
                  onClick={() => setFilterToggle(key)}
                  style={{
                    borderRadius: 0,
                    ...(label === 'All'
                      ? { borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }
                      : {}),
                    ...(label === 'Paused'
                      ? { borderTopRightRadius: 6, borderBottomRightRadius: 6 }
                      : {}),
                  }}
                >
                  {label}{' '}
                  <Badge
                    count={count}
                    showZero
                    style={{
                      marginLeft: 6,
                      backgroundColor: selected
                        ? 'rgba(255,255,255,0.3)'
                        : '#8c8c8c',
                    }}
                  />
                </Button>
              );
            })}
          </Space>
          <Select
            placeholder="模块筛选"
            allowClear
            value={filterModule}
            onChange={(v) => setFilterModule(v)}
            style={{ width: 160 }}
            options={modules.map((m) => ({ value: m, label: m }))}
          />
          <Input
            placeholder="按名称过滤"
            allowClear
            defaultValue={filterName}
            onChange={(e) => {
              const v = e.target.value;
              if (debounceRef.current) clearTimeout(debounceRef.current);
              debounceRef.current = setTimeout(
                () => setFilterName(v || undefined),
                300,
              );
            }}
            style={{ width: 220 }}
          />
        </Space>
      </Card>

      {/* Jobs table */}
      <Card>
        <Table
          rowKey="id"
          loading={loading}
          columns={columns}
          dataSource={jobs}
          scroll={{ x: 1200 }}
          pagination={{
            current: page,
            pageSize: PAGE_SIZE,
            total,
            onChange: (p) => setPage(p),
            showTotal: (t) => `共 ${t} 条`,
          }}
          size="small"
        />
      </Card>

      {/* AI Create Cron Job Modal */}
      <Modal
        title="AI 创建定时任务"
        open={aiModalOpen}
        onCancel={() => setAiModalOpen(false)}
        footer={null}
        width={520}
      >
        <Text type="secondary" style={{ display: 'block', marginBottom: 12 }}>
          描述你的业务模块和定时任务需求，AI 将自动为你创建
        </Text>
        <Input.TextArea
          value={aiPrompt}
          onChange={(e) => setAiPrompt(e.target.value)}
          placeholder={
            '例：为 order 模块创建一个定时任务，每天凌晨2点自动清理超过30天的已取消订单，执行前先记录日志，失败时发送通知'
          }
          autoSize={{ minRows: 6, maxRows: 12 }}
          onPressEnter={(e) => {
            if (e.ctrlKey && aiPrompt.trim()) {
              window.parent.postMessage(
                {
                  type: 'SEND_PROMPT',
                  payload: `使用 cron-job-management skill来创建一个定时任务，任务描述：\n${aiPrompt.trim()}`,
                },
                '*',
              );
              setAiSent(true);
            }
          }}
        />
        <Button
          type="primary"
          icon={<SendOutlined />}
          onClick={() => {
            if (aiPrompt.trim()) {
              window.parent.postMessage(
                {
                  type: 'SEND_PROMPT',
                  payload: `使用 cron-job-management skill来创建一个定时任务，任务描述：\n${aiPrompt.trim()}`,
                },
                '*',
              );
              setAiSent(true);
            }
          }}
          disabled={!aiPrompt.trim()}
          style={{ marginTop: 12 }}
          block
        >
          发送
        </Button>
        {aiSent && (
          <Alert
            type="success"
            showIcon
            style={{ marginTop: 12 }}
            message="已发送给 AI Agent"
            description="请查看右下角 Agent 的工作情况，如果成功了，请点右侧刷新按钮查看。"
          />
        )}
      </Modal>
    </div>
  );
}
