import React, { useEffect } from 'react';
import { Alert, Button, DatePicker, Divider, Form, Input, InputNumber, Select, Space } from 'antd';
import dayjs from 'dayjs';
import type {
  ModelPricingBillingMode,
  ModelPricingCalculatorVersion,
  ModelPricingRule,
  ModelPricingRulePayload,
} from '../../types';

interface Props {
  initial?: ModelPricingRule | null;
  loading?: boolean;
  onSubmit: (payload: ModelPricingRulePayload) => Promise<void> | void;
  onCancel: () => void;
}

const modeOptions = [
  { value: 'text_token_tiered', label: '文本分档 Token 计价' },
  { value: 'image_per_output', label: '按输出图片数量计价' },
  { value: 'image_input_output_tiered', label: '输入图片 + 输出像素分档计价' },
  { value: 'video_token_rate', label: '视频像素 Token 计价' },
];

const calculatorByMode: Record<ModelPricingBillingMode, ModelPricingCalculatorVersion> = {
  text_token_tiered: 'text_token_tiered_v1',
  image_per_output: 'image_per_output_v1',
  image_input_output_tiered: 'image_input_output_tiered_v1',
  video_token_rate: 'video_pixel_token_v1',
};

const billByOptions = [
  { value: 'successful_output_count', label: '实际成功输出数' },
  { value: 'requested_output_count', label: '请求输出数（估算）' },
  { value: 'provider_billed_count', label: '供应商明确计费数' },
];

function splitList(value?: string): string[] {
  return String(value || '').split(',').map(v => v.trim()).filter(Boolean);
}

function readAlias(source: Record<string, any>, snakeKey: string, camelKey: string): any {
  if (Object.prototype.hasOwnProperty.call(source, snakeKey)) return source[snakeKey];
  return source[camelKey];
}

function removeKeys(source: Record<string, any>, keys: string[]): Record<string, any> {
  const result = { ...source };
  keys.forEach(key => delete result[key]);
  return result;
}

function normalizeTextTier(value: Record<string, any>): Record<string, any> {
  const result = removeKeys(value || {}, [
    'max_context_tokens', 'maxContextTokens',
    'input_rate', 'inputRate',
    'audio_input_rate', 'audioInputRate',
    'output_rate', 'outputRate',
    'cached_input_rate', 'cachedInputRate',
    'cached_audio_input_rate', 'cachedAudioInputRate',
  ]);
  const maxContextTokens = readAlias(value || {}, 'max_context_tokens', 'maxContextTokens');
  return {
    ...result,
    max_context_tokens: maxContextTokens === undefined ? null : maxContextTokens,
    input_rate: readAlias(value || {}, 'input_rate', 'inputRate'),
    audio_input_rate: readAlias(value || {}, 'audio_input_rate', 'audioInputRate'),
    output_rate: readAlias(value || {}, 'output_rate', 'outputRate'),
    cached_input_rate: readAlias(value || {}, 'cached_input_rate', 'cachedInputRate'),
    cached_audio_input_rate: readAlias(value || {}, 'cached_audio_input_rate', 'cachedAudioInputRate'),
  };
}

function normalizeOutputTier(value: Record<string, any>): Record<string, any> {
  const result = removeKeys(value || {}, ['max_pixels', 'maxPixels']);
  const maxPixels = readAlias(value || {}, 'max_pixels', 'maxPixels');
  return {
    ...result,
    max_pixels: maxPixels === undefined ? null : maxPixels,
    rate: value?.rate,
  };
}

function normalizeVideoRate(value: Record<string, any>): Record<string, any> {
  const result = removeKeys(value || {}, [
    'has_input_video', 'hasInputVideo',
    'generate_audio', 'generateAudio',
    'inference_modes', 'inferenceModes',
  ]);
  const hasInputVideo = readAlias(value || {}, 'has_input_video', 'hasInputVideo');
  const generateAudio = readAlias(value || {}, 'generate_audio', 'generateAudio');
  const inferenceModes = readAlias(value || {}, 'inference_modes', 'inferenceModes');
  return {
    ...result,
    ...(hasInputVideo === undefined ? {} : { has_input_video: hasInputVideo }),
    ...(generateAudio === undefined ? {} : { generate_audio: generateAudio }),
    ...(inferenceModes === undefined ? {} : { inference_modes: inferenceModes }),
  };
}

