import crypto from 'crypto';
import { NextRequest } from 'next/server';
import { decryptSecret, encryptSecret, previewSecret } from '@/lib/server-crypto';
import { getAuthenticatedUserId } from '@/lib/session-auth';
import { getDbClient } from '@/storage/database/local-db';
import { isProductionRuntime } from '@/lib/runtime-env';

export type ServerManagedApiConfig = {
  id: string;
  provider: string;
  name: string;
  apiUrl: string;
  modelName: string;
  modelGroup: string;
  note: string;
  apiKey: string;
  apiKeyPreview: string;
  type: 'image' | 'video' | 'text';
  creditsPerUse: number;
  billingMode: 'fixed' | 'ratio' | 'token';
  fixedPrice: number;
  inputPricePer1K: number;
  outputPricePer1K: number;
  modelRatio: number;
  completionRatio: number;
  groupRatio: number;
  priceNote: string;
  isActive: boolean;
  sortOrder: number;
  createdAt?: string;
  updatedAt?: string | null;
};

export type ClientApiConfigRef = {
  apiUrl?: string;
  modelName?: string;
  apiKey?: string;
  provider?: string;
  customApiKeyId?: string;
  systemApiId?: string;
};

const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;

export function isUuid(value: unknown): value is string {
  return typeof value === 'string' && UUID_REGEX.test(value);
}

export function getInternalGenerationSecret(): string {
  const secret = process.env.GENERATION_INTERNAL_SECRET || process.env.JWT_SECRET || process.env.DATA_ENCRYPTION_KEY;
  if (secret) return secret;
  if (isProductionRuntime()) {
    throw new Error('GENERATION_INTERNAL_SECRET, JWT_SECRET or DATA_ENCRYPTION_KEY is required in production');
  }
  return 'miaojing-local-generation-secret';
}

export function getInternalGenerationHeaders(): Record<string, string> {
  return { 'x-miaojing-generation-internal': getInternalGenerationSecret() };
}

export function isTrustedInternalGenerationRequest(request: NextRequest): boolean {
  const provided = request.headers.get('x-miaojing-generation-internal') || '';
  const expected = getInternalGenerationSecret();
  const providedBuffer = Buffer.from(provided);
  const expectedBuffer = Buffer.from(expected);
  return providedBuffer.length === expectedBuffer.length
    && crypto.timingSafeEqual(providedBuffer, expectedBuffer);
}

export async function ensureSystemApiSchema(client: Awaited<ReturnType<typeof getDbClient>>): Promise<void> {
  await client.query(`
    CREATE TABLE IF NOT EXISTS system_api_configs (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      provider VARCHAR(128),
      name VARCHAR(255) NOT NULL,
      api_url TEXT NOT NULL DEFAULT '',
      model_name VARCHAR(255) NOT NULL,
      model_group VARCHAR(128) NOT NULL DEFAULT 'default',
      note TEXT NOT NULL DEFAULT '',
      api_key_encrypted TEXT NOT NULL DEFAULT '',
      api_key_preview VARCHAR(64) NOT NULL DEFAULT '',
      type VARCHAR(16) NOT NULL DEFAULT 'image',
      credits_per_use INTEGER NOT NULL DEFAULT 10,
      billing_mode VARCHAR(24) NOT NULL DEFAULT 'fixed',
      fixed_price NUMERIC(12, 4) NOT NULL DEFAULT 0,
      input_price_per_1k NUMERIC(12, 6) NOT NULL DEFAULT 0,
      output_price_per_1k NUMERIC(12, 6) NOT NULL DEFAULT 0,
      model_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      completion_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      group_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      price_note TEXT NOT NULL DEFAULT '',
      is_active BOOLEAN NOT NULL DEFAULT true,
      sort_order INTEGER NOT NULL DEFAULT 0,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      updated_at TIMESTAMPTZ
    )
  `);
  await client.query(`
    ALTER TABLE system_api_configs
      ADD COLUMN IF NOT EXISTS model_group VARCHAR(128) NOT NULL DEFAULT 'default',
      ADD COLUMN IF NOT EXISTS billing_mode VARCHAR(24) NOT NULL DEFAULT 'fixed',
      ADD COLUMN IF NOT EXISTS fixed_price NUMERIC(12, 4) NOT NULL DEFAULT 0,
      ADD COLUMN IF NOT EXISTS input_price_per_1k NUMERIC(12, 6) NOT NULL DEFAULT 0,
      ADD COLUMN IF NOT EXISTS output_price_per_1k NUMERIC(12, 6) NOT NULL DEFAULT 0,
      ADD COLUMN IF NOT EXISTS model_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      ADD COLUMN IF NOT EXISTS completion_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      ADD COLUMN IF NOT EXISTS group_ratio NUMERIC(12, 6) NOT NULL DEFAULT 1,
      ADD COLUMN IF NOT EXISTS price_note TEXT NOT NULL DEFAULT ''
  `);
  await client.query('CREATE INDEX IF NOT EXISTS system_api_configs_active_type_sort_idx ON system_api_configs (is_active, type, sort_order)');
  await client.query('CREATE INDEX IF NOT EXISTS system_api_configs_group_type_sort_idx ON system_api_configs (model_group, type, sort_order)');
}

