import type { ProjectSource } from "../types";

/**
 * Validates and builds source configurations with credentials
 */
export class SourceConfigBuilder {
  /**
   * Build IndexedDB source config
   */
  static indexedDB(dbName?: string): ProjectSource {
    return {
      type: "indexeddb",
      config: {
        dbName: dbName || `firesystem-${Date.now()}`
      }
    };
  }

  /**
   * Build Memory source config
   */
  static memory(initialData?: any): ProjectSource {
    return {
      type: "memory",
      config: {
        initialData
      }
    };
  }

  /**
   * Build S3 source config
   */
  static s3(config: {
    bucket: string;
    prefix?: string;
    region?: string;
    credentials?: {
      accessKeyId: string;
      secretAccessKey: string;
    };
  }): ProjectSource {
    const source: ProjectSource = {
      type: "s3",
      config: {
        bucket: config.bucket,
        prefix: config.prefix || "",
        region: config.region || "us-east-1"
      }
    };

    // Add auth if credentials provided
    if (config.credentials) {
      source.auth = {
        type: "token",
        credentials: config.credentials
      };
    }

    return source;
  }

  /**
   * Build GitHub source config
   */
  static github(config: {
    owner: string;
    repo: string;
    branch?: string;
    path?: string;
    token?: string;
  }): ProjectSource {
    const source: ProjectSource = {
      type: "github",
      config: {
        owner: config.owner,
        repo: config.repo,
        branch: config.branch || "main",
        path: config.path || "/"
      }
    };

    if (config.token) {
      source.auth = {
        type: "bearer",
        credentials: { token: config.token }
      };
    }

    return source;
  }

  /**
   * Build API source config
   */
  static api(config: {
    baseUrl: string;
    projectEndpoint?: string;
    headers?: Record<string, string>;
    apiKey?: string;
  }): ProjectSource {
    const source: ProjectSource = {
      type: "api",
      config: {
        baseUrl: config.baseUrl,
        projectEndpoint: config.projectEndpoint || "/projects",
        headers: config.headers
      }
    };

    if (config.apiKey) {
      source.auth = {
        type: "token",
        credentials: { apiKey: config.apiKey }
      };
    }

    return source;
  }

  /**
   * Validate source configuration
   */
  static validate(source: ProjectSource): { valid: boolean; errors: string[] } {
    const errors: string[] = [];

    switch (source.type) {
      case "indexeddb":
        if (!source.config.dbName) {
          errors.push("IndexedDB source requires dbName");
        }
        break;

      case "s3":
        if (!source.config.bucket) {
          errors.push("S3 source requires bucket");
        }
        // For validation, we don't require credentials - they can be provided at runtime
        break;

      case "github":
        if (!source.config.owner || !source.config.repo) {
          errors.push("GitHub source requires owner and repo");
        }
        break;

      case "api":
        if (!source.config.baseUrl) {
          errors.push("API source requires baseUrl");
        }
        break;

      case "memory":
        // Memory source has no required fields
        break;

      default:
        errors.push(`Unknown source type: ${source.type}`);
    }

    return {
      valid: errors.length === 0,
      errors
    };
  }

  /**
   * Sanitize source for export (remove credentials)
   */
  static sanitize(source: ProjectSource): ProjectSource {
    const sanitized = { ...source };
    
    // Remove auth completely
    delete sanitized.auth;

    // Clean specific fields based on type
    switch (source.type) {
      case "s3":
        // Keep only bucket and prefix
        sanitized.config = {
          bucket: source.config.bucket,
          prefix: source.config.prefix
        };
        break;

      case "api":
        // Remove headers that might contain auth
        const { headers, ...restConfig } = source.config;
        sanitized.config = restConfig;
        break;

      // For other types (memory, indexeddb, github), preserve config as-is
      default:
        // No special sanitization needed for other types
        break;
    }

    return sanitized;
  }
}