/**
 * 后端规则 JSON 统一使用 snake_case；同时兼容接口层已转换成 camelCase 的历史/当前数据。
 * 返回值会移除已知 camelCase 别名，避免保存时同时存在两套字段。
 */
function normalizeRuleJson(
  mode: ModelPricingBillingMode,
  value: Record<string, any>,
): Record<string, any> {
  const source = value || {};
  const base = removeKeys(source, [
    'cache_storage_rate_per_million_token_hour', 'cacheStorageRatePerMillionTokenHour',
    'output_rate', 'outputRate',
    'bill_by', 'billBy',
    'free_input_images', 'freeInputImages',
    'input_image_rate', 'inputImageRate',
    'output_tiers', 'outputTiers',
    'token_formula', 'tokenFormula',
    'default_fps', 'defaultFps',
    'supported_resolutions', 'supportedResolutions',
    'dimension_map', 'dimensionMap',
  ]);

  if (mode === 'text_token_tiered') {
    return {
      ...base,
      cache_storage_rate_per_million_token_hour: readAlias(
        source,
        'cache_storage_rate_per_million_token_hour',
        'cacheStorageRatePerMillionTokenHour',
      ),
      tiers: (Array.isArray(source.tiers) ? source.tiers : []).map(item => normalizeTextTier(item || {})),
    };
  }

  if (mode === 'image_per_output') {
    return {
      ...base,
      output_rate: readAlias(source, 'output_rate', 'outputRate'),
      bill_by: readAlias(source, 'bill_by', 'billBy'),
    };
  }

  if (mode === 'image_input_output_tiered') {
    const outputTiers = readAlias(source, 'output_tiers', 'outputTiers');
    return {
      ...base,
      free_input_images: readAlias(source, 'free_input_images', 'freeInputImages'),
      input_image_rate: readAlias(source, 'input_image_rate', 'inputImageRate'),
      output_tiers: (Array.isArray(outputTiers) ? outputTiers : []).map(item => normalizeOutputTier(item || {})),
      bill_by: readAlias(source, 'bill_by', 'billBy'),
    };
  }

  return {
    ...base,
    token_formula: readAlias(source, 'token_formula', 'tokenFormula'),
    default_fps: readAlias(source, 'default_fps', 'defaultFps'),
    supported_resolutions: readAlias(source, 'supported_resolutions', 'supportedResolutions'),
    dimension_map: readAlias(source, 'dimension_map', 'dimensionMap') || {},
    rates: (Array.isArray(source.rates) ? source.rates : []).map(item => normalizeVideoRate(item || {})),
  };
}

function dimensionRows(rule: Record<string, any>): Array<Record<string, any>> {
  const rows: Array<Record<string, any>> = [];
  Object.entries(rule.dimension_map || {}).forEach(([resolution, ratios]) => {
    Object.entries((ratios || {}) as Record<string, any>).forEach(([aspectRatio, value]) => {
      const item = value as Record<string, any>;
      rows.push({ resolution, aspectRatio, width: item.width, height: item.height });
    });
  });
  return rows;
}

function toFormPricing(mode: ModelPricingBillingMode, rule: Record<string, any>): Record<string, any> {
  const normalized = normalizeRuleJson(mode, rule || {});
  if (mode === 'text_token_tiered') {
    return {
      tiers: normalized.tiers || [],
      cacheStorageRate: normalized.cache_storage_rate_per_million_token_hour ?? 0,
    };
  }
  if (mode === 'image_per_output') {
    return {
      outputRate: normalized.output_rate ?? 0,
      billBy: normalized.bill_by || 'successful_output_count',
    };
  }
  if (mode === 'image_input_output_tiered') {
    return {
      freeInputImages: normalized.free_input_images ?? 1,
      inputImageRate: normalized.input_image_rate ?? 0,
      outputTiers: normalized.output_tiers || [],
      billBy: normalized.bill_by || 'successful_output_count',
    };
  }
  return {
    tokenFormula: normalized.token_formula
      || '(input_video_seconds + output_video_seconds) * width * height * fps / 1024',
    supportedResolutions: (normalized.supported_resolutions || []).join(','),
    defaultFps: normalized.default_fps ?? 30,
    dimensionRows: dimensionRows(normalized),
    rates: (normalized.rates || []).map((r: any) => ({
      ...r,
      resolutions: (r.resolutions || []).join(','),
      inferenceModes: (r.inference_modes || []).join(','),
      hasInputVideo: r.has_input_video === undefined ? 'any' : r.has_input_video ? 'true' : 'false',
      generateAudio: r.generate_audio === undefined ? 'any' : r.generate_audio ? 'true' : 'false',
    })),
  };
}

