/**
 * 触发器统一管理页面 — 聚合 biz / ai / etl 三类触发器为 Tab 视图。
 *
 * - 4 个 Tab：all（全部，只读统一视图）、biz（业务）、ai（AI）、etl（ETL）
 * - Tab 切换通过 useSearchParams 同步 URL 查询参数 ?tab=all|biz|ai|etl
 * - destroyInactiveTabPane={false} 保持 Tab 状态不丢失
 * - "全部"Tab 调用 fetchUnifiedTriggers()，展示统一字段表格
 * - "业务"Tab 复用 TriggerJobs 组件 + 编辑 Modal
 * - "AI"Tab 复用 AITriggers（触发器设置）+ AIOperations + AITriggerJobs 组件
 * - "ETL"Tab 展示 scheduled_tasks 数据
 *
 * CHANGE 2026-07-15 | Task 10.1：创建 TriggerManager 页面
 */

import React, { useMemo, useState, useEffect, useCallback } from 'react';
import {
  Tabs, Typography, Table, Tag, message, Modal, Form, Input, InputNumber, Space,
  Button, Card,
} from 'antd';
import {
  AppstoreOutlined,
  SettingOutlined,
  RobotOutlined,
  CloudServerOutlined,
  EditOutlined,
  ReloadOutlined,
} from '@ant-design/icons';
import { useSearchParams } from 'react-router-dom';
import type { ColumnsType } from 'antd/es/table';

import { fetchUnifiedTriggers, type UnifiedTriggerItem } from '../api/triggers';
import {
  fetchTriggerJobs, updateTriggerConfig,
  type TriggerJob, type UpdateTriggerConfigReq,
} from '../api/triggerJobs';
import { fetchSchedules } from '../api/schedules';
import type { ScheduledTask } from '../types';
import AIOperations from './AIOperations';
import AITriggerJobs from './AITriggerJobs';
import AITriggers from './AITriggers';

const { Title } = Typography;

/* ───────── Tab 常量 ───────── */

const VALID_TABS = ['all', 'biz', 'ai', 'etl'] as const;
type TabKey = (typeof VALID_TABS)[number];
const DEFAULT_TAB: TabKey = 'all';

function isValidTab(value: string | null): value is TabKey {
  return value != null && (VALID_TABS as readonly string[]).includes(value);
}

/* ───────── 工具函数 ───────── */

const SOURCE_COLOR: Record<string, string> = {
  biz: 'blue', ai: 'purple', etl: 'green',
};
const SOURCE_LABEL: Record<string, string> = {
  biz: '业务', ai: 'AI', etl: 'ETL',
};

function formatTime(raw: string | null): string {
  if (!raw) return '—';
  const d = new Date(raw);
  return Number.isNaN(d.getTime()) ? raw : d.toLocaleString('zh-CN');
}

/* ───────── "全部"Tab：统一视图（只读） ───────── */

