import type { BaseModelCatalogItem } from '@easyai-ai-gateway/contracts';
import type { PlatformCreateInput, PlatformModelBindingInput } from '../../types';

export const authTypes = [
  { value: 'APIKey', label: 'API Key', description: 'apiKey 字段，兼容 OpenAI / Gemini' },
  { value: 'Token', label: 'Token', description: 'token 字段，适合 Bearer Token 类平台' },
  { value: 'AccessKey-SecretKey', label: 'AccessKey + SecretKey', description: 'accessKey / secretKey 双字段' },
  { value: 'none', label: '无授权', description: '仅用于内网或测试模式' },
];

export interface PlatformWizardForm {
  provider: string;
  platformKey: string;
  name: string;
  internalName: string;
  baseUrl: string;
  authType: string;
  credentialsPreview: Record<string, unknown>;
  apiKey: string;
  token: string;
  accessKey: string;
  secretKey: string;
  pricingRuleSetId: string;
  defaultDiscountFactor: string;
  priority: string;
  retryEnabled: boolean;
  retryMaxAttempts: string;
  rpmLimit: string;
  rpsLimit: string;
  tpmLimit: string;
  concurrencyLimit: string;
  testMode: boolean;
  proxyMode: 'none' | 'global' | 'custom';
  httpProxy: string;
  supportBase64Input: boolean;
  supportUrlInput: boolean;
  modelDiscountFactor: string;
  modelDiscountFactors: Record<string, string>;
  modelNameMappings: Record<string, string>;
  modelOverrideRetry: boolean;
  modelRetryEnabled: boolean;
  modelRetryMaxAttempts: string;
  modelOverrideRateLimit: boolean;
  modelRpmLimit: string;
  modelRpsLimit: string;
  modelTpmLimit: string;
  modelConcurrencyLimit: string;
  selectionMode: 'all' | 'partial';
  selectedModelIds: string[];
}

export interface ProviderConnectionDefaults {
  defaultAuthType?: string;
  defaultBaseUrl?: string;
}

export interface ProviderModelPreset {
  providerKey: string;
  providerCode?: string;
  providerModelName?: string;
  modelAlias?: string;
  displayName?: string;
  modelType?: string[];
  iconPath?: string;
  sourceProviderName?: string;
  baseProviderKey?: string;
}

export function createEmptyPlatformForm(provider = '', defaults?: ProviderConnectionDefaults): PlatformWizardForm {
  return {
    provider,
    platformKey: '',
    name: '',
    internalName: '',
    baseUrl: defaults?.defaultBaseUrl ?? '',
    authType: defaults?.defaultAuthType ?? 'APIKey',
    credentialsPreview: {},
    apiKey: '',
    token: '',
    accessKey: '',
    secretKey: '',
    pricingRuleSetId: '',
    defaultDiscountFactor: '1',
    priority: '100',
    retryEnabled: true,
    retryMaxAttempts: '2',
    rpmLimit: '',
    rpsLimit: '',
    tpmLimit: '',
    concurrencyLimit: '',
    testMode: false,
    proxyMode: 'none',
    httpProxy: '',
    supportBase64Input: true,
    supportUrlInput: true,
    modelDiscountFactor: '',
    modelDiscountFactors: {},
    modelNameMappings: {},
    modelOverrideRetry: false,
    modelRetryEnabled: true,
    modelRetryMaxAttempts: '2',
    modelOverrideRateLimit: false,
    modelRpmLimit: '',
    modelRpsLimit: '',
    modelTpmLimit: '',
    modelConcurrencyLimit: '',
    selectionMode: 'partial',
    selectedModelIds: [],
  };
}

export function applyProviderDefaults(form: PlatformWizardForm, provider: string, defaults?: ProviderConnectionDefaults): PlatformWizardForm {
  return {
    ...form,
    provider,
    baseUrl: defaults?.defaultBaseUrl ?? '',
    authType: defaults?.defaultAuthType ?? 'APIKey',
    selectedModelIds: [],
    modelDiscountFactors: {},
    modelNameMappings: {},
  };
}

export function modelsForProvider(models: BaseModelCatalogItem[], provider: string) {
  return models.filter((item) => item.status !== 'hidden' && modelMatchesProvider(item, provider));
}

