import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Alert,
  Button,
  Form,
  Input,
  InputNumber,
  Modal,
  Select,
  Space,
  Switch,
  Table,
  Tag,
  Typography,
  message,
} from "antd";
import type { ColumnsType } from "antd/es/table";
import { PlusOutlined, ReloadOutlined } from "@ant-design/icons";
import EllipsisCell from "./EllipsisCell";

const API_BASE_URL =
  import.meta.env.VITE_API_BASE_URL ?? "/demand/api/v1";

const getResolvedApiBaseUrl = () => {
  if (API_BASE_URL.startsWith("http://") || API_BASE_URL.startsWith("https://")) {
    return API_BASE_URL;
  }
  return new URL(API_BASE_URL, window.location.origin).toString();
};

type StrategyConfigItem = {
  strategy_id: string;
  name: string;
  version: string;
  params: Record<string, unknown>;
  active: boolean;
  daily_write_limit: number;
  priority: number;
  registered: boolean;
  create_time: string | null;
  updated_time: string | null;
};

type StrategyConfigResponse = {
  items: StrategyConfigItem[];
};

type AvailableStrategyItem = {
  strategy_id: string;
  name: string;
  version: string;
};

type AvailableStrategyResponse = {
  items: AvailableStrategyItem[];
};

function formatParamsPreview(params: Record<string, unknown>): string {
  const text = JSON.stringify(params ?? {}, null, 0);
  if (!text || text === "{}") {
    return "-";
  }
  return text.length > 80 ? `${text.slice(0, 80)}…` : text;
}

function formatExperimentNumber(value: number | null | undefined): string {
  if (value === undefined || value === null) {
    return "-";
  }
  return String(value);
}

const PARAMS_HINT = "策略运行阈值等参数，JSON 格式";
const DAILY_LIMIT_HINT = "0 表示不限制，直到 staging 全部写入";
const PRIORITY_HINT =
  "数值越小同批次越先选取；同名需求一旦写入 Hive，其他 priority 不可再写，仅同 priority 可重复";

function parseParamsJson(raw: string): Record<string, unknown> {
  const trimmed = raw.trim();
  if (!trimmed) {
    return {};
  }
  const parsed: unknown = JSON.parse(trimmed);
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
    throw new Error("params 必须是 JSON 对象");
  }
  return parsed as Record<string, unknown>;
}

async function readErrorDetail(response: Response): Promise<string> {
  const text = await response.text();
  if (!text) {
    return `HTTP ${response.status}`;
  }
  try {
    const payload = JSON.parse(text) as { detail?: unknown };
    if (typeof payload.detail === "string") {
      return payload.detail;
    }
  } catch {
    /* 非 JSON 响应 */
  }
  return text;
}

function compareStrategyConfigs(a: StrategyConfigItem, b: StrategyConfigItem): number {
  if (a.active !== b.active) {
    return a.active ? -1 : 1;
  }
  const priorityA = a.priority ?? 0;
  const priorityB = b.priority ?? 0;
  if (priorityA !== priorityB) {
    return priorityA - priorityB;
  }
  return a.strategy_id.localeCompare(b.strategy_id);
}

