/**
 * 调度管理 Tab 组件。
 *
 * 功能：
 * - 调度任务列表（名称、调度类型、启用 Switch、下次执行、执行次数、最近状态、操作）
 * - 创建/编辑调度任务 Modal（名称 + 调度配置）
 * - 删除确认
 */

import React, { useEffect, useState, useCallback } from 'react';
import {
  Table, Tag, Button, Switch, Popconfirm, Space, Modal, Form,
  Input, Select, InputNumber, TimePicker, Checkbox, message, Typography,
} from 'antd';
import { ReloadOutlined, EditOutlined, DeleteOutlined, HistoryOutlined, PlayCircleOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/zh-cn';
import type { ScheduledTask, ScheduleConfig } from '../types';
import {
  fetchSchedules,
  updateSchedule,
  deleteSchedule,
  toggleSchedule,
  runScheduleNow,
} from '../api/schedules';
import ScheduleHistoryDrawer from './ScheduleHistoryDrawer';

dayjs.extend(relativeTime);
dayjs.locale('zh-cn');

const { Text } = Typography;

/* ------------------------------------------------------------------ */
/*  常量 & 工具                                                        */
/* ------------------------------------------------------------------ */

const STATUS_COLOR: Record<string, string> = {
  success: 'success',
  failed: 'error',
  running: 'processing',
  cancelled: 'warning',
};

const SCHEDULE_TYPE_LABEL: Record<string, string> = {
  once: '一次性',
  interval: '固定间隔',
  daily: '每日',
  weekly: '每周',
  cron: 'Cron',
};

const INTERVAL_UNIT_LABEL: Record<string, string> = {
  minutes: '分钟',
  hours: '小时',
  days: '天',
};

const WEEKDAY_OPTIONS = [
  { label: '周一', value: 1 },
  { label: '周二', value: 2 },
  { label: '周三', value: 3 },
  { label: '周四', value: 4 },
  { label: '周五', value: 5 },
  { label: '周六', value: 6 },
  { label: '周日', value: 0 },
];

/** 格式化时间 */
function fmtTime(iso: string | null | undefined): string {
  if (!iso) return '—';
  return new Date(iso).toLocaleString('zh-CN');
}

/** 根据调度配置生成可读描述 */
function describeSchedule(cfg: ScheduleConfig): string {
  switch (cfg.schedule_type) {
    case 'once':
      return '一次性';
    case 'interval':
      return `每 ${cfg.interval_value} ${INTERVAL_UNIT_LABEL[cfg.interval_unit] ?? cfg.interval_unit}`;
    case 'daily':
      return `每日 ${cfg.daily_time}`;
    case 'weekly': {
      const days = (cfg.weekly_days ?? [])
        .map((d) => WEEKDAY_OPTIONS.find((o) => o.value === d)?.label ?? `${d}`)
        .join('、');
      return `每周 ${days} ${cfg.weekly_time}`;
    }
    case 'cron':
      return `Cron: ${cfg.cron_expression}`;
    default:
      return cfg.schedule_type;
  }
}

/* ------------------------------------------------------------------ */
/*  调度配置表单子组件                                                  */
/* ------------------------------------------------------------------ */

/** 根据调度类型动态渲染配置项 */
const ScheduleConfigFields: React.FC<{ scheduleType: string }> = ({ scheduleType }) => {
  switch (scheduleType) {
    case 'interval':
      return (
        <Space>
          <Form.Item name={['schedule_config', 'interval_value']} noStyle rules={[{ required: true }]}>
            <InputNumber min={1} placeholder="间隔值" />
          </Form.Item>
          <Form.Item name={['schedule_config', 'interval_unit']} noStyle rules={[{ required: true }]}>
            <Select style={{ width: 100 }} options={[
              { label: '分钟', value: 'minutes' },
              { label: '小时', value: 'hours' },
              { label: '天', value: 'days' },
            ]} />
          </Form.Item>
        </Space>
      );
    case 'daily':
      return (
        <Form.Item name={['schedule_config', 'daily_time']} label="执行时间" rules={[{ required: true }]}>
          <TimePicker format="HH:mm" />
        </Form.Item>
      );
    case 'weekly':
      return (
        <>
          <Form.Item name={['schedule_config', 'weekly_days']} label="星期" rules={[{ required: true }]}>
            <Checkbox.Group options={WEEKDAY_OPTIONS} />
          </Form.Item>
          <Form.Item name={['schedule_config', 'weekly_time']} label="执行时间" rules={[{ required: true }]}>
            <TimePicker format="HH:mm" />
          </Form.Item>
        </>
      );
    case 'cron':
      return (
        <Form.Item name={['schedule_config', 'cron_expression']} label="Cron 表达式" rules={[{ required: true }]}>
          <Input placeholder="0 4 * * *" />
        </Form.Item>
      );
    default:
      return null;
  }
};

/* ------------------------------------------------------------------ */
/*  主组件                                                             */
/* ------------------------------------------------------------------ */

const ScheduleTab: React.FC = () => {
  const [data, setData] = useState<ScheduledTask[]>([]);
  const [loading, setLoading] = useState(false);
  const [modalOpen, setModalOpen] = useState(false);
  const [editing, setEditing] = useState<ScheduledTask | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [scheduleType, setScheduleType] = useState<string>('daily');
  const [form] = Form.useForm();

  /* 执行历史抽屉状态 */
  const [historyOpen, setHistoryOpen] = useState(false);
  const [historyScheduleId, setHistoryScheduleId] = useState<string | null>(null);
  const [historyScheduleName, setHistoryScheduleName] = useState('');

  /* 加载列表 */
  const load = useCallback(async () => {
    setLoading(true);
    try {
      setData(await fetchSchedules());
    } catch {
      message.error('加载调度任务失败');
    } finally {
      setLoading(false);
    }
  }, []);

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

  /* 打开编辑 Modal */
  const openEdit = (record: ScheduledTask) => {
    setEditing(record);
    const cfg = record.schedule_config;
    form.setFieldsValue({
      name: record.name,
      min_run_interval_value: record.min_run_interval_value ?? 0,
      min_run_interval_unit: record.min_run_interval_unit ?? 'minutes',
      schedule_config: {
        ...cfg,
        daily_time: cfg.daily_time ? dayjs(cfg.daily_time, 'HH:mm') : undefined,
        weekly_time: cfg.weekly_time ? dayjs(cfg.weekly_time, 'HH:mm') : undefined,
      },
    });
    setScheduleType(cfg.schedule_type);
    setModalOpen(true);
  };

  /* 打开执行历史 */
  const openHistory = (record: ScheduledTask) => {
    setHistoryScheduleId(record.id);
    setHistoryScheduleName(record.name);
    setHistoryOpen(true);
  };

  /* 提交编辑 */
  const handleSubmit = async () => {
    if (!editing) return;
    try {
      const values = await form.validateFields();
      setSubmitting(true);

      const cfg = { ...values.schedule_config };
      if (cfg.daily_time && typeof cfg.daily_time !== 'string') {
        cfg.daily_time = cfg.daily_time.format('HH:mm');
      }
      if (cfg.weekly_time && typeof cfg.weekly_time !== 'string') {
        cfg.weekly_time = cfg.weekly_time.format('HH:mm');
      }

      const scheduleConfig: ScheduleConfig = {
        schedule_type: cfg.schedule_type ?? 'daily',
        interval_value: cfg.interval_value ?? 1,
        interval_unit: cfg.interval_unit ?? 'hours',
        daily_time: cfg.daily_time ?? '04:00',
        weekly_days: cfg.weekly_days ?? [1],
        weekly_time: cfg.weekly_time ?? '04:00',
        cron_expression: cfg.cron_expression ?? '0 4 * * *',
        enabled: true,
        start_date: null,
        end_date: null,
      };

      await updateSchedule(editing.id, {
        name: values.name,
        schedule_config: scheduleConfig,
        min_run_interval_value: values.min_run_interval_value ?? 0,
        min_run_interval_unit: values.min_run_interval_unit ?? 'minutes',
      });
      message.success('调度任务已更新');

      setModalOpen(false);
      load();
    } catch {
      // 表单验证失败
    } finally {
      setSubmitting(false);
    }
  };

  /* 删除 */
  const handleDelete = async (id: string) => {
    try {
      await deleteSchedule(id);
      message.success('已删除');
      load();
    } catch {
      message.error('删除失败');
    }
  };

  /* 启用/禁用 */
  const handleToggle = async (id: string) => {
    try {
      await toggleSchedule(id);
      load();
    } catch {
      message.error('切换状态失败');
    }
  };

  /* 手动执行 — 状态 */
  const [runConfirmOpen, setRunConfirmOpen] = useState(false);
  const [runForceCheck, setRunForceCheck] = useState(false);
  const [runTargetId, setRunTargetId] = useState<string | null>(null);

  /* 打开手动执行确认 Modal */
  const openRunConfirm = (id: string) => {
    setRunTargetId(id);
    setRunForceCheck(false);
    setRunConfirmOpen(true);
  };

  /* 确认手动执行 */
  const handleRunNow = async () => {
    if (!runTargetId) return;
    try {
      await runScheduleNow(runTargetId, runForceCheck);
      message.success('已提交到执行队列');
      setRunConfirmOpen(false);
    } catch (err: unknown) {
      const axiosErr = err as { response?: { status?: number; data?: { detail?: string } } };
      if (axiosErr?.response?.status === 409) {
        message.warning(axiosErr.response.data?.detail ?? '任务正在运行或未达到最小间隔');
      } else {
        message.error('执行失败');
      }
    }
  };

  /* 表格列定义 */
  const columns: ColumnsType<ScheduledTask> = [
    {
      title: '调度 ID',
      dataIndex: 'id',
      key: 'id',
      width: 120,
      render: (id: string) => (
        <Text copyable={{ text: id }} style={{ fontSize: 11 }}>
          {id.slice(0, 8)}…
        </Text>
      ),
    },
    {
      title: '名称',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '调度类型',
      key: 'schedule_type',
      render: (_: unknown, record: ScheduledTask) => describeSchedule(record.schedule_config),
    },
    {
      title: '启用',
      dataIndex: 'enabled',
      key: 'enabled',
      width: 80,
      render: (enabled: boolean, record: ScheduledTask) => (
        <Switch checked={enabled} onChange={() => handleToggle(record.id)} size="small" />
      ),
    },
    {
      title: '下次执行',
      dataIndex: 'next_run_at',
      key: 'next_run_at',
      render: fmtTime,
    },
    {
      title: '执行次数',
      dataIndex: 'run_count',
      key: 'run_count',
      width: 90,
    },
    {
      title: '最近状态',
      dataIndex: 'last_status',
      key: 'last_status',
      width: 100,
      render: (s: string | null) =>
        s ? <Tag color={STATUS_COLOR[s] ?? 'default'}>{s}</Tag> : '—',
    },
    {
      title: '最小间隔',
      dataIndex: 'min_run_interval_value',
      key: 'min_run_interval',
      width: 120,
      render: (value: number, record: ScheduledTask) => {
        if (!value) return '无限制';
        const unit = INTERVAL_UNIT_LABEL[record.min_run_interval_unit] ?? record.min_run_interval_unit;
        return `${value} ${unit}`;
      },
    },
    {
      title: '上次成功',
      dataIndex: 'last_success_at',
      key: 'last_success_at',
      width: 120,
      render: (value: string | null) => (value ? dayjs(value).fromNow() : '—'),
    },
    {
      title: '操作',
      key: 'action',
      width: 300,
      render: (_: unknown, record: ScheduledTask) => (
        <Space size="small">
          <Button type="link" icon={<PlayCircleOutlined />} size="small" onClick={() => openRunConfirm(record.id)}>
            立即执行
          </Button>
          <Button type="link" icon={<HistoryOutlined />} size="small" onClick={() => openHistory(record)}>
            执行历史
          </Button>
          <Button type="link" icon={<EditOutlined />} size="small" onClick={() => openEdit(record)}>
            编辑
          </Button>
          <Popconfirm title="确认删除该调度任务？" onConfirm={() => handleDelete(record.id)}>
            <Button type="link" danger icon={<DeleteOutlined />} size="small">
              删除
            </Button>
          </Popconfirm>
        </Space>
      ),
    },
  ];

  return (
    <>
      <div style={{ marginBottom: 12, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <Text type="secondary">共 {data.length} 个调度任务</Text>
        <Button icon={<ReloadOutlined />} onClick={load} loading={loading}>
          刷新
        </Button>
      </div>

      <Table<ScheduledTask>
        rowKey="id"
        columns={columns}
        dataSource={data}
        loading={loading}
        pagination={false}
        size="middle"
      />

      {/* 编辑 Modal */}
      <Modal
        title="编辑调度任务"
        open={modalOpen}
        onOk={handleSubmit}
        onCancel={() => setModalOpen(false)}
        confirmLoading={submitting}
        destroyOnClose
      >
        <Form form={form} layout="vertical" preserve={false}>
          <Form.Item name="name" label="名称" rules={[{ required: true, message: '请输入调度任务名称' }]}>
            <Input placeholder="例如：每日全量同步" />
          </Form.Item>

          <Form.Item name={['schedule_config', 'schedule_type']} label="调度类型" rules={[{ required: true }]}>
            <Select
              options={Object.entries(SCHEDULE_TYPE_LABEL).map(([value, label]) => ({ value, label }))}
              onChange={(v: string) => setScheduleType(v)}
            />
          </Form.Item>

          <ScheduleConfigFields scheduleType={scheduleType} />

          <Form.Item label="最小运行间隔">
            <Space>
              <Form.Item name="min_run_interval_value" noStyle initialValue={0}>
                <InputNumber min={0} placeholder="0 = 无限制" style={{ width: 140 }} />
              </Form.Item>
              <Form.Item name="min_run_interval_unit" noStyle initialValue="minutes">
                <Select style={{ width: 100 }} options={[
                  { label: '分钟', value: 'minutes' },
                  { label: '小时', value: 'hours' },
                  { label: '天', value: 'days' },
                ]} />
              </Form.Item>
            </Space>
          </Form.Item>
        </Form>
      </Modal>

      {/* 执行历史抽屉 */}
      <ScheduleHistoryDrawer
        open={historyOpen}
        scheduleId={historyScheduleId}
        scheduleName={historyScheduleName}
        onClose={() => setHistoryOpen(false)}
      />

      {/* 手动执行确认 Modal */}
      <Modal
        title="确认立即执行"
        open={runConfirmOpen}
        onOk={handleRunNow}
        onCancel={() => setRunConfirmOpen(false)}
        okText="执行"
        cancelText="取消"
      >
        <p>确认立即执行一次？（不影响调度间隔）</p>
        <Checkbox checked={runForceCheck} onChange={(e) => setRunForceCheck(e.target.checked)}>
          强制执行（忽略最小间隔）
        </Checkbox>
      </Modal>
    </>
  );
};

export default ScheduleTab;