export function selectedModelsForForm(models: BaseModelCatalogItem[], form: PlatformWizardForm) {
  const visibleModels = models.filter((item) => item.status !== 'hidden');
  if (form.selectionMode === 'all') {
    return visibleModels;
  }
  const selectedIds = new Set(form.selectedModelIds);
  return visibleModels.filter((item) => selectedIds.has(item.id));
}

export function platformPayload(form: PlatformWizardForm, options: { preserveEmptyCredentials?: boolean } = {}): PlatformCreateInput {
  const credentials = credentialsPayload(form, options);
  return {
    provider: form.provider,
    platformKey: optionalString(form.platformKey),
    name: form.name.trim(),
    internalName: optionalString(form.internalName),
    baseUrl: form.baseUrl.trim(),
    authType: form.authType,
    credentials,
    config: {
      testMode: form.testMode,
      networkProxy: networkProxyPayload(form),
      supportBase64Input: form.supportBase64Input,
      supportUrlInput: form.supportUrlInput,
      source: 'gateway-admin',
    },
    retryPolicy: {
      enabled: form.retryEnabled,
      maxAttempts: form.retryEnabled ? positiveInt(form.retryMaxAttempts, 2) : 1,
    },
    rateLimitPolicy: rateLimitPolicyPayload(form),
    defaultPricingMode: 'inherit_discount',
    defaultDiscountFactor: positiveNumber(form.defaultDiscountFactor, 1),
    pricingRuleSetId: optionalString(form.pricingRuleSetId),
    priority: positiveInt(form.priority, 100),
  };
}

export function platformModelPayloads(models: BaseModelCatalogItem[], form: PlatformWizardForm): PlatformModelBindingInput[] {
  return selectedModelsForForm(models, form).map((model) => {
    const preset = providerModelPresetFor(model, form.provider);
    const providerModelName =
      optionalString(form.modelNameMappings[model.id]) ??
      providerModelNameForProvider(model, form.provider);
    return {
      baseModelId: model.id,
      canonicalModelKey: model.canonicalModelKey,
      modelName: model.providerModelName,
      providerModelName,
      modelAlias: preset?.modelAlias || stableModelAlias(model),
      modelType: baseModelTypesForProvider(model, form.provider),
      displayName:
        preset?.displayName ||
        stableModelAlias(model) ||
        providerModelName ||
        model.providerModelName,
      pricingMode: 'inherit_discount',
      discountFactor: optionalPositiveNumber(form.modelDiscountFactors[model.id]) ?? optionalPositiveNumber(form.modelDiscountFactor),
      retryPolicy: form.modelOverrideRetry
        ? { enabled: form.modelRetryEnabled, maxAttempts: form.modelRetryEnabled ? positiveInt(form.modelRetryMaxAttempts, 2) : 1 }
        : undefined,
      rateLimitPolicy: form.modelOverrideRateLimit ? rateLimitPolicyPayload({
        rpmLimit: form.modelRpmLimit,
        rpsLimit: form.modelRpsLimit,
        tpmLimit: form.modelTpmLimit,
        concurrencyLimit: form.modelConcurrencyLimit,
      }) : undefined,
      runtimePolicyOverride: platformModelRuntimeOverride(form),
    };
  });
}

export function stableModelAlias(model: BaseModelCatalogItem) {
  return stripProviderPrefix(
    readString(model.modelAlias) ||
    readString(model.displayName) ||
    readString(model.metadata?.alias) ||
    readString(readRecord(model.metadata?.rawModel)?.alias) ||
    model.providerModelName ||
    model.canonicalModelKey,
    model.providerKey,
    model.canonicalModelKey,
  );
}

export function baseModelTypes(model: BaseModelCatalogItem) {
  if (Array.isArray(model.modelType)) return model.modelType.map(String).filter(Boolean);
  const values = model.metadata?.originalTypes ?? model.capabilities?.originalTypes;
  if (Array.isArray(values)) return values.map(String).filter(Boolean);
  return [];
}

