import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Badge,
  Button,
  Card,
  Col,
  DatePicker,
  Descriptions,
  Popconfirm,
  Row,
  Select,
  Space,
  Spin,
  Switch,
  Tag,
  Tooltip,
  Typography,
  message,
} from 'antd';
import {
  ArrowLeftOutlined,
  DeleteOutlined,
  PlayCircleOutlined,
} from '@ant-design/icons';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { customRequest } from 'helpers/http';
import { useECharts } from 'hooks/useECharts';
import dayjs from 'dayjs';

const { Title } = Typography;

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

interface JobDetail {
  name: string;
  module: string | null;
  state: string;
  disabled: boolean;
  nextRunAt: string | null;
  lastRunAt: string | null;
  lastFinishedAt: string | null;
  failReason: string | null;
  repeatInterval: string | null;
  data: Record<string, any> | null;
  runs: { queued: number; running: number; success: number; failed: number };
  duration: {
    totalRuns: number;
    maxMs: number | null;
    minMs: number | null;
    avgMs: number | null;
    firstRunAt: string | null;
    lastRunAt: string | null;
  };
}

interface LogItem {
  id: string;
  jobName: string;
  status: 'success' | 'failed';
  startAt: string;
  endAt: string;
  durationMs: number;
  error: string | null;
  logs: string | null;
  data: Record<string, any> | null;
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

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

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

function formatTime(v: string | null): string {
  return v ? new Date(v).toLocaleString() : '—';
}

/** 圆圈指示器 */
function RunDot({
  count,
  color,
  label,
}: {
  count: number;
  color: string;
  label: string;
}) {
  const size = 28;
  const hasCount = count > 0;
  return (
    <Tooltip title={`${label}: ${count}`}>
      <span
        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: 'default',
          lineHeight: 1,
        }}
      >
        {hasCount ? count : ''}
      </span>
    </Tooltip>
  );
}

// ─── Duration Bar Chart ───────────────────────────────────────────────────────

function DurationChart({
  logs,
  selectedIndex,
  onSelect,
}: {
  logs: LogItem[];
  selectedIndex: number | null;
  onSelect: (index: number) => void;
}) {
  // 按时间正序（最早在左）
  const sorted = useMemo(() => [...logs].reverse(), [logs]);

  const option = useMemo(() => {
    return {
      tooltip: {
        trigger: 'axis' as const,
        formatter: (params: any) => {
          const p = params[0];
          return `${p.name}<br/>Duration: ${formatMs(p.value)}<br/>Status: ${sorted[p.dataIndex]?.status}`;
        },
      },
      grid: { left: 50, right: 16, top: 16, bottom: 40 },
      xAxis: {
        type: 'category' as const,
        data: sorted.map((l) =>
          new Date(l.startAt).toLocaleTimeString(undefined, {
            hour: '2-digit',
            minute: '2-digit',
          }),
        ),
        axisLabel: { rotate: 30, fontSize: 10 },
      },
      yAxis: {
        type: 'value' as const,
        name: 'Duration',
        axisLabel: {
          formatter: (v: number) => formatMs(v),
        },
      },
      series: [
        {
          type: 'bar',
          data: sorted.map((l, i) => {
            const isSuccess = l.status === 'success';
            const baseColor = isSuccess ? '#52c41a' : '#ff4d4f';
            const dimColor = isSuccess ? '#b7eb8f' : '#ffa39e';
            const isSelected = selectedIndex !== null && i === selectedIndex;
            const hasSel = selectedIndex !== null;
            return {
              value: l.durationMs,
              itemStyle: {
                color: hasSel ? (isSelected ? baseColor : dimColor) : baseColor,
                borderColor: isSelected ? '#000' : 'transparent',
                borderWidth: isSelected ? 2 : 0,
              },
            };
          }),
          barMaxWidth: 30,
          cursor: 'pointer',
        },
      ],
    };
  }, [sorted, selectedIndex]);

  const onEvents = useMemo(
    () => ({
      click: (params: any) => {
        if (params.componentType === 'series') {
          onSelect(params.dataIndex);
        }
      },
    }),
    [onSelect],
  );

  const { domRef } = useECharts({ option, onEvents });

  return <div ref={domRef} style={{ width: '100%', height: 280 }} />;
}