const AllTriggersTab: React.FC = () => {
  const [data, setData] = useState<UnifiedTriggerItem[]>([]);
  const [loading, setLoading] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      setData(await fetchUnifiedTriggers());
    } catch {
      message.error('加载统一触发器数据失败');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const columns: ColumnsType<UnifiedTriggerItem> = [
    { title: '名称', dataIndex: 'name', key: 'name', width: 200 },
    {
      title: '类型', dataIndex: 'source', key: 'source', width: 80,
      render: (v: string) => (
        <Tag color={SOURCE_COLOR[v] ?? 'default'}>{SOURCE_LABEL[v] ?? v}</Tag>
      ),
    },
    { title: '触发条件', dataIndex: 'trigger_condition', key: 'trigger_condition', width: 120 },
    {
      title: '状态', dataIndex: 'status', key: 'status', width: 100,
      render: (v: string) => {
        const color = v === 'running' ? 'processing' : v === 'error' ? 'error'
          : v === 'disabled' ? 'default' : 'success';
        return <Tag color={color}>{v}</Tag>;
      },
    },
    { title: '上次执行', dataIndex: 'last_run_at', key: 'last_run_at', width: 170, render: formatTime },
    { title: '下次执行', dataIndex: 'next_run_at', key: 'next_run_at', width: 170, render: formatTime },
    {
      title: '最近错误', dataIndex: 'last_error', key: 'last_error', ellipsis: true,
      render: (v: string | null) => v
        ? <Typography.Text type="danger" ellipsis style={{ maxWidth: 200 }}>{v}</Typography.Text>
        : '—',
    },
  ];

  return (
    <Card
      size="small"
      extra={<Button icon={<ReloadOutlined />} size="small" onClick={load} loading={loading}>刷新</Button>}
    >
      <Table<UnifiedTriggerItem>
        rowKey={(r) => `${r.source}-${r.id}`}
        columns={columns}
        dataSource={data}
        loading={loading}
        pagination={{ pageSize: 20, showTotal: (t) => `共 ${t} 条` }}
        size="small"
        scroll={{ x: 1000 }}
      />
    </Card>
  );
};

/* ───────── "业务"Tab：TriggerJobs + 编辑 Modal ───────── */