export function providerModelPresets(model: BaseModelCatalogItem): ProviderModelPreset[] {
  const rawPresets = model.metadata?.providerModelPresets;
  if (!Array.isArray(rawPresets)) return [];
  return rawPresets
    .map(readRecord)
    .filter((item): item is Record<string, unknown> => Boolean(item))
    .map((item) => ({
      providerKey: readString(item.providerKey || item.providerCode),
      providerCode: readString(item.providerCode || item.providerKey),
      providerModelName: readString(item.providerModelName || item.realModelNameOverride),
      modelAlias: readString(item.modelAlias || item.alias),
      displayName: readString(item.displayName || item.modelAlias || item.alias),
      modelType: readStringArray(item.modelType || item.modelTypes),
      iconPath: readString(item.iconPath || item.icon_path),
      sourceProviderName: readString(item.sourceProviderName || item.providerName),
      baseProviderKey: readString(item.baseProviderKey || item.baseProviderCode),
    }))
    .filter((item) => item.providerKey);
}

export function providerModelPresetFor(model: BaseModelCatalogItem, provider: string) {
  const providerKey = provider.trim();
  if (!providerKey) return undefined;
  return providerModelPresets(model).find(
    (preset) => preset.providerKey === providerKey || preset.providerCode === providerKey,
  );
}

export function modelMatchesProvider(model: BaseModelCatalogItem, provider: string) {
  if (!provider) return true;
  return model.providerKey === provider || Boolean(providerModelPresetFor(model, provider));
}

export function providerModelNameForProvider(model: BaseModelCatalogItem, provider: string) {
  return providerModelPresetFor(model, provider)?.providerModelName || model.providerModelName;
}

export function baseModelTypesForProvider(model: BaseModelCatalogItem, provider: string) {
  const presetTypes = providerModelPresetFor(model, provider)?.modelType;
  return presetTypes?.length ? presetTypes : baseModelTypes(model);
}

export function baseModelTypeText(model: BaseModelCatalogItem) {
  return baseModelTypes(model).join(', ');
}

export function baseModelTypeTextForProvider(model: BaseModelCatalogItem, provider: string) {
  return baseModelTypesForProvider(model, provider).join(', ');
}

export function primaryBaseModelType(model: BaseModelCatalogItem) {
  return baseModelTypes(model)[0] ?? 'text_generate';
}

function stripProviderPrefix(value: string, providerKey: string, canonicalModelKey: string) {
  const trimmed = value.trim();
  if (!trimmed) return trimmed;
  const prefix = `${providerKey}:`;
  if (providerKey && trimmed.startsWith(prefix)) return trimmed.slice(prefix.length);
  if (trimmed === canonicalModelKey) {
    const [, alias] = trimmed.split(/:(.*)/s);
    return alias || trimmed;
  }
  return trimmed;
}

function readRecord(value: unknown) {
  return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
}

function readString(value: unknown) {
  return typeof value === 'string' ? value.trim() : '';
}

function readStringArray(value: unknown) {
  return Array.isArray(value) ? value.map(String).map((item) => item.trim()).filter(Boolean) : [];
}

function platformModelRuntimeOverride(form: PlatformWizardForm) {
  const override: Record<string, unknown> = {};
  if (form.modelOverrideRetry) {
    override.retryPolicy = {
      enabled: form.modelRetryEnabled,
      maxAttempts: form.modelRetryEnabled ? positiveInt(form.modelRetryMaxAttempts, 2) : 1,
    };
  }
  if (form.modelOverrideRateLimit) {
    override.rateLimitPolicy = rateLimitPolicyPayload({
      rpmLimit: form.modelRpmLimit,
      rpsLimit: form.modelRpsLimit,
      tpmLimit: form.modelTpmLimit,
      concurrencyLimit: form.modelConcurrencyLimit,
    });
  }
  return Object.keys(override).length ? override : undefined;
}

export function validatePlatformForm(form: PlatformWizardForm, selectedCount: number, options: { allowEmptyCredentials?: boolean } = {}): string {
  if (!form.provider.trim()) return '请选择模型厂商。';
  if (!form.name.trim()) return '请填写平台名称。';
  if (!form.baseUrl.trim()) return '请填写 Base URL。';
  if (options.allowEmptyCredentials && !hasCredentialInput(form)) {
    if (selectedCount === 0) return '请至少添加一个模型。';
    return '';
  }
  if (form.authType === 'APIKey' && !form.apiKey.trim() && !form.testMode) return '请填写 API Key，或开启测试模式。';
  if (form.authType === 'Token' && !form.token.trim() && !form.testMode) return '请填写 Token，或开启测试模式。';
  if (form.authType === 'AccessKey-SecretKey' && (!form.accessKey.trim() || !form.secretKey.trim()) && !form.testMode) {
    return '请填写 AccessKey 和 SecretKey，或开启测试模式。';
  }
  if (form.proxyMode === 'custom' && !form.httpProxy.trim()) return '请填写自定义 HTTP 代理地址。';
  if (selectedCount === 0) return '请至少添加一个模型。';
  return '';
}