// ─── AgendaJobShow ────────────────────────────────────────────────────────────

export default function AgendaJobShow() {
  const { jobName: rawJobName } = useParams<{ jobName: string }>();
  const jobName = decodeURIComponent(rawJobName || '');
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const initialStatus = searchParams.get('status') || undefined;

  const [detail, setDetail] = useState<JobDetail | null>(null);
  const [loading, setLoading] = useState(true);

  // Logs for chart
  const [chartLogs, setChartLogs] = useState<LogItem[]>([]);
  // Selected run index (in time-ascending order, i.e. reversed chartLogs)
  const [selectedRunIndex, setSelectedRunIndex] = useState<number | null>(null);
  const sortedLogs = useMemo(() => [...chartLogs].reverse(), [chartLogs]);
  const selectedRun =
    selectedRunIndex !== null ? sortedLogs[selectedRunIndex] : null;

  // Chart filters
  const [filterBefore, setFilterBefore] = useState<dayjs.Dayjs | null>(dayjs());
  const [filterLimit, setFilterLimit] = useState(25);
  const [filterStatus, setFilterStatus] = useState<string | undefined>(
    initialStatus,
  );

  // Fetch job detail
  const fetchDetail = useCallback(async () => {
    setLoading(true);
    try {
      const res = await customRequest<JobDetail>(
        `agenda/job/${encodeURIComponent(jobName)}`,
        'GET',
      );
      setDetail(res);
    } catch (e: any) {
      message.error(e?.message ?? 'Failed to fetch job detail');
    } finally {
      setLoading(false);
    }
  }, [jobName]);

  // Fetch chart logs with filters
  const fetchChartLogs = useCallback(async () => {
    try {
      const params: Record<string, any> = {
        jobName,
        skip: 0,
        limit: filterLimit,
      };
      if (filterBefore) params.before = filterBefore.toISOString();
      if (filterStatus) params.status = filterStatus;
      const res = await customRequest<{ logs: LogItem[]; total: number }>(
        'agenda/logs',
        'GET',
        params,
      );
      setChartLogs(res.logs);
      setSelectedRunIndex(null);
    } catch {
      // ignore
    }
  }, [jobName, filterLimit, filterBefore, filterStatus]);

  useEffect(() => {
    fetchDetail();
    fetchChartLogs();
  }, [fetchDetail, fetchChartLogs]);

  // Actions
  async function handleAction(
    action: 'requeue' | 'delete' | 'disable' | 'enable',
  ) {
    if (!detail) return;
    try {
      const jobsRes = await customRequest<{ jobs: { id: string }[] }>(
        'agenda/jobs',
        'GET',
        { job: jobName, limit: 100 },
      );
      const ids = jobsRes.jobs.map((j) => j.id);
      if (!ids.length) {
        message.warning('No matching jobs found');
        return;
      }
      const res = await customRequest<{ affected: number }>(
        `agenda/${action}`,
        'POST',
        { jobIds: ids },
      );
      message.success(`操作成功，影响 ${res.affected} 条任务`);
      if (action === 'delete') {
        navigate(-1);
      } else {
        fetchDetail();
        fetchChartLogs();
      }
    } catch (e: any) {
      message.error(e?.message ?? '操作失败');
    }
  }

  if (loading) {
    return (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          minHeight: 'calc(100vh - 64px)',
        }}
      >
        <Spin size="large" />
      </div>
    );
  }

  if (!detail) {
    return (
      <div style={{ padding: 24 }}>
        <Button
          icon={<ArrowLeftOutlined />}
          onClick={() => navigate(-1)}
        ></Button>
        <div style={{ marginTop: 24, textAlign: 'center', color: '#999' }}>
          Job 不存在
        </div>
      </div>
    );
  }

  const { runs, duration } = detail;
  const totalRuns = runs.success + runs.failed;

  return (
    <div style={{ background: '#f0f2f5', minHeight: 'calc(100vh - 64px)' }}>
      {/* Header */}
      <Card style={{ marginBottom: 16 }}>
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <Space size="middle" align="center">
            <Button
              type="text"
              icon={<ArrowLeftOutlined />}
              onClick={() => navigate(-1)}
            />
            <div>
              <Title level={4} style={{ margin: 0 }}>
                {detail.name}
              </Title>
              <Space size={4} style={{ marginTop: 4 }}>
                <Popconfirm
                  title={
                    detail.disabled ? '确定恢复此任务？' : '确定暂停此任务？'
                  }
                  okText="确认"
                  cancelText="取消"
                  onConfirm={() =>
                    handleAction(detail.disabled ? 'enable' : 'disable')
                  }
                >
                  <span style={{ marginRight: 8 }}>
                    <Switch checked={!detail.disabled} />
                  </span>
                </Popconfirm>
                {detail.module && <Tag color="cyan">{detail.module}</Tag>}
                <Badge
                  status={STATE_COLOR[detail.state] as any}
                  text={detail.state}
                />
                {detail.repeatInterval && (
                  <Tag color="purple">{detail.repeatInterval}</Tag>
                )}
              </Space>
            </div>
          </Space>
          <Space>
            <Popconfirm
              title="确定立即执行此任务？"
              okText="确认"
              cancelText="取消"
              onConfirm={() => handleAction('requeue')}
            >
              <Tooltip title="Trigger: 立即执行一次">
                <Button icon={<PlayCircleOutlined />} />
              </Tooltip>
            </Popconfirm>
            <Popconfirm
              title="确定删除此任务？"
              description="删除后无法恢复，请谨慎操作。"
              okText="确认删除"
              cancelText="取消"
              okButtonProps={{ danger: true }}
              onConfirm={() => handleAction('delete')}
            >
              <Tooltip title="Delete">
                <Button danger icon={<DeleteOutlined />} />
              </Tooltip>
            </Popconfirm>
          </Space>
        </div>
      </Card>

      {/* Filter bar */}
      <Card size="small" style={{ marginBottom: 16 }}>
        <Space wrap size="middle" align="center">
          <DatePicker
            showTime
            placeholder="截止时间"
            value={filterBefore}
            onChange={(v) => setFilterBefore(v)}
            allowClear
            style={{ width: 200 }}
          />
          <Select
            value={filterLimit}
            onChange={(v) => setFilterLimit(v)}
            style={{ width: 80 }}
            options={[10, 25, 50, 100].map((n) => ({
              value: n,
              label: String(n),
            }))}
          />
          <Space size={6}>
            {(
              [
                { key: undefined, label: 'All', color: undefined },
                { key: 'queued', label: 'Queued', color: '#faad14' },
                { key: 'success', label: 'Success', color: '#006d32' },
                { key: 'running', label: 'Running', color: '#52c41a' },
                { key: 'failed', label: 'Failed', color: '#ff4d4f' },
              ] as const
            ).map((item) => (
              <Tag
                key={item.label}
                color={
                  filterStatus === item.key
                    ? (item.color ?? 'processing')
                    : undefined
                }
                style={{
                  cursor: 'pointer',
                  borderColor:
                    filterStatus === item.key
                      ? (item.color ?? '#1677ff')
                      : undefined,
                }}
                onClick={() => setFilterStatus(item.key)}
              >
                {item.label}
              </Tag>
            ))}
          </Space>
          <Button
            type="link"
            onClick={() => {
              setFilterBefore(null);
              setFilterLimit(25);
              setFilterStatus(undefined);
            }}
          >
            Clear Filters
          </Button>
        </Space>
      </Card>

      {/* Left: Chart | Right: Details */}
      <Row gutter={16} style={{ marginBottom: 16 }}>
        <Col span={10}>
          <Card title="运行历史" size="small" style={{ height: '100%' }}>
            {chartLogs.length > 0 ? (
              <DurationChart
                logs={chartLogs}
                selectedIndex={selectedRunIndex}
                onSelect={(i) =>
                  setSelectedRunIndex(selectedRunIndex === i ? null : i)
                }
              />
            ) : (
              <div
                style={{
                  height: 280,
                  display: 'flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  color: '#999',
                }}
              >
                暂无运行记录
              </div>
            )}
          </Card>
        </Col>
        <Col span={14}>
          <Card size="small" style={{ height: '100%' }}>
            {selectedRun ? (
              <>
                <div
                  style={{
                    display: 'flex',
                    justifyContent: 'space-between',
                    alignItems: 'center',
                    marginBottom: 12,
                  }}
                >
                  <Title level={5} style={{ margin: 0, color: '#595959' }}>
                    Run Detail
                  </Title>
                  <Button
                    size="small"
                    type="link"
                    onClick={() => setSelectedRunIndex(null)}
                  >
                    返回总览
                  </Button>
                </div>
                <Descriptions column={2} size="small">
                  <Descriptions.Item label="Status">
                    <Tag
                      color={
                        selectedRun.status === 'success' ? 'success' : 'error'
                      }
                    >
                      {selectedRun.status}
                    </Tag>
                  </Descriptions.Item>
                  <Descriptions.Item label="Duration">
                    {formatMs(selectedRun.durationMs)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Start">
                    {formatTime(selectedRun.startAt)}
                  </Descriptions.Item>
                  <Descriptions.Item label="End">
                    {formatTime(selectedRun.endAt)}
                  </Descriptions.Item>
                  {selectedRun.error && (
                    <Descriptions.Item label="Error" span={2}>
                      <span style={{ color: '#ff4d4f' }}>
                        {selectedRun.error}
                      </span>
                    </Descriptions.Item>
                  )}
                </Descriptions>

                <Title level={5} style={{ marginTop: 16, color: '#595959' }}>
                  Handler Logs
                </Title>
                {selectedRun.logs ? (
                  <pre
                    style={{
                      margin: 0,
                      padding: 12,
                      background: '#fafafa',
                      border: '1px solid #f0f0f0',
                      borderRadius: 4,
                      fontSize: 12,
                      lineHeight: 1.6,
                      maxHeight: 300,
                      overflow: 'auto',
                      whiteSpace: 'pre-wrap',
                      wordBreak: 'break-all',
                    }}
                  >
                    {selectedRun.logs}
                  </pre>
                ) : (
                  <div style={{ color: '#999' }}>暂无日志</div>
                )}
              </>
            ) : (
              <>
                <Title level={5} style={{ marginTop: 0, color: '#595959' }}>
                  Runs Summary
                </Title>
                <Descriptions column={2} size="small">
                  <Descriptions.Item label="Total Runs">
                    {totalRuns}
                  </Descriptions.Item>
                  <Descriptions.Item label="First Run">
                    {formatTime(duration.firstRunAt)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Success">
                    <span style={{ color: '#006d32' }}>{runs.success}</span>
                  </Descriptions.Item>
                  <Descriptions.Item label="Last Run">
                    {formatTime(duration.lastRunAt)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Failed">
                    <span style={{ color: '#ff4d4f' }}>{runs.failed}</span>
                  </Descriptions.Item>
                  <Descriptions.Item label="Max Duration">
                    {formatMs(duration.maxMs)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Avg Duration">
                    {formatMs(duration.avgMs)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Min Duration">
                    {formatMs(duration.minMs)}
                  </Descriptions.Item>
                </Descriptions>

                <Title level={5} style={{ marginTop: 16, color: '#595959' }}>
                  Job Details
                </Title>
                <Descriptions column={2} size="small">
                  <Descriptions.Item label="Name">
                    {detail.name}
                  </Descriptions.Item>
                  <Descriptions.Item label="Module">
                    {detail.module ?? '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="State">
                    <Badge
                      status={STATE_COLOR[detail.state] as any}
                      text={detail.state}
                    />
                  </Descriptions.Item>
                  <Descriptions.Item label="Schedule">
                    {detail.repeatInterval ?? '—'}
                  </Descriptions.Item>
                  <Descriptions.Item label="Next Run">
                    {formatTime(detail.nextRunAt)}
                  </Descriptions.Item>
                  <Descriptions.Item label="Last Run">
                    {formatTime(detail.lastRunAt)}
                  </Descriptions.Item>
                  {detail.failReason && (
                    <Descriptions.Item label="Fail Reason" span={2}>
                      <span style={{ color: '#ff4d4f' }}>
                        {detail.failReason}
                      </span>
                    </Descriptions.Item>
                  )}
                  {detail.data && (
                    <Descriptions.Item label="Data" span={2}>
                      <pre
                        style={{
                          margin: 0,
                          fontSize: 12,
                          maxHeight: 120,
                          overflow: 'auto',
                        }}
                      >
                        {JSON.stringify(detail.data, null, 2)}
                      </pre>
                    </Descriptions.Item>
                  )}
                </Descriptions>
              </>
            )}
          </Card>
        </Col>
      </Row>
    </div>
  );
}