const BizTriggersTab: React.FC = () => {
  const [jobs, setJobs] = useState<TriggerJob[]>([]);
  const [loading, setLoading] = useState(false);
  const [editingJob, setEditingJob] = useState<TriggerJob | null>(null);
  const [editModalOpen, setEditModalOpen] = useState(false);
  const [saving, setSaving] = useState(false);
  const [form] = Form.useForm<UpdateTriggerConfigReq>();

  const load = useCallback(async () => {
    setLoading(true);
    try {
      setJobs(await fetchTriggerJobs());
    } catch {
      message.error('加载业务触发器失败');
    } finally {
      setLoading(false);
    }
  }, []);

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

  const openEdit = (job: TriggerJob) => {
    setEditingJob(job);
    const cfg = job.trigger_config ?? {};
    form.setFieldsValue({
      cron_expression: (cfg.cron_expression as string) ?? undefined,
      interval_seconds: (cfg.interval_seconds as number) ?? undefined,
    });
    setEditModalOpen(true);
  };

  const handleSave = async () => {
    if (!editingJob) return;
    try {
      const values = await form.validateFields();
      // 只发送有值的字段
      const body: UpdateTriggerConfigReq = {};
      if (values.cron_expression != null && values.cron_expression !== '') {
        body.cron_expression = values.cron_expression;
      }
      if (values.interval_seconds != null) {
        body.interval_seconds = values.interval_seconds;
      }
      if (!body.cron_expression && body.interval_seconds == null) {
        message.warning('请至少填写 cron 表达式或间隔秒数');
        return;
      }
      setSaving(true);
      await updateTriggerConfig(editingJob.id, body);
      message.success('触发器配置已更新');
      setEditModalOpen(false);
      setEditingJob(null);
      form.resetFields();
      await load();
    } catch (err: unknown) {
      // 422 错误展示具体信息
      if (err && typeof err === 'object' && 'response' in err) {
        const resp = (err as { response?: { status?: number; data?: { detail?: string } } }).response;
        if (resp?.status === 422 && resp.data?.detail) {
          message.error(resp.data.detail);
          return;
        }
      }
      message.error('保存失败');
    } finally {
      setSaving(false);
    }
  };

  const TRIGGER_LABEL: Record<string, string> = {
    cron: '定时（Cron）', interval: '间隔', event: '事件触发',
  };

  const formatTriggerConfig = (job: TriggerJob): string => {
    const cfg = job.trigger_config;
    if (!cfg) return '—';
    if (job.trigger_condition === 'cron') return (cfg.cron_expression as string) || '—';
    if (job.trigger_condition === 'interval') {
      const sec = cfg.interval_seconds as number;
      if (sec >= 3600) return `每 ${sec / 3600} 小时`;
      if (sec >= 60) return `每 ${sec / 60} 分钟`;
      return `每 ${sec} 秒`;
    }
    if (job.trigger_condition === 'event') return `事件: ${cfg.event_name || '—'}`;
    return JSON.stringify(cfg);
  };

  const columns: ColumnsType<TriggerJob> = [
    {
      title: '任务名称', dataIndex: 'job_name', key: 'job_name', width: 180,
      render: (name: string, record) => (
        <>
          <Typography.Text strong>{record.description || name}</Typography.Text>
          <br />
          <Typography.Text type="secondary" style={{ fontSize: 12 }}>{name}</Typography.Text>
        </>
      ),
    },
    {
      title: '触发方式', dataIndex: 'trigger_condition', key: 'trigger_condition', width: 120,
      render: (v: string) => <Tag>{TRIGGER_LABEL[v] || v}</Tag>,
    },
    {
      title: '触发配置', key: 'trigger_config', width: 150,
      render: (_: unknown, record) => <code style={{ fontSize: 12 }}>{formatTriggerConfig(record)}</code>,
    },
    {
      title: '状态', dataIndex: 'status', key: 'status', width: 80,
      render: (v: string) => (
        <Tag color={v === 'enabled' ? 'green' : 'default'}>{v === 'enabled' ? '启用' : '禁用'}</Tag>
      ),
    },
    { title: '上次执行', dataIndex: 'last_run_at', key: 'last_run_at', width: 170, render: formatTime },
    { title: '下次执行', dataIndex: 'next_run_at', key: 'next_run_at', width: 170, render: formatTime },
    {
      title: '最近错误', dataIndex: 'last_error', key: 'last_error', width: 200,
      render: (v: string | null) => v
        ? <Typography.Text type="danger" ellipsis style={{ maxWidth: 180 }}>{v}</Typography.Text>
        : <Typography.Text type="success">正常</Typography.Text>,
    },
    {
      title: '操作', key: 'action', width: 80, fixed: 'right',
      render: (_: unknown, record) => (
        <Button
          size="small"
          icon={<EditOutlined />}
          onClick={() => openEdit(record)}
          disabled={record.status !== 'enabled'}
        >
          编辑
        </Button>
      ),
    },
  ];

  return (
    <>
      <Card
        size="small"
        extra={<Button icon={<ReloadOutlined />} size="small" onClick={load} loading={loading}>刷新</Button>}
      >
        <Table<TriggerJob>
          rowKey="id"
          columns={columns}
          dataSource={jobs}
          loading={loading}
          pagination={false}
          size="small"
          scroll={{ x: 1200 }}
        />
      </Card>

      <Modal
        title={`编辑触发器配置 — ${editingJob?.description || editingJob?.job_name || ''}`}
        open={editModalOpen}
        onCancel={() => { setEditModalOpen(false); setEditingJob(null); form.resetFields(); }}
        onOk={handleSave}
        confirmLoading={saving}
        okText="保存"
        cancelText="取消"
        destroyOnClose
      >
        <Form form={form} layout="vertical">
          <Form.Item
            name="cron_expression"
            label="Cron 表达式（5 字段格式）"
            help="例如：0 */2 * * *（每 2 小时执行）"
          >
            <Input placeholder="分 时 日 月 周" />
          </Form.Item>
          <Form.Item
            name="interval_seconds"
            label="间隔秒数"
            help="最小值为 1"
            rules={[{ type: 'number', min: 1, message: 'interval_seconds 必须 >= 1' }]}
          >
            <InputNumber style={{ width: '100%' }} min={1} placeholder="秒" />
          </Form.Item>
        </Form>
      </Modal>
    </>
  );
};

/* ───────── "AI"Tab：AIOperations + AITriggerJobs ───────── */

