/**
 * Blockchain Manager
 * Singleton to manage the global plant blockchain instance
 *
 * Supports two modes:
 * 1. File-based (legacy): Uses JSON file storage
 * 2. Database-backed: Uses PostgreSQL via Prisma (recommended)
 */

import { PlantChain } from './PlantChain';
import { PlantChainDB, getPlantChain as getDBPlantChain } from './PlantChainDB';
import fs from 'fs';
import path from 'path';

const BLOCKCHAIN_FILE = path.join(process.cwd(), 'data', 'plantchain.json');

// Flag to determine storage mode
const USE_DATABASE = process.env.DATABASE_URL ? true : false;

class BlockchainManager {
  private static instance: BlockchainManager;
  private plantChain: PlantChain;
  private autoSaveInterval: NodeJS.Timeout | null = null;

  private constructor() {
    this.plantChain = this.loadBlockchain();
    this.startAutoSave();
  }

  public static getInstance(): BlockchainManager {
    if (!BlockchainManager.instance) {
      BlockchainManager.instance = new BlockchainManager();
    }
    return BlockchainManager.instance;
  }

  public getChain(): PlantChain {
    return this.plantChain;
  }

  /**
   * Load blockchain from file or create new one
   */
  private loadBlockchain(): PlantChain {
    try {
      // Ensure data directory exists
      const dataDir = path.join(process.cwd(), 'data');
      if (!fs.existsSync(dataDir)) {
        fs.mkdirSync(dataDir, { recursive: true });
      }

      if (fs.existsSync(BLOCKCHAIN_FILE)) {
        const data = fs.readFileSync(BLOCKCHAIN_FILE, 'utf-8');
        const chainData = JSON.parse(data);
        console.log('✓ Loaded existing blockchain with', chainData.chain.length, 'blocks');
        return PlantChain.fromJSON(chainData);
      }
    } catch (error) {
      console.error('Error loading blockchain:', error);
    }

    console.log('✓ Created new blockchain');
    return new PlantChain(4); // difficulty of 4
  }

  /**
   * Save blockchain to file
   */
  public saveBlockchain(): void {
    try {
      const dataDir = path.join(process.cwd(), 'data');
      if (!fs.existsSync(dataDir)) {
        fs.mkdirSync(dataDir, { recursive: true });
      }

      const data = JSON.stringify(this.plantChain.toJSON(), null, 2);
      fs.writeFileSync(BLOCKCHAIN_FILE, data, 'utf-8');
      console.log('✓ Blockchain saved');
    } catch (error) {
      console.error('Error saving blockchain:', error);
    }
  }

  /**
   * Auto-save blockchain every 5 minutes
   */
  private startAutoSave(): void {
    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
    }

    this.autoSaveInterval = setInterval(() => {
      this.saveBlockchain();
    }, 5 * 60 * 1000); // 5 minutes
  }

  /**
   * Stop auto-save
   */
  public stopAutoSave(): void {
    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
      this.autoSaveInterval = null;
    }
  }
}

export function getBlockchain(): PlantChain {
  return BlockchainManager.getInstance().getChain();
}

export function saveBlockchain(): void {
  BlockchainManager.getInstance().saveBlockchain();
}

/**
 * Get the database-backed blockchain instance
 * Use this for production applications with PostgreSQL
 */
export async function getBlockchainDB(): Promise<PlantChainDB> {
  return getDBPlantChain();
}

/**
 * Check if using database storage
 */
export function isUsingDatabase(): boolean {
  return USE_DATABASE;
}

// Export the DB class for type usage
export { PlantChainDB };
