import { useSettingsStore } from '@/store/use-settings';
import { LLMService } from './llm-service';
import {
  ConnectionValidationResult,
  createValidationSuccess,
  createValidationError,
  ApiErrorType,
} from '@/types/settings';

// Provider settings interface
export interface ProviderSettings {
  apiKey: string;
  baseUrl: string;
  modelName: string;
}

// Validation result interface (legacy for backward compatibility)
export interface ValidationResult {
  isValid: boolean;
  error?: string;
}

/**
 * Settings Service - Business logic for settings management
 * Following Logic Sandwich pattern: UI -> Store -> Service
 */
export class SettingsService {
  /**
   * Save provider settings to the store
   * @param settings - The provider settings to save
   */
  static saveProviderSettings(settings: ProviderSettings): void {
    const actions = useSettingsStore.getState().actions;

    actions.setApiKey(settings.apiKey);
    actions.setBaseUrl(settings.baseUrl);
    actions.setModelName(settings.modelName);

    // Note: Persistence to localStorage is handled automatically by Zustand persist middleware
  }

  /**
   * Get current provider settings from the store
   * @returns Current provider settings
   */
  static getProviderSettings(): ProviderSettings {
    const state = useSettingsStore.getState();

    return {
      apiKey: state.apiKey,
      baseUrl: state.baseUrl,
      modelName: state.modelName,
    };
  }

  /**
   * Validate provider settings structure
   * @param settings - The settings to validate
   * @returns Validation result
   */
  static validateProviderSettings(settings: ProviderSettings): ValidationResult {
    // Check API key
    if (!settings.apiKey || settings.apiKey.trim().length === 0) {
      return { isValid: false, error: 'API Key is required' };
    }

    // Check base URL format
    try {
      new URL(settings.baseUrl);
    } catch {
      return { isValid: false, error: 'Base URL must be a valid URL' };
    }

    // Check model name
    // Check model name
    const modelName = settings.modelName?.trim() || '';
    if (modelName.length === 0) {
      return { isValid: false, error: 'Model Name is required' };
    }

    // Fix: Weak Validation finding
    if (modelName.length < 2) {
      return { isValid: false, error: 'Model Name must be at least 2 characters' };
    }

    // Allow alphanumeric, dashes, dots, slashes, colons (common model ID chars)
    // e.g., "gpt-4", "anthropic/claude-3", "llama2:7b"
    const validModelRegex = /^[a-zA-Z0-9\-\.\/\:_]+$/;
    if (!validModelRegex.test(modelName)) {
      return { isValid: false, error: 'Model Name contains invalid characters' };
    }

    return { isValid: true };
  }

  /**
   * Validate provider connection by making a test API call
   * @returns Promise that resolves to validation result
   */
  static async validateProviderConnection(): Promise<ValidationResult> {
    const settings = this.getProviderSettings();

    // First validate structure
    const structureValidation = this.validateProviderSettings(settings);
    if (!structureValidation.isValid) {
      return structureValidation;
    }

    // Then validate connection with detailed error info
    const detailedResult = await LLMService.validateConnection(
      settings.baseUrl,
      settings.apiKey,
      settings.modelName
    );

    // Map detailed result to legacy ValidationResult format
    if (detailedResult.isValid) {
      return { isValid: true };
    } else {
      return {
        isValid: false,
        error: detailedResult.errorMessage || 'Connection failed',
      };
    }
  }

  /**
   * Check if provider is configured
   * @returns true if provider is configured
   */
  static isProviderConfigured(): boolean {
    return useSettingsStore.getState().isConfigured;
  }

  /**
   * Clear all provider settings
   */
  static clearProviderSettings(): void {
    useSettingsStore.getState().actions.clearSettings();
  }

  /**
   * Validate connection and return detailed result (Story 4.2)
   * @param settings - The provider settings to validate
   * @returns Promise resolving to ConnectionValidationResult
   */
  static async validateConnectionWithDetails(
    settings: ProviderSettings
  ): Promise<ConnectionValidationResult> {
    // First validate structure
    const structureValidation = this.validateProviderSettings(settings);
    if (!structureValidation.isValid) {
      // Return structure validation error with actual message
      return {
        isValid: false,
        errorMessage: structureValidation.error,
        errorType: ApiErrorType.UNKNOWN,
        rawError: structureValidation.error,
      };
    }

    // Then validate connection with detailed error info
    return await LLMService.validateConnection(
      settings.baseUrl,
      settings.apiKey,
      settings.modelName
    );
  }

  /**
   * Save provider settings only after validation passes (Story 4.2)
   * @param settings - The provider settings to validate and save
   * @returns Promise resolving to undefined if success, ConnectionValidationResult if failed
   */
  static async saveProviderSettingsWithValidation(
    settings: ProviderSettings
  ): Promise<ConnectionValidationResult | undefined> {
    // Validate structure first
    const structureValidation = this.validateProviderSettings(settings);
    if (!structureValidation.isValid) {
      // Return structure validation error with actual message
      return {
        isValid: false,
        errorMessage: structureValidation.error,
        errorType: ApiErrorType.UNKNOWN,
        rawError: structureValidation.error,
      };
    }

    // Validate connection
    const connectionValidation = await this.validateConnectionWithDetails(settings);
    if (!connectionValidation.isValid) {
      return connectionValidation; // Return error without saving
    }

    // All validations passed - save settings
    this.saveProviderSettings(settings);
    return undefined; // Success
  }
}
