import { geminiClient } from './geminiClient';
import {
  isTranslationProviderError,
  toTranslationProviderError,
  TranslationProvider,
  TranslationProviderError,
  StructuredTranslationFields,
  validateProviderResult,
} from './translationProvider';
import type { BulkStringItem, BulkTranslateResponse, GeminiTranslationResponse, Tone } from '../types';
import type { StructuredTranslationResponse } from './translationProvider';

export type GeminiProviderClient = Pick<
  TranslationProvider,
  'translate' | 'translateBulk' | 'translateStructured'
>;

function isBulkParseFailure(result: unknown): boolean {
  if (typeof result !== 'object' || result === null || !('results' in result)) return false;
  const results = (result as { results?: unknown }).results;
  return Array.isArray(results) && results.length > 0 && results.every(item =>
    typeof item === 'object' &&
    item !== null &&
    (item as { success?: unknown }).success === false &&
    (item as { error?: unknown }).error === 'Failed to parse bulk translation response as JSON'
  );
}

export class GeminiTranslationProvider implements TranslationProvider {
  private readonly client: GeminiProviderClient;

  constructor(client: GeminiProviderClient = geminiClient) {
    this.client = client;
  }

  async translate(
    content: string,
    sourceLang: string,
    targetLang: string,
    tone?: Tone
  ): Promise<GeminiTranslationResponse> {
    try {
      const result = await this.client.translate(content, sourceLang, targetLang, tone);
      return validateProviderResult('text', result);
    } catch (error) {
      throw this.normalizeError(error);
    }
  }

  async translateBulk(
    strings: BulkStringItem[],
    sourceLang: string,
    targetLang: string,
    tone?: Tone
  ): Promise<BulkTranslateResponse> {
    try {
      const result = await this.client.translateBulk(strings, sourceLang, targetLang, tone);
      if (isBulkParseFailure(result)) {
        throw new TranslationProviderError({ kind: 'malformed_response' });
      }
      return validateProviderResult('bulk', result, strings);
    } catch (error) {
      throw this.normalizeError(error);
    }
  }

  async translateStructured(
    fields: StructuredTranslationFields,
    sourceLang: string,
    targetLang: string,
    tone?: Tone
  ): Promise<StructuredTranslationResponse> {
    try {
      const result = await this.client.translateStructured(fields, sourceLang, targetLang, tone);
      return validateProviderResult('structured', result, fields);
    } catch (error) {
      throw this.normalizeError(error);
    }
  }

  private normalizeError(error: unknown): TranslationProviderError {
    if (isTranslationProviderError(error)) return error;
    return toTranslationProviderError(error);
  }
}

export const geminiTranslationProvider = new GeminiTranslationProvider();

export default geminiTranslationProvider;