export function providerLabel(provider: string) {
  return provider || 'provider';
}

function credentialsPayload(form: PlatformWizardForm, options: { preserveEmptyCredentials?: boolean } = {}) {
  if (form.authType === 'APIKey') {
    return credentialPayloadForFields(form, options, [{ key: 'apiKey', value: form.apiKey, previewKeys: ['apiKey', 'api_key', 'key'] }]);
  }
  if (form.authType === 'Token') {
    return credentialPayloadForFields(form, options, [{ key: 'token', value: form.token, previewKeys: ['token'] }]);
  }
  if (form.authType === 'AccessKey-SecretKey') {
    return credentialPayloadForFields(form, options, [
      { key: 'accessKey', value: form.accessKey, previewKeys: ['accessKey', 'access_key'] },
      { key: 'secretKey', value: form.secretKey, previewKeys: ['secretKey', 'secret_key'] },
    ]);
  }
  return {};
}

function credentialPayloadForFields(
  form: PlatformWizardForm,
  options: { preserveEmptyCredentials?: boolean },
  fields: Array<{ key: string; previewKeys: string[]; value: string }>,
) {
  const entries = fields.map((field) => ({
    key: field.key,
    preview: credentialPreviewValue(form.credentialsPreview, ...field.previewKeys),
    value: field.value.trim(),
  }));
  const allUnchanged = entries.every((entry) => entry.preview && entry.value === entry.preview);
  if (options.preserveEmptyCredentials && allUnchanged) return undefined;
  const allEmpty = entries.every((entry) => !entry.value);
  if (allEmpty) return {};
  const payloadEntries: Array<[string, string | null]> = [];
  for (const entry of entries) {
    if (entry.preview && entry.value === entry.preview) continue;
    payloadEntries.push([entry.key, entry.value || null]);
  }
  return Object.fromEntries(payloadEntries);
}

function hasCredentialInput(form: PlatformWizardForm) {
  if (form.authType === 'APIKey') return Boolean(form.apiKey.trim());
  if (form.authType === 'Token') return Boolean(form.token.trim());
  if (form.authType === 'AccessKey-SecretKey') return Boolean(form.accessKey.trim() || form.secretKey.trim());
  return true;
}

function credentialPreviewValue(preview: Record<string, unknown> | undefined, ...keys: string[]) {
  if (!preview) return '';
  for (const key of keys) {
    const value = preview[key];
    if (typeof value === 'string' && value.trim()) return value;
  }
  return '';
}

function rateLimitPolicyPayload(form: Pick<PlatformWizardForm, 'rpmLimit' | 'rpsLimit' | 'tpmLimit' | 'concurrencyLimit'>) {
  const rules = [
    limitRule('rpm', form.rpmLimit),
    limitRule('rps', form.rpsLimit, 1),
    limitRule('tpm_total', form.tpmLimit),
    limitRule('concurrent', form.concurrencyLimit),
  ].filter((rule): rule is NonNullable<ReturnType<typeof limitRule>> => Boolean(rule));
  return { rules };
}

function networkProxyPayload(form: PlatformWizardForm) {
  if (form.proxyMode === 'custom') {
    return {
      mode: 'custom',
      httpProxy: form.httpProxy.trim(),
    };
  }
  return { mode: form.proxyMode };
}

function limitRule(metric: string, value: string, windowSeconds = 60) {
  const limit = positiveNumber(value, 0);
  if (!limit) return undefined;
  return {
    metric,
    limit,
    windowSeconds,
    leaseTtlSeconds: metric === 'concurrent' ? 120 : 70,
  };
}

function optionalString(value: string | null | undefined) {
  const trimmed = value?.trim() ?? '';
  return trimmed || undefined;
}

function positiveNumber(value: string, fallback: number) {
  const parsed = Number(value);
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
}

function optionalPositiveNumber(value: string) {
  const parsed = Number(value);
  return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
}

function positiveInt(value: string, fallback: number) {
  const parsed = Number.parseInt(value, 10);
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
}