function buildDimensionMap(rows: Array<Record<string, any>>): Record<string, any> {
  const result: Record<string, any> = {};
  (rows || []).forEach(row => {
    const resolution = String(row.resolution || '').trim().toLowerCase();
    const aspectRatio = String(row.aspectRatio || '').trim();
    const width = Number(row.width || 0);
    const height = Number(row.height || 0);
    if (!resolution || !aspectRatio || width <= 0 || height <= 0) return;
    result[resolution] ||= {};
    result[resolution][aspectRatio] = { width, height };
  });
  return result;
}

function buildRuleJson(
  mode: ModelPricingBillingMode,
  pricing: Record<string, any>,
  baseRule: Record<string, any>,
): Record<string, any> {
  const base = normalizeRuleJson(mode, baseRule || {});
  if (mode === 'text_token_tiered') {
    return {
      ...base,
      unit: 'CNY_per_million_tokens',
      cache_storage_rate_per_million_token_hour: String(pricing.cacheStorageRate ?? 0),
      tiers: (pricing.tiers || []).map((v: any) => ({
        max_context_tokens: readAlias(v || {}, 'max_context_tokens', 'maxContextTokens') === '' || readAlias(v || {}, 'max_context_tokens', 'maxContextTokens') === undefined
          ? null
          : readAlias(v || {}, 'max_context_tokens', 'maxContextTokens'),
        input_rate: String(readAlias(v || {}, 'input_rate', 'inputRate') ?? 0),
        audio_input_rate: String(readAlias(v || {}, 'audio_input_rate', 'audioInputRate') ?? readAlias(v || {}, 'input_rate', 'inputRate') ?? 0),
        output_rate: String(readAlias(v || {}, 'output_rate', 'outputRate') ?? 0),
        cached_input_rate: String(readAlias(v || {}, 'cached_input_rate', 'cachedInputRate') ?? readAlias(v || {}, 'input_rate', 'inputRate') ?? 0),
        cached_audio_input_rate: String(
          readAlias(v || {}, 'cached_audio_input_rate', 'cachedAudioInputRate')
            ?? readAlias(v || {}, 'cached_input_rate', 'cachedInputRate')
            ?? readAlias(v || {}, 'audio_input_rate', 'audioInputRate')
            ?? readAlias(v || {}, 'input_rate', 'inputRate')
            ?? 0,
        ),
      })),
    };
  }
  if (mode === 'image_per_output') {
    return {
      ...base,
      unit: 'CNY_per_image',
      output_rate: String(pricing.outputRate ?? 0),
      bill_by: pricing.billBy || 'successful_output_count',
    };
  }
  if (mode === 'image_input_output_tiered') {
    return {
      ...base,
      unit: 'CNY_per_image',
      free_input_images: Number(pricing.freeInputImages || 0),
      input_image_rate: String(pricing.inputImageRate ?? 0),
      output_tiers: (pricing.outputTiers || []).map((v: any) => ({
        max_pixels: readAlias(v || {}, 'max_pixels', 'maxPixels') === undefined
          || readAlias(v || {}, 'max_pixels', 'maxPixels') === null
          || readAlias(v || {}, 'max_pixels', 'maxPixels') === ''
          ? null
          : Number(readAlias(v || {}, 'max_pixels', 'maxPixels')),
        rate: String(v.rate ?? 0),
      })),
      bill_by: pricing.billBy || 'successful_output_count',
    };
  }
  return {
    ...base,
    unit: 'CNY_per_million_tokens',
    token_formula: '(input_video_seconds + output_video_seconds) * width * height * fps / 1024',
    default_fps: Number(pricing.defaultFps || 30),
    supported_resolutions: splitList(pricing.supportedResolutions).map(v => v.toLowerCase()),
    dimension_map: buildDimensionMap(pricing.dimensionRows || []),
    rates: (pricing.rates || []).map((v: any) => ({
      ...(splitList(v.resolutions).length
        ? { resolutions: splitList(v.resolutions).map(item => item.toLowerCase()) }
        : {}),
      ...(v.hasInputVideo !== 'any' && v.hasInputVideo !== undefined
        ? { has_input_video: v.hasInputVideo === 'true' }
        : {}),
      ...(v.generateAudio !== 'any' && v.generateAudio !== undefined
        ? { generate_audio: v.generateAudio === 'true' }
        : {}),
      ...(splitList(v.inferenceModes).length
        ? { inference_modes: splitList(v.inferenceModes).map(item => item.toLowerCase()) }
        : {}),
      rate: String(v.rate ?? 0),
    })),
  };
}

