import * as Config from "effect/Config";
import * as ConfigProvider from "effect/ConfigProvider";
import * as Option from "effect/Option";

const trimNonEmptyOption = (value: string): Option.Option<string> => {
  const trimmed = value.trim();
  return trimmed.length > 0 ? Option.some(trimmed) : Option.none();
};

const trimmedString = (name: string) =>
  Config.string(name).pipe(Config.option, Config.map(Option.flatMap(trimNonEmptyOption)));

const optionalBoolean = (name: string) =>
  Config.boolean(name).pipe(Config.option, Config.map(Option.getOrElse(() => false)));

const commaSeparatedStrings = (name: string) =>
  trimmedString(name).pipe(
    Config.map(
      Option.match({
        onNone: () => [],
        onSome: (value) =>
          value
            .split(",")
            .map((entry) => entry.trim())
            .filter((entry) => entry.length > 0),
      }),
    ),
  );

const compactEnv = (env: Readonly<Record<string, string | undefined>>): Record<string, string> =>
  Object.fromEntries(
    Object.entries(env).filter((entry): entry is [string, string] => entry[1] !== undefined),
  );

export const DesktopConfig = Config.all({
  appDataDirectory: trimmedString("APPDATA"),
  xdgConfigHome: trimmedString("XDG_CONFIG_HOME"),
  belweaveHome: trimmedString("BELWEAVE_HOME"),
  devServerUrl: Config.url("VITE_DEV_SERVER_URL").pipe(Config.option),
  devRemoteBelweaveServerEntryPath: trimmedString("BELWEAVE_DEV_REMOTE_BELWEAVE_SERVER_ENTRY_PATH"),
  configuredBackendPort: Config.port("BELWEAVE_PORT").pipe(Config.option),
  commitHashOverride: trimmedString("BELWEAVE_COMMIT_HASH"),
  desktopLanHostOverride: trimmedString("BELWEAVE_DESKTOP_LAN_HOST"),
  desktopHttpsEndpointUrls: commaSeparatedStrings("BELWEAVE_DESKTOP_HTTPS_ENDPOINTS"),
  otlpTracesUrl: trimmedString("BELWEAVE_OTLP_TRACES_URL"),
  otlpExportIntervalMs: Config.int("BELWEAVE_OTLP_EXPORT_INTERVAL_MS").pipe(
    Config.withDefault(10_000),
  ),
  appImagePath: trimmedString("APPIMAGE"),
  disableAutoUpdate: optionalBoolean("BELWEAVE_DISABLE_AUTO_UPDATE"),
  mockUpdates: optionalBoolean("BELWEAVE_DESKTOP_MOCK_UPDATES"),
  mockUpdateServerPort: Config.port("BELWEAVE_DESKTOP_MOCK_UPDATE_SERVER_PORT").pipe(
    Config.withDefault(3000),
  ),
});

export const layerTest = (env: Readonly<Record<string, string | undefined>>) =>
  ConfigProvider.layer(ConfigProvider.fromEnv({ env: compactEnv(env) }));