const AITriggersTab: React.FC = () => (
  <Space direction="vertical" style={{ width: '100%' }} size="large">
    <AITriggers />
    <AIOperations />
    <AITriggerJobs />
  </Space>
);

/* ───────── "ETL"Tab：scheduled_tasks 数据 ───────── */

const ETLTriggersTab: React.FC = () => {
  const [data, setData] = useState<ScheduledTask[]>([]);
  const [loading, setLoading] = useState(false);

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

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

  const columns: ColumnsType<ScheduledTask> = [
    { title: '名称', dataIndex: 'name', key: 'name', width: 200 },
    {
      title: '任务代码', dataIndex: 'task_codes', key: 'task_codes', width: 200,
      render: (v: string[]) => v?.join(', ') ?? '—',
    },
    {
      title: '状态', dataIndex: 'enabled', key: 'enabled', width: 80,
      render: (v: boolean) => <Tag color={v ? 'green' : 'default'}>{v ? '启用' : '禁用'}</Tag>,
    },
    {
      title: '上次状态', dataIndex: 'last_status', key: 'last_status', width: 100,
      render: (v: string | null) => v
        ? <Tag color={v === 'success' ? 'success' : v === 'failed' ? 'error' : 'default'}>{v}</Tag>
        : '—',
    },
    { title: '上次执行', dataIndex: 'last_run_at', key: 'last_run_at', width: 170, render: formatTime },
    { title: '下次执行', dataIndex: 'next_run_at', key: 'next_run_at', width: 170, render: formatTime },
    { title: '执行次数', dataIndex: 'run_count', key: 'run_count', width: 90 },
    { title: '创建时间', dataIndex: 'created_at', key: 'created_at', width: 170, render: formatTime },
  ];

  return (
    <Card
      size="small"
      extra={<Button icon={<ReloadOutlined />} size="small" onClick={load} loading={loading}>刷新</Button>}
    >
      <Table<ScheduledTask>
        rowKey="id"
        columns={columns}
        dataSource={data}
        loading={loading}
        pagination={{ pageSize: 20, showTotal: (t) => `共 ${t} 条` }}
        size="small"
        scroll={{ x: 1000 }}
      />
    </Card>
  );
};

/* ───────── 主组件 ───────── */

const TriggerManager: React.FC = () => {
  const [searchParams, setSearchParams] = useSearchParams();

  const activeTab: TabKey = useMemo(() => {
    const raw = searchParams.get('tab');
    return isValidTab(raw) ? raw : DEFAULT_TAB;
  }, [searchParams]);

  const handleTabChange = (key: string) => {
    setSearchParams({ tab: key }, { replace: true });
  };

  const items = useMemo(
    () => [
      {
        key: 'all' as TabKey,
        label: (
          <span>
            <AppstoreOutlined style={{ marginRight: 6 }} />
            全部
          </span>
        ),
        children: <AllTriggersTab />,
      },
      {
        key: 'biz' as TabKey,
        label: (
          <span>
            <SettingOutlined style={{ marginRight: 6 }} />
            业务
          </span>
        ),
        children: <BizTriggersTab />,
      },
      {
        key: 'ai' as TabKey,
        label: (
          <span>
            <RobotOutlined style={{ marginRight: 6 }} />
            AI
          </span>
        ),
        children: <AITriggersTab />,
      },
      {
        key: 'etl' as TabKey,
        label: (
          <span>
            <CloudServerOutlined style={{ marginRight: 6 }} />
            ETL
          </span>
        ),
        children: <ETLTriggersTab />,
      },
    ],
    [],
  );

  return (
    <div>
      <Title level={4} style={{ marginBottom: 16 }}>
        <SettingOutlined style={{ marginRight: 8 }} />
        触发器管理
      </Title>
      <Tabs
        activeKey={activeTab}
        onChange={handleTabChange}
        items={items}
        destroyInactiveTabPane={false}
      />
    </div>
  );
};

export default TriggerManager;
