import { readFileSync } from 'fs';
import { resolve } from 'path';
import * as cf from '@pulumi/cloudflare';
import * as pulumi from '@pulumi/pulumi';
import { S3 } from '../services/s3';

export class CloudflareCDN {
  constructor(
    private config: {
      envName: string;
      zoneId: string;
      cdnDnsRecord: string;
      sentryDsn: string | pulumi.Output<string>;
      release: string;
      s3: S3;
      s3Mirror: S3;
    },
  ) {}

  deploy() {
    const kvStorage = new cf.WorkersKvNamespace('hive-ha-storage', {
      title: `hive-ha-cdn-${this.config.envName}`,
    });

    const script = new cf.WorkerScript('hive-ha-worker', {
      content: readFileSync(
        // eslint-disable-next-line no-process-env
        process.env.CDN_WORKER_ARTIFACT_PATH ||
          resolve(__dirname, '../../packages/services/cdn-worker/dist/index.worker.mjs'),
        'utf-8',
      ),
      name: `hive-storage-cdn-${this.config.envName}`,
      module: true,
      kvNamespaceBindings: [
        {
          // HIVE_DATA is in use in cdn-script.js as well, its the name of the global variable
          name: 'HIVE_DATA',
          namespaceId: kvStorage.id,
        },
      ],
      analyticsEngineBindings: [
        {
          name: 'USAGE_ANALYTICS',
          dataset: `hive_ha_cdn_usage_${this.config.envName}`,
        },
        {
          name: 'ERROR_ANALYTICS',
          dataset: `hive_ha_cdn_error_${this.config.envName}`,
        },
        {
          name: 'KEY_VALIDATION_ANALYTICS',
          dataset: `hive_ha_cdn_key_validation_${this.config.envName}`,
        },
        {
          name: 'R2_ANALYTICS',
          dataset: `hive_ha_cdn_r2_${this.config.envName}`,
        },
        {
          name: 'S3_ANALYTICS',
          dataset: `hive_ha_cdn_s3_${this.config.envName}`,
        },
        {
          name: 'RESPONSE_ANALYTICS',
          dataset: `hive_ha_cdn_response_${this.config.envName}`,
        },
      ],
      secretTextBindings: [
        {
          name: 'SENTRY_DSN',
          text: this.config.sentryDsn,
        },
        {
          name: 'SENTRY_ENVIRONMENT',
          text: this.config.envName,
        },
        {
          name: 'SENTRY_RELEASE',
          text: this.config.release,
        },
        {
          name: 'S3_ENDPOINT',
          text: this.config.s3.secret.raw.endpoint,
        },
        {
          name: 'S3_ACCESS_KEY_ID',
          text: this.config.s3.secret.raw.accessKeyId,
        },
        {
          name: 'S3_SECRET_ACCESS_KEY',
          text: this.config.s3.secret.raw.secretAccessKey,
        },
        {
          name: 'S3_BUCKET_NAME',
          text: this.config.s3.secret.raw.bucket,
        },
        {
          name: 'S3_MIRROR_ENDPOINT',
          text: this.config.s3Mirror.secret.raw.endpoint,
        },
        {
          name: 'S3_MIRROR_ACCESS_KEY_ID',
          text: this.config.s3Mirror.secret.raw.accessKeyId,
        },
        {
          name: 'S3_MIRROR_SECRET_ACCESS_KEY',
          text: this.config.s3Mirror.secret.raw.secretAccessKey,
        },
        {
          name: 'S3_MIRROR_BUCKET_NAME',
          text: this.config.s3Mirror.secret.raw.bucket,
        },
      ],
    });

    const workerBase = this.config.cdnDnsRecord;
    const workerUrl = `https://${workerBase}`;

    new cf.WorkerRoute('cf-hive-worker', {
      scriptName: script.name,
      pattern: `${workerBase}/*`,
      zoneId: this.config.zoneId,
    });

    return {
      workerBaseUrl: workerUrl,
      cfStorageNamespaceId: kvStorage.id,
    };
  }
}

export class CloudflareBroker {
  constructor(
    private config: {
      envName: string;
      zoneId: string;
      cdnDnsRecord: string;
      secretSignature: pulumi.Output<string>;
      sentryDsn: string | pulumi.Output<string>;
      release: string;
      loki: null | {
        endpoint: string;
        username: string;
        password: pulumi.Output<string>;
      };
    },
  ) {}

  deploy() {
    const secretTextBindings = [
      {
        name: 'SIGNATURE',
        text: this.config.secretSignature,
      },
      {
        name: 'SENTRY_DSN',
        text: this.config.sentryDsn,
      },
      {
        name: 'SENTRY_ENVIRONMENT',
        text: this.config.envName,
      },
      {
        name: 'SENTRY_RELEASE',
        text: this.config.release,
      },
    ];

    if (this.config.loki) {
      secretTextBindings.push(
        {
          name: 'LOKI_PASSWORD',
          text: this.config.loki.password,
        },
        {
          name: 'LOKI_USERNAME',
          text: this.config.loki.username,
        },
        {
          name: 'LOKI_ENDPOINT',
          text: this.config.loki.endpoint,
        },
      );
    }

    const script = new cf.WorkerScript('hive-broker-worker', {
      content: readFileSync(
        // eslint-disable-next-line no-process-env
        process.env.BROKER_WORKER_ARTIFACT_PATH ||
          resolve(__dirname, '../../packages/services/broker-worker/dist/index.worker.mjs'),
        'utf-8',
      ),
      module: true,
      name: `hive-broker-${this.config.envName}`,
      secretTextBindings,
    });

    const workerBase = this.config.cdnDnsRecord;
    const workerUrl = `https://${workerBase}`;

    new cf.WorkerRoute('cf-hive-broker-worker', {
      scriptName: script.name,
      pattern: `${workerBase}/*`,
      zoneId: this.config.zoneId,
    });

    return {
      secretSignature: this.config.secretSignature,
      workerBaseUrl: workerUrl,
    };
  }
}