function normalizeBillingMode(value: unknown): ServerManagedApiConfig['billingMode'] {
  return value === 'ratio' || value === 'token' ? value : 'fixed';
}

export function toSafeSystemApi(row: Record<string, unknown>, includeInactive = true): Omit<ServerManagedApiConfig, 'apiKey'> & { apiKey: '' } {
  return {
    id: String(row.id || ''),
    provider: String(row.provider || ''),
    name: String(row.name || ''),
    apiUrl: String(row.api_url || ''),
    modelName: String(row.model_name || ''),
    modelGroup: String(row.model_group || 'default'),
    note: String(row.note || ''),
    apiKey: '',
    apiKeyPreview: String(row.api_key_preview || ''),
    type: row.type === 'video' || row.type === 'text' ? row.type : 'image',
    creditsPerUse: Number(row.credits_per_use || 0),
    billingMode: normalizeBillingMode(row.billing_mode),
    fixedPrice: Number(row.fixed_price || 0),
    inputPricePer1K: Number(row.input_price_per_1k || 0),
    outputPricePer1K: Number(row.output_price_per_1k || 0),
    modelRatio: Number(row.model_ratio || 1),
    completionRatio: Number(row.completion_ratio || 1),
    groupRatio: Number(row.group_ratio || 1),
    priceNote: String(row.price_note || ''),
    isActive: includeInactive ? row.is_active !== false : true,
    sortOrder: Number(row.sort_order || 0),
    createdAt: row.created_at ? String(row.created_at) : undefined,
    updatedAt: row.updated_at ? String(row.updated_at) : null,
  };
}

export async function listSystemApis(includeInactive = false) {
  const client = await getDbClient();
  try {
    await ensureSystemApiSchema(client);
    const result = await client.query(
      `SELECT id, provider, name, api_url, model_name, model_group, note, api_key_preview, type,
              credits_per_use, billing_mode, fixed_price, input_price_per_1k, output_price_per_1k,
              model_ratio, completion_ratio, group_ratio, price_note,
              is_active, sort_order, created_at, updated_at
       FROM system_api_configs
       ${includeInactive ? '' : 'WHERE is_active = true'}
       ORDER BY model_group ASC, sort_order ASC, created_at ASC`,
    );
    return result.rows.map(row => toSafeSystemApi(row, includeInactive));
  } finally {
    client.release();
  }
}

export async function resolveServerApiConfig(
  request: NextRequest,
  input: ClientApiConfigRef | undefined,
  trustedUserId?: string | null,
): Promise<ClientApiConfigRef | undefined> {
  if (!input) return undefined;

  if (isUuid(input.customApiKeyId)) {
    const userId = trustedUserId || await getAuthenticatedUserId(request);
    if (!userId) throw new Error('请先登录后再使用自定义 API');
    const client = await getDbClient();
    try {
      const result = await client.query(
        `SELECT provider, supplier_name, api_url, model_name, api_key_encrypted, type
         FROM user_api_keys
         WHERE id = $1 AND user_id = $2 AND is_active = true
         LIMIT 1`,
        [input.customApiKeyId, userId],
      );
      if (result.rows.length === 0) throw new Error('自定义 API 不存在或未启用');
      const row = result.rows[0];
      const apiKey = decryptSecret(row.api_key_encrypted);
      if (!apiKey) throw new Error('自定义 API 密钥不可用，请重新保存密钥');
      return {
        provider: row.supplier_name || row.provider || 'custom',
        apiUrl: row.api_url || input.apiUrl || '',
        modelName: row.model_name || input.modelName || '',
        apiKey,
      };
    } finally {
      client.release();
    }
  }

  if (isUuid(input.systemApiId)) {
    const hasAccess = trustedUserId || isTrustedInternalGenerationRequest(request) || await getAuthenticatedUserId(request);
    if (!hasAccess) throw new Error('请先登录后再使用系统 API');
    const client = await getDbClient();
    try {
      await ensureSystemApiSchema(client);
      const result = await client.query(
        `SELECT provider, name, api_url, model_name, api_key_encrypted
         FROM system_api_configs
         WHERE id = $1 AND is_active = true
         LIMIT 1`,
        [input.systemApiId],
      );
      if (result.rows.length === 0) throw new Error('系统 API 不存在或未启用');
      const row = result.rows[0];
      return {
        provider: row.provider || row.name || 'system',
        apiUrl: row.api_url || input.apiUrl || '',
        modelName: row.model_name || input.modelName || '',
        apiKey: decryptSecret(row.api_key_encrypted) || '',
      };
    } finally {
      client.release();
    }
  }

  if (input.apiKey) return input;
  return undefined;
}

export function encryptApiKeyForStorage(apiKey: string) {
  const normalized = apiKey.trim();
  return {
    encrypted: normalized ? encryptSecret(normalized) : '',
    preview: normalized ? previewSecret(normalized) : '',
  };
}