export default function StrategyConfigApp() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [items, setItems] = useState<StrategyConfigItem[]>([]);
  const [availableItems, setAvailableItems] = useState<AvailableStrategyItem[]>([]);
  const [createOpen, setCreateOpen] = useState(false);
  const [editOpen, setEditOpen] = useState(false);
  const [editingItem, setEditingItem] = useState<StrategyConfigItem | null>(null);
  const [createForm] = Form.useForm();
  const [editForm] = Form.useForm();
  const [submitting, setSubmitting] = useState(false);
  const [togglingId, setTogglingId] = useState<string | null>(null);

  const fetchConfigs = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const resolvedBase = getResolvedApiBaseUrl();
      const baseWithSlash = resolvedBase.endsWith("/")
        ? resolvedBase
        : `${resolvedBase}/`;
      const url = new URL("strategy-configs", baseWithSlash);
      const response = await fetch(url.toString(), {
        method: "GET",
        headers: { Accept: "application/json" },
      });
      if (!response.ok) {
        throw new Error(await readErrorDetail(response));
      }
      const payload = (await response.json()) as StrategyConfigResponse;
      setItems(payload.items ?? []);
    } catch (queryError) {
      setError(
        queryError instanceof Error ? queryError.message : "加载策略配置失败",
      );
    } finally {
      setLoading(false);
    }
  }, []);

  const fetchAvailable = useCallback(async () => {
    try {
      const resolvedBase = getResolvedApiBaseUrl();
      const baseWithSlash = resolvedBase.endsWith("/")
        ? resolvedBase
        : `${resolvedBase}/`;
      const url = new URL("strategy-configs/available", baseWithSlash);
      const response = await fetch(url.toString(), {
        method: "GET",
        headers: { Accept: "application/json" },
      });
      if (!response.ok) {
        throw new Error(await readErrorDetail(response));
      }
      const payload = (await response.json()) as AvailableStrategyResponse;
      setAvailableItems(payload.items ?? []);
    } catch (queryError) {
      message.error(
        queryError instanceof Error ? queryError.message : "加载可添加策略失败",
      );
    }
  }, []);

  useEffect(() => {
    void fetchConfigs();
  }, [fetchConfigs]);

  const sortedItems = useMemo(
    () => [...items].sort(compareStrategyConfigs),
    [items],
  );

  const openCreateModal = () => {
    createForm.resetFields();
    createForm.setFieldsValue({
      paramsText: "{}",
      daily_write_limit: 0,
      priority: 0,
      active: false,
    });
    setCreateOpen(true);
    void fetchAvailable();
  };

  const openEditModal = (item: StrategyConfigItem) => {
    setEditingItem(item);
    editForm.setFieldsValue({
      paramsText: JSON.stringify(item.params ?? {}, null, 2),
      daily_write_limit: item.daily_write_limit ?? 0,
      priority: item.priority ?? 0,
      active: item.active,
    });
    setEditOpen(true);
  };

  const handleCreate = async () => {
    try {
      const values = await createForm.validateFields();
      setSubmitting(true);
      const params = parseParamsJson(String(values.paramsText ?? ""));
      const resolvedBase = getResolvedApiBaseUrl();
      const baseWithSlash = resolvedBase.endsWith("/")
        ? resolvedBase
        : `${resolvedBase}/`;
      const url = new URL("strategy-configs", baseWithSlash);
      const response = await fetch(url.toString(), {
        method: "POST",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          strategy_id: values.strategy_id,
          params,
          daily_write_limit: Number(values.daily_write_limit ?? 0),
          priority: Number(values.priority ?? 0),
          active: Boolean(values.active),
        }),
      });
      if (!response.ok) {
        throw new Error(await readErrorDetail(response));
      }
      message.success("策略配置已添加");
      setCreateOpen(false);
      await fetchConfigs();
    } catch (submitError) {
      if (submitError instanceof Error) {
        message.error(submitError.message);
      }
    } finally {
      setSubmitting(false);
    }
  };

  const handleEdit = async () => {
    if (!editingItem) {
      return;
    }
    try {
      const values = await editForm.validateFields();
      setSubmitting(true);
      const params = parseParamsJson(String(values.paramsText ?? ""));
      const resolvedBase = getResolvedApiBaseUrl();
      const baseWithSlash = resolvedBase.endsWith("/")
        ? resolvedBase
        : `${resolvedBase}/`;
      const url = new URL(`strategy-configs/${encodeURIComponent(editingItem.strategy_id)}`, baseWithSlash);
      const response = await fetch(url.toString(), {
        method: "PUT",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          params,
          daily_write_limit: Number(values.daily_write_limit ?? 0),
          priority: Number(values.priority ?? 0),
          active: Boolean(values.active),
        }),
      });
      if (!response.ok) {
        throw new Error(await readErrorDetail(response));
      }
      message.success("策略配置已更新");
      setEditOpen(false);
      setEditingItem(null);
      await fetchConfigs();
    } catch (submitError) {
      if (submitError instanceof Error) {
        message.error(submitError.message);
      }
    } finally {
      setSubmitting(false);
    }
  };

  const handleToggleActive = async (item: StrategyConfigItem) => {
    setTogglingId(item.strategy_id);
    try {
      const resolvedBase = getResolvedApiBaseUrl();
      const baseWithSlash = resolvedBase.endsWith("/")
        ? resolvedBase
        : `${resolvedBase}/`;
      const url = new URL(
        `strategy-configs/${encodeURIComponent(item.strategy_id)}/active`,
        baseWithSlash,
      );
      const response = await fetch(url.toString(), {
        method: "PATCH",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ active: !item.active }),
      });
      if (!response.ok) {
        throw new Error(await readErrorDetail(response));
      }
      message.success(item.active ? "策略已暂停" : "策略已开始");
      await fetchConfigs();
    } catch (toggleError) {
      message.error(
        toggleError instanceof Error ? toggleError.message : "操作失败",
      );
    } finally {
      setTogglingId(null);
    }
  };

  const columns: ColumnsType<StrategyConfigItem> = useMemo(
    () => [
      {
        title: "策略 ID",
        dataIndex: "strategy_id",
        width: 220,
        render: (value) => <EllipsisCell value={value} />,
      },
      {
        title: "策略名称",
        dataIndex: "name",
        width: 160,
        render: (value) => value ?? "-",
      },
      {
        title: "版本",
        dataIndex: "version",
        width: 100,
        render: (value) => value ?? "-",
      },
      {
        title: "状态",
        dataIndex: "active",
        width: 100,
        render: (active: boolean) => (
          <Tag color={active ? "green" : "default"}>
            {active ? "运行中" : "已暂停"}
          </Tag>
        ),
      },
      {
        title: "代码注册",
        dataIndex: "registered",
        width: 110,
        render: (registered: boolean) => (
          <Tag color={registered ? "blue" : "orange"}>
            {registered ? "已注册" : "未注册"}
          </Tag>
        ),
      },
      {
        title: "日写入上限",
        dataIndex: "daily_write_limit",
        width: 110,
        render: (value: number) => formatExperimentNumber(value),
      },
      {
        title: "优先级",
        dataIndex: "priority",
        width: 90,
        render: (value: number) => formatExperimentNumber(value),
      },
      {
        title: "运行参数",
        dataIndex: "params",
        render: (params: Record<string, unknown>) => (
          <EllipsisCell value={formatParamsPreview(params)} />
        ),
      },
      {
        title: "更新时间",
        dataIndex: "updated_time",
        width: 180,
        render: (value) => value ?? "-",
      },
      {
        title: "操作",
        key: "actions",
        width: 220,
        fixed: "right",
        render: (_, record) => (
          <Space size="small">
            <Button type="link" size="small" onClick={() => openEditModal(record)}>
              修改
            </Button>
            <Button
              type="link"
              size="small"
              loading={togglingId === record.strategy_id}
              onClick={() => void handleToggleActive(record)}
            >
              {record.active ? "暂停" : "开始"}
            </Button>
          </Space>
        ),
      },
    ],
    [togglingId],
  );

  return (
    <div className="page">
      <div className="hero">
        <Typography.Title level={2} className="hero-title">
          需求策略配置
        </Typography.Title>
        <div className="hero-subtitle">
          <Tag color="blue">策略管理</Tag>
          <Tag color="cyan">参数配置</Tag>
          <Tag color="green">启停控制</Tag>
          <Tag color="purple">实验写入 ODPS</Tag>
        </div>
      </div>

      <div className="dashboard-shell">
        <div className="panel-sheet">
          <section className="panel-section panel-section--table">
            <div className="table-toolbar">
              <Space wrap>
                <Button
                  type="primary"
                  icon={<PlusOutlined />}
                  onClick={openCreateModal}
                  disabled={loading}
                >
                  添加策略
                </Button>
                <Button
                  icon={<ReloadOutlined />}
                  onClick={() => void fetchConfigs()}
                  loading={loading}
                >
                  刷新
                </Button>
              </Space>
            </div>

            {error ? (
              <Alert
                type="error"
                showIcon
                message={error}
                style={{ marginBottom: 16 }}
              />
            ) : null}

            <Table<StrategyConfigItem>
              rowKey="strategy_id"
              loading={loading}
              columns={columns}
              dataSource={sortedItems}
              pagination={false}
              scroll={{ x: 1200 }}
              locale={{ emptyText: "暂无策略配置，点击「添加策略」创建" }}
            />
          </section>
        </div>
      </div>

      <Modal
        title="添加策略配置"
        open={createOpen}
        onCancel={() => setCreateOpen(false)}
        onOk={() => void handleCreate()}
        confirmLoading={submitting}
        okText="添加"
        cancelText="取消"
        destroyOnClose
        width={640}
      >
        <Form form={createForm} layout="vertical">
          <Form.Item
            label="策略"
            name="strategy_id"
            rules={[{ required: true, message: "请选择策略" }]}
          >
            <Select
              placeholder="选择要添加的策略"
              options={availableItems.map((item) => ({
                value: item.strategy_id,
                label: `${item.name} (${item.strategy_id})`,
              }))}
              notFoundContent="暂无可添加策略"
            />
          </Form.Item>
          <Form.Item
            label="日写入上限"
            name="daily_write_limit"
            extra={DAILY_LIMIT_HINT}
          >
            <InputNumber min={0} precision={0} style={{ width: "100%" }} />
          </Form.Item>
          <Form.Item
            label="优先级"
            name="priority"
            extra={PRIORITY_HINT}
          >
            <InputNumber min={0} precision={0} style={{ width: "100%" }} />
          </Form.Item>
          <Form.Item
            label="运行参数 (JSON)"
            name="paramsText"
            rules={[{ required: true, message: "请输入运行参数" }]}
            extra={PARAMS_HINT}
          >
            <Input.TextArea rows={8} placeholder="{}" />
          </Form.Item>
          <Form.Item label="创建后立即开始" name="active" valuePropName="checked">
            <Switch />
          </Form.Item>
        </Form>
      </Modal>

      <Modal
        title={editingItem ? `修改策略：${editingItem.name}` : "修改策略配置"}
        open={editOpen}
        onCancel={() => {
          setEditOpen(false);
          setEditingItem(null);
        }}
        onOk={() => void handleEdit()}
        confirmLoading={submitting}
        okText="保存"
        cancelText="取消"
        destroyOnClose
        width={640}
      >
        <Form form={editForm} layout="vertical">
          <Form.Item
            label="日写入上限"
            name="daily_write_limit"
            extra={DAILY_LIMIT_HINT}
          >
            <InputNumber min={0} precision={0} style={{ width: "100%" }} />
          </Form.Item>
          <Form.Item
            label="优先级"
            name="priority"
            extra={PRIORITY_HINT}
          >
            <InputNumber min={0} precision={0} style={{ width: "100%" }} />
          </Form.Item>
          <Form.Item
            label="运行参数 (JSON)"
            name="paramsText"
            rules={[{ required: true, message: "请输入运行参数" }]}
            extra={PARAMS_HINT}
          >
            <Input.TextArea rows={10} />
          </Form.Item>
          <Form.Item label="运行状态" name="active" valuePropName="checked">
            <Switch checkedChildren="运行中" unCheckedChildren="已暂停" />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