const PricingRuleForm: React.FC<Props> = ({ initial, loading, onSubmit, onCancel }) => {
  const [form] = Form.useForm();
  const mode = Form.useWatch('billingMode', form) as ModelPricingBillingMode | undefined;

  useEffect(() => {
    const billingMode = initial?.billingMode || 'video_token_rate';
    form.setFieldsValue({
      provider: initial?.provider || 'volcengine',
      modelName: initial?.modelName || '',
      modelCategory: initial?.modelCategory || 'video',
      billingMode,
      calculatorVersion: initial?.calculatorVersion || calculatorByMode[billingMode],
      versionCode: initial?.versionCode || `manual_${dayjs().format('YYYYMMDD_HHmmss')}`,
      effectiveRange: [
        dayjs(initial?.effectiveFrom || undefined),
        initial?.effectiveTo ? dayjs(initial.effectiveTo) : null,
      ],
      currency: initial?.currency || 'CNY',
      ruleSchemaVersion: initial?.ruleSchemaVersion || 1,
      sourceUrl: initial?.sourceUrl || 'https://www.volcengine.com/docs/82379/1544106',
      sourceUpdatedAt: initial?.sourceUpdatedAt ? dayjs(initial.sourceUpdatedAt) : null,
      remark: initial?.remark || '',
      pricing: toFormPricing(billingMode, initial?.ruleJson || {}),
    });
  }, [initial, form]);

  useEffect(() => {
    if (!mode) return;
    form.setFieldValue('calculatorVersion', calculatorByMode[mode]);
  }, [mode, form]);

  const submit = async (values: any) => {
    const billingMode = values.billingMode as ModelPricingBillingMode;
    const [from, to] = values.effectiveRange || [];
    const preserveBase = initial?.billingMode === billingMode ? initial.ruleJson : {};
    await onSubmit({
      provider: values.provider,
      model_name: values.modelName,
      model_category: values.modelCategory,
      billing_mode: billingMode,
      calculator_version: calculatorByMode[billingMode],
      version_code: values.versionCode,
      effective_from: from.toISOString(),
      effective_to: to ? to.toISOString() : null,
      currency: values.currency || 'CNY',
      rule_schema_version: Number(values.ruleSchemaVersion || initial?.ruleSchemaVersion || 1),
      rule_json: buildRuleJson(billingMode, values.pricing || {}, preserveBase || {}),
      source_url: values.sourceUrl || null,
      source_updated_at: values.sourceUpdatedAt ? values.sourceUpdatedAt.toISOString() : null,
      remark: values.remark || null,
    });
  };

  return (
    <Form form={form} layout="vertical" onFinish={submit} preserve={false}>
      <Alert
        type="warning"
        showIcon
        style={{ marginBottom: 16 }}
        message="种子规则只会创建草稿。请核对真实生效时间、单价和模型输出尺寸后再发布。"
      />
      <Space size={12} align="start" style={{ display: 'flex' }}>
        <Form.Item name="provider" label="供应商" rules={[{ required: true }]} style={{ flex: 1 }}><Input /></Form.Item>
        <Form.Item name="modelName" label="完整模型名称" rules={[{ required: true }]} style={{ flex: 2 }}><Input /></Form.Item>
      </Space>
      <Space size={12} align="start" style={{ display: 'flex' }}>
        <Form.Item name="modelCategory" label="模型类型" rules={[{ required: true }]} style={{ flex: 1 }}>
          <Select options={[{ value: 'text', label: '文本' }, { value: 'image', label: '图片' }, { value: 'video', label: '视频' }]} />
        </Form.Item>
        <Form.Item name="billingMode" label="计价模式" rules={[{ required: true }]} style={{ flex: 2 }}>
          <Select options={modeOptions} />
        </Form.Item>
        <Form.Item name="calculatorVersion" label="计算器版本" style={{ flex: 2 }}><Input disabled /></Form.Item>
      </Space>
      <Space size={12} align="start" style={{ display: 'flex' }}>
        <Form.Item name="versionCode" label="价格版本号" rules={[{ required: true }]} style={{ flex: 1 }}><Input /></Form.Item>
        <Form.Item name="effectiveRange" label="真实生效区间 [开始, 结束)" rules={[{ required: true }]} style={{ flex: 2 }}>
          <DatePicker.RangePicker showTime allowEmpty={[false, true]} style={{ width: '100%' }} />
        </Form.Item>
        <Form.Item name="currency" label="币种" style={{ width: 100 }}><Input /></Form.Item>
        <Form.Item name="ruleSchemaVersion" label="结构版本" style={{ width: 100 }}><InputNumber min={1} /></Form.Item>
      </Space>

      <Divider orientation="left">价格参数</Divider>
      {mode === 'text_token_tiered' && <>
        <Form.Item name={['pricing', 'cacheStorageRate']} label="缓存存储单价（元/M Token·小时）">
          <InputNumber min={0} stringMode style={{ width: 260 }} />
        </Form.Item>
        <Form.List name={['pricing', 'tiers']}>
          {(fields, { add, remove }) => <>
            {fields.map(field => (
              <Space key={field.key} align="baseline" wrap>
                <Form.Item {...field} name={[field.name, 'max_context_tokens']} label="最大上下文 Token"><InputNumber min={1} /></Form.Item>
                <Form.Item {...field} name={[field.name, 'input_rate']} label="输入单价/M"><InputNumber min={0} stringMode /></Form.Item>
                <Form.Item {...field} name={[field.name, 'audio_input_rate']} label="音频输入/M"><InputNumber min={0} stringMode /></Form.Item>
                <Form.Item {...field} name={[field.name, 'cached_input_rate']} label="缓存文本/M"><InputNumber min={0} stringMode /></Form.Item>
                <Form.Item {...field} name={[field.name, 'cached_audio_input_rate']} label="缓存音频/M"><InputNumber min={0} stringMode /></Form.Item>
                <Form.Item {...field} name={[field.name, 'output_rate']} label="输出单价/M"><InputNumber min={0} stringMode /></Form.Item>
                <Button danger onClick={() => remove(field.name)}>删除</Button>
              </Space>
            ))}
            <Button onClick={() => add({})}>新增 Token 档位</Button>
          </>}
        </Form.List>
      </>}

      {mode === 'image_per_output' && <Space align="baseline">
        <Form.Item name={['pricing', 'outputRate']} label="输出图片单价（元/张）" rules={[{ required: true }]}>
          <InputNumber min={0} stringMode style={{ width: 220 }} />
        </Form.Item>
        <Form.Item name={['pricing', 'billBy']} label="计费数量来源"><Select style={{ width: 220 }} options={billByOptions} /></Form.Item>
      </Space>}

      {mode === 'image_input_output_tiered' && <>
        <Space align="baseline">
          <Form.Item name={['pricing', 'freeInputImages']} label="免费输入图片数"><InputNumber min={0} /></Form.Item>
          <Form.Item name={['pricing', 'inputImageRate']} label="超出后输入图片单价"><InputNumber min={0} stringMode /></Form.Item>
          <Form.Item name={['pricing', 'billBy']} label="输出计费数量来源"><Select style={{ width: 220 }} options={billByOptions} /></Form.Item>
        </Space>
        <Form.List name={['pricing', 'outputTiers']}>
          {(fields, { add, remove }) => <>
            {fields.map(field => <Space key={field.key} align="baseline">
              <Form.Item {...field} name={[field.name, 'max_pixels']} label="最大像素（末档留空）"><InputNumber min={1} /></Form.Item>
              <Form.Item {...field} name={[field.name, 'rate']} label="输出单价（元/张）"><InputNumber min={0} stringMode /></Form.Item>
              <Button danger onClick={() => remove(field.name)}>删除</Button>
            </Space>)}
            <Button onClick={() => add({ max_pixels: null, rate: 0 })}>新增输出像素档位</Button>
          </>}
        </Form.List>
      </>}

      {mode === 'video_token_rate' && <>
        <Form.Item name={['pricing', 'tokenFormula']} label="Token 公式说明（由计算器版本实现，不执行文本公式）"><Input disabled /></Form.Item>
        <Space align="baseline" wrap>
          <Form.Item name={['pricing', 'supportedResolutions']} label="支持分辨率（逗号分隔）"><Input placeholder="480p,720p" /></Form.Item>
          <Form.Item name={['pricing', 'defaultFps']} label="默认 FPS"><InputNumber min={1} max={120} /></Form.Item>
        </Space>
        <Divider orientation="left" plain>分辨率 + 比例对应真实像素</Divider>
        <Form.List name={['pricing', 'dimensionRows']}>
          {(fields, { add, remove }) => <>
            {fields.map(field => <Space key={field.key} align="baseline" wrap>
              <Form.Item {...field} name={[field.name, 'resolution']} label="分辨率" rules={[{ required: true }]}><Input placeholder="720p" /></Form.Item>
              <Form.Item {...field} name={[field.name, 'aspectRatio']} label="比例" rules={[{ required: true }]}><Input placeholder="9:16" /></Form.Item>
              <Form.Item {...field} name={[field.name, 'width']} label="宽" rules={[{ required: true }]}><InputNumber min={1} /></Form.Item>
              <Form.Item {...field} name={[field.name, 'height']} label="高" rules={[{ required: true }]}><InputNumber min={1} /></Form.Item>
              <Button danger onClick={() => remove(field.name)}>删除</Button>
            </Space>)}
            <Button onClick={() => add({})}>新增尺寸映射</Button>
          </>}
        </Form.List>
        <Divider orientation="left" plain>视频价格档位</Divider>
        <Form.List name={['pricing', 'rates']}>
          {(fields, { add, remove }) => <>
            {fields.map(field => <div key={field.key} style={{ border: '1px solid #eee', padding: 12, marginBottom: 12, borderRadius: 8 }}>
              <Space align="baseline" wrap>
                <Form.Item {...field} name={[field.name, 'resolutions']} label="分辨率"><Input placeholder="480p,720p；可空" /></Form.Item>
                <Form.Item {...field} name={[field.name, 'hasInputVideo']} label="含输入视频"><Select style={{ width: 120 }} options={[{ value: 'any', label: '不限' }, { value: 'true', label: '是' }, { value: 'false', label: '否' }]} /></Form.Item>
                <Form.Item {...field} name={[field.name, 'generateAudio']} label="生成音频"><Select style={{ width: 120 }} options={[{ value: 'any', label: '不限' }, { value: 'true', label: '是' }, { value: 'false', label: '否' }]} /></Form.Item>
                <Form.Item {...field} name={[field.name, 'inferenceModes']} label="推理模式"><Input placeholder="online,flex；可空" /></Form.Item>
                <Form.Item {...field} name={[field.name, 'rate']} label="单价/M Token" rules={[{ required: true }]}><InputNumber min={0} stringMode /></Form.Item>
                <Button danger onClick={() => remove(field.name)}>删除</Button>
              </Space>
            </div>)}
            <Button onClick={() => add({ hasInputVideo: 'any', generateAudio: 'any' })}>新增视频价格档位</Button>
          </>}
        </Form.List>
      </>}

      <Divider orientation="left">来源与备注</Divider>
      <Form.Item name="sourceUrl" label="官方来源 URL"><Input /></Form.Item>
      <Form.Item name="sourceUpdatedAt" label="官方文档更新时间（不是价格生效时间）"><DatePicker showTime /></Form.Item>
      <Form.Item name="remark" label="备注"><Input.TextArea rows={3} /></Form.Item>
      <Space style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <Button onClick={onCancel}>取消</Button>
        <Button type="primary" htmlType="submit" loading={loading}>保存草稿</Button>
      </Space>
    </Form>
  );
};

export default PricingRuleForm;
