/**
 * 调度任务执行历史抽屉组件。
 *
 * - 表格展示执行记录（ID、状态、开始时间、耗时、退出码），50 条/页分页
 * - 点击行打开详情（复用 LogStream 展示日志，running 任务走 WebSocket）
 */

import React, { useEffect, useState, useCallback, useRef } from 'react';
import {
  Drawer, Table, Tag, Typography, Descriptions, Spin, Space, message,
} from 'antd';
import { FileTextOutlined } from '@ant-design/icons';
import type { ColumnsType } from 'antd/es/table';
import type { ExecutionLog } from '../types';
import { fetchScheduleHistory } from '../api/schedules';
import { apiClient } from '../api/client';
import LogStream from './LogStream';

const { Text } = Typography;

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

function fmtTime(iso: string | null | undefined): string {
  if (!iso) return '—';
  return new Date(iso).toLocaleString('zh-CN');
}

function fmtDuration(ms: number | null | undefined): 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 remainSec = Math.round(sec % 60);
  return `${min}m${remainSec}s`;
}

interface Props {
  open: boolean;
  scheduleId: string | null;
  scheduleName: string;
  onClose: () => void;
}

const ScheduleHistoryDrawer: React.FC<Props> = ({ open, scheduleId, scheduleName, onClose }) => {
  const [data, setData] = useState<ExecutionLog[]>([]);
  const [loading, setLoading] = useState(false);
  const [page, setPage] = useState(1);
  const [detail, setDetail] = useState<ExecutionLog | null>(null);
  const [logLines, setLogLines] = useState<string[]>([]);
  const [logLoading, setLogLoading] = useState(false);
  const [wsConnected, setWsConnected] = useState(false);
  const wsRef = useRef<WebSocket | null>(null);

  const closeWs = useCallback(() => {
    wsRef.current?.close();
    wsRef.current = null;
    setWsConnected(false);
  }, []);

  const load = useCallback(async (p: number) => {
    if (!scheduleId) return;
    setLoading(true);
    try {
      setData(await fetchScheduleHistory(scheduleId, p, 50));
    } catch {
      message.error('加载执行历史失败');
    } finally {
      setLoading(false);
    }
  }, [scheduleId]);

  useEffect(() => {
    if (open && scheduleId) {
      setPage(1);
      setDetail(null);
      load(1);
    }
    return () => { closeWs(); };
  }, [open, scheduleId, load, closeWs]);

  const handleRowClick = useCallback(async (record: ExecutionLog) => {
    setDetail(record);
    setLogLines([]);
    setLogLoading(true);
    closeWs();

    if (record.status === 'running') {
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const host = window.location.host;
      const ws = new WebSocket(`${protocol}//${host}/ws/logs/${record.id}`);
      wsRef.current = ws;
      ws.onopen = () => { setWsConnected(true); setLogLoading(false); };
      ws.onmessage = (event) => { setLogLines((prev) => [...prev, event.data]); };
      ws.onclose = () => { setWsConnected(false); };
      ws.onerror = () => {
        setWsConnected(false);
        apiClient.get<{ output_log: string | null; error_log: string | null }>(
          `/execution/${record.id}/logs`,
        ).then(({ data: logData }) => {
          const parts: string[] = [];
          if (logData.output_log) parts.push(logData.output_log);
          if (logData.error_log) parts.push(logData.error_log);
          setLogLines(parts.join('\n').split('\n').filter(Boolean));
        }).catch(() => {}).finally(() => setLogLoading(false));
      };
    } else {
      try {
        const { data: logData } = await apiClient.get<{
          output_log: string | null; error_log: string | null;
        }>(`/execution/${record.id}/logs`);
        const parts: string[] = [];
        if (logData.output_log) parts.push(logData.output_log);
        if (logData.error_log) parts.push(logData.error_log);
        setLogLines(parts.join('\n').split('\n').filter(Boolean));
      } catch { /* 静默 */ }
      finally { setLogLoading(false); }
    }
  }, [closeWs]);

  const columns: ColumnsType<ExecutionLog> = [
    {
      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: 'status', key: 'status', width: 90,
      render: (s: string) => <Tag color={STATUS_COLOR[s] ?? 'default'}>{s}</Tag>,
    },
    { title: '开始时间', dataIndex: 'started_at', key: 'started_at', width: 170, render: fmtTime },
    { title: '时长', dataIndex: 'duration_ms', key: 'duration_ms', width: 90, render: fmtDuration },
    {
      title: '退出码', dataIndex: 'exit_code', key: 'exit_code', width: 70, align: 'center',
      render: (v: number | null) => v != null
        ? <Tag color={v === 0 ? 'success' : 'error'}>{v}</Tag>
        : '—',
    },
  ];

  return (
    <Drawer
      title={`执行历史 — ${scheduleName}`}
      open={open}
      onClose={() => { closeWs(); setDetail(null); onClose(); }}
      width={800}
      styles={{ body: { padding: 12 } }}
    >
      <Table<ExecutionLog>
        rowKey="id"
        columns={columns}
        dataSource={data}
        loading={loading}
        size="small"
        pagination={{
          current: page,
          pageSize: 50,
          onChange: (p) => { setPage(p); load(p); },
          showTotal: (t) => `共 ${t} 条`,
        }}
        onRow={(record) => ({
          onClick: () => handleRowClick(record),
          style: { cursor: 'pointer' },
        })}
      />

      {/* 执行详情 */}
      <Drawer
        title={
          <Space>
            <span>执行详情</span>
            {detail?.status === 'running' && (
              wsConnected ? <Tag color="processing">实时连接中</Tag> : <Tag>未连接</Tag>
            )}
          </Space>
        }
        open={!!detail}
        onClose={() => { closeWs(); setDetail(null); }}
        width={700}
        styles={{ body: { padding: 12 } }}
      >
        {detail && (
          <>
            <Descriptions column={1} bordered size="small" style={{ marginBottom: 16 }}>
              <Descriptions.Item label="执行 ID">{detail.id}</Descriptions.Item>
              <Descriptions.Item label="任务">{detail.task_codes?.join(', ')}</Descriptions.Item>
              <Descriptions.Item label="状态">
                <Tag color={STATUS_COLOR[detail.status] ?? 'default'}>{detail.status}</Tag>
              </Descriptions.Item>
              <Descriptions.Item label="开始时间">{fmtTime(detail.started_at)}</Descriptions.Item>
              <Descriptions.Item label="结束时间">{fmtTime(detail.finished_at)}</Descriptions.Item>
              <Descriptions.Item label="时长">{fmtDuration(detail.duration_ms)}</Descriptions.Item>
              <Descriptions.Item label="退出码">
                {detail.exit_code != null
                  ? <Tag color={detail.exit_code === 0 ? 'success' : 'error'}>{detail.exit_code}</Tag>
                  : '—'}
              </Descriptions.Item>
              <Descriptions.Item label="命令">
                <code style={{ wordBreak: 'break-all', fontSize: 12 }}>{detail.command || '—'}</code>
              </Descriptions.Item>
            </Descriptions>
            <div style={{ marginBottom: 8, display: 'flex', alignItems: 'center', gap: 8 }}>
              <FileTextOutlined />
              <Text strong>执行日志</Text>
              {logLoading && <Spin size="small" />}
            </div>
            <div style={{ height: 400 }}>
              <LogStream executionId={detail.id} lines={logLines} />
            </div>
          </>
        )}
      </Drawer>
    </Drawer>
  );
};

export default ScheduleHistoryDrawer;
