import { BusinessRecord } from './classes.businessrecord.js';
import { HandelsRegister } from './classes.handelsregister.js';
import { JsonlDataProcessor, type SeedEntryType } from './classes.jsonldata.js';
import * as plugins from './plugins.js';

export interface IOpenDataConfig {
  downloadDir: string;
  germanBusinessDataDir: string;
  nogitDir: string;
}

export class OpenData {
  public db!: plugins.smartdata.SmartdataDb;
  private localSmartDb?: plugins.smartdb.LocalSmartDb;
  private config: IOpenDataConfig;
  private started = false;

  public jsonLDataProcessor!: JsonlDataProcessor<SeedEntryType>;
  public handelsregister!: HandelsRegister;

  public CBusinessRecord = plugins.smartdata.setDefaultManagerForDoc(this, BusinessRecord);

  constructor(configArg: IOpenDataConfig) {
    if (!configArg) {
      throw new Error('@fin.cx/opendata: Configuration is required. You must provide downloadDir, germanBusinessDataDir, and nogitDir paths.');
    }
    if (!configArg.downloadDir || !configArg.germanBusinessDataDir || !configArg.nogitDir) {
      throw new Error('@fin.cx/opendata: All directory paths are required (downloadDir, germanBusinessDataDir, nogitDir).');
    }
    this.config = configArg;
  }

  public async start() {
    if (this.started) {
      return;
    }

    // Ensure configured directories exist
    await plugins.smartfs.directory(this.config.nogitDir).create();
    await plugins.smartfs.directory(this.config.downloadDir).create();
    await plugins.smartfs.directory(this.config.germanBusinessDataDir).create();

    this.localSmartDb = new plugins.smartdb.LocalSmartDb({
      folderPath: plugins.path.join(this.config.nogitDir, 'opendata-smartdb'),
    });

    const connectionInfo = await this.localSmartDb.start();
    this.db = new plugins.smartdata.SmartdataDb({
      mongoDbUrl: connectionInfo.connectionUri,
      mongoDbName: 'opendata',
    });

    try {
      await this.db.init();
      await this.db.mongoDb.collection('_opendata_bootstrap').insertOne({
        createdAt: new Date(),
      });
      await this.db.mongoDb.collection('_opendata_bootstrap').deleteMany({});

      this.jsonLDataProcessor = new JsonlDataProcessor(
        this.config.germanBusinessDataDir,
        async (entryArg) => {
          const businessRecord = new this.CBusinessRecord();
          businessRecord.id = await this.CBusinessRecord.getNewId();
          businessRecord.data.name = entryArg.name;
          businessRecord.data.germanParsedRegistration = {
            court: entryArg.all_attributes.registered_office,
            number: entryArg.all_attributes._registerNummer,
            type: entryArg.all_attributes._registerArt as 'HRA' | 'HRB',
          };
          await businessRecord.save();
        }
      );

      this.handelsregister = new HandelsRegister(this, this.config.downloadDir);
      await this.handelsregister.start();
      this.started = true;
    } catch (error) {
      if (this.handelsregister) {
        await this.handelsregister.stop().catch(() => {});
      }
      await this.db.close().catch(() => {});
      await this.localSmartDb.stop().catch(() => {});
      this.localSmartDb = undefined;
      throw error;
    }
  }

  public async buildInitialDb() {
    await this.jsonLDataProcessor.processDataFromUrl();
  }

  public async slowValidateDb() {

  }

  public async validateSearchByName() {

  }

  public async searchDbByBusinessNameAndPostalCode(businessNameArg: string, postalCodeArg: string) {

  }



  public async stop() {
    if (!this.started) {
      return;
    }

    if (this.handelsregister) {
      await this.handelsregister.stop();
    }
    await this.db.close();
    await this.localSmartDb?.stop();
    this.localSmartDb = undefined;
    this.started = false;
  }
}
