import * as fs from 'fs';
import * as path from 'path';

const dbRoot = path.join(process.cwd(), 'db');
const configDir = path.join(dbRoot, 'config');
const configFile = path.join(configDir, 'storage-paths.json');

export interface StorageConfig {
  backupPath: string;
  codePath: string;
  documentsPath: string;
  autoBackupEnabled: boolean;
  autoBackupIntervalHours: number;
  lastBackupTime?: string;
}

// Default configuration
const DEFAULT_CONFIG: StorageConfig = {
  backupPath: path.join(path.dirname(process.cwd()), 'backups'),
  codePath: process.cwd(),
  documentsPath: path.join(path.dirname(process.cwd()), 'documents'),
  autoBackupEnabled: false,
  autoBackupIntervalHours: 3,
};

/**
 * Ensure config directory exists
 */
export function ensureConfigDir(): void {
  if (!fs.existsSync(configDir)) {
    fs.mkdirSync(configDir, { recursive: true });
  }
}

/**
 * Read storage configuration from disk
 */
export function readStorageConfig(): StorageConfig {
  ensureConfigDir();
  
  try {
    if (fs.existsSync(configFile)) {
      const content = fs.readFileSync(configFile, 'utf-8');
      const parsed = JSON.parse(content);
      let config = { ...DEFAULT_CONFIG, ...parsed };

      // Migration: Detect old overlapping paths and reset to defaults
      const overlapCheck = checkPathsOverlap(config.backupPath, config.codePath, config.documentsPath);
      if (!overlapCheck.valid) {
        // Reset to new defaults
        config = { ...DEFAULT_CONFIG };
        writeStorageConfig(config);
      }

      return config;
    }
  } catch (error) {
    // Fall back to defaults if read fails
  }
  
  return DEFAULT_CONFIG;
}

/**
 * Write storage configuration to disk
 */
export function writeStorageConfig(config: Partial<StorageConfig>): void {
  ensureConfigDir();
  const current = readStorageConfig();
  const updated = { ...current, ...config };
  
  fs.writeFileSync(configFile, JSON.stringify(updated, null, 2), 'utf-8');
}

/**
 * Validate storage path: must be absolute, writable, and not a system directory
 */
export function validateStoragePath(inputPath: string): { valid: boolean; error?: string } {
  if (!inputPath || typeof inputPath !== 'string') {
    return { valid: false, error: 'Path cannot be empty' };
  }

  const normalized = path.normalize(inputPath);
  
  // Check if path is absolute
  if (!path.isAbsolute(normalized)) {
    return { valid: false, error: 'Path must be absolute (e.g., C:\\path\\to\\dir)' };
  }

  // Prevent dangerous system paths
  const systemPaths = [
    path.normalize('C:\\Windows'),
    path.normalize('C:\\Program Files'),
    path.normalize('C:\\Users'),
  ];

  for (const sysPath of systemPaths) {
    if (normalized.startsWith(sysPath)) {
      return { valid: false, error: 'Cannot use system directories' };
    }
  }

  // Check if parent directory exists
  const parentDir = path.dirname(normalized);
  if (!fs.existsSync(parentDir)) {
    return { valid: false, error: `Parent directory does not exist: ${parentDir}` };
  }

  // Check if writable (try to create the directory if it doesn't exist)
  try {
    if (!fs.existsSync(normalized)) {
      fs.mkdirSync(normalized, { recursive: true });
    } else {
      // Check if we can write to existing directory
      const testFile = path.join(normalized, '.write-test');
      fs.writeFileSync(testFile, 'test', 'utf-8');
      fs.unlinkSync(testFile);
    }
  } catch (error: any) {
    return { valid: false, error: `Directory is not writable: ${error?.message || 'Unknown error'}` };
  }

  return { valid: true };
}

/**
 * Check if paths overlap (different paths must not be nested within each other)
 * Allows db and document folders under code path (standard web app structure)
 */
export function checkPathsOverlap(
  backupPath: string,
  codePath: string,
  documentsPath: string
): { valid: boolean; error?: string } {
  const normalizedBackup = path.normalize(backupPath);
  const normalizedCode = path.normalize(codePath);
  const normalizedDocs = path.normalize(documentsPath);
  const normalizedDbPath = path.normalize(path.join(codePath, 'db'));

  // Exception: backup path CAN be at codePath/db/backups (backward compatibility)
  const isBackupInDb = normalizedBackup === path.normalize(path.join(normalizedDbPath, 'backups'));

  // Exception: documents path CAN be anywhere under code directory (standard web app structure)
  const isDocsUnderCode = normalizedDocs.startsWith(normalizedCode + path.sep) || normalizedDocs === normalizedCode;

  // Check Backup vs Code (but allow db/backups under code)
  if (!isBackupInDb) {
    if (
      normalizedBackup === normalizedCode ||
      normalizedBackup.startsWith(normalizedCode + path.sep) ||
      normalizedCode.startsWith(normalizedBackup + path.sep)
    ) {
      return {
        valid: false,
        error: `Paths cannot overlap: Backup and Code`,
      };
    }
  }

  // Check Backup vs Documents
  if (
    normalizedBackup === normalizedDocs ||
    normalizedBackup.startsWith(normalizedDocs + path.sep) ||
    normalizedDocs.startsWith(normalizedBackup + path.sep)
  ) {
    return {
      valid: false,
      error: `Paths cannot overlap: Backup and Documents`,
    };
  }

  // Check Code vs Documents (but allow documents under code)
  if (!isDocsUnderCode) {
    if (
      normalizedCode === normalizedDocs ||
      normalizedCode.startsWith(normalizedDocs + path.sep) ||
      normalizedDocs.startsWith(normalizedCode + path.sep)
    ) {
      return {
        valid: false,
        error: `Paths cannot overlap: Code and Documents`,
      };
    }
  }

  return { valid: true };
}

/**
 * Update storage configuration with validation
 */
export function updateStorageConfig(updates: Partial<StorageConfig>): {
  success: boolean;
  error?: string;
  config?: StorageConfig;
} {
  try {
    // Validate each path
    if (updates.backupPath) {
      const validation = validateStoragePath(updates.backupPath);
      if (!validation.valid) return { success: false, error: `Backup path: ${validation.error}` };
    }

    if (updates.codePath) {
      const validation = validateStoragePath(updates.codePath);
      if (!validation.valid) return { success: false, error: `Code path: ${validation.error}` };
    }

    if (updates.documentsPath) {
      const validation = validateStoragePath(updates.documentsPath);
      if (!validation.valid) return { success: false, error: `Documents path: ${validation.error}` };
    }

    // Check for overlaps
    const current = readStorageConfig();
    const mergedConfig = { ...current, ...updates };
    const overlapCheck = checkPathsOverlap(
      mergedConfig.backupPath,
      mergedConfig.codePath,
      mergedConfig.documentsPath
    );

    if (!overlapCheck.valid) {
      return { success: false, error: overlapCheck.error };
    }

    // Write config
    writeStorageConfig(updates);
    const updated = readStorageConfig();
    return { success: true, config: updated };
  } catch (error: any) {
    return { success: false, error: error?.message || 'Failed to update config' };
  }
}
