import Logger from 'src/application/logging/logger';
import {
  StatsigExperiment as ApiOrgConfigExperiment,
  StatsigFeatureGate as ApiOrgConfigFeatureGate,
  OrganizationSettings as ApiOrgConfigOrganizationSettings,
  Organization as ApiOrganization,
  OrganizationStatusEnum,
} from '@spiffy-ai/commerce-api-client';
import { ApiOrganizationConfig, isApiOrganizationConfig } from './isApiOrganizationConfig';

interface ApiOrgConfigResults {
  configs: ApiOrganizationConfig[];
  experiments: ApiOrgConfigExperiment[];
  gates: ApiOrgConfigFeatureGate[];
  org: ApiOrgConfigOrganizationSettings;
}

const logger = new Logger('isApiOrgConfigResults');

const isApiOrgConfigExperiment = (data: unknown): data is ApiOrgConfigExperiment => {
  if (data == null || typeof data !== 'object') {
    logger.logDebug('isApiOrgConfigExperiment: data is not an object', undefined, {
      data,
    });
    return false;
  }

  if ('group' in data && typeof data.group !== 'string' && data.group !== undefined) {
    logger.logDebug('isApiOrgConfigExperiment: group is not a string or undefined', undefined, {
      data,
    });
    return false;
  }

  if (
    'group_name' in data &&
    typeof data.group_name !== 'string' &&
    data.group_name !== undefined
  ) {
    logger.logDebug('isApiOrgConfigExperiment: group_name is not a string', undefined, {
      data,
    });
    return false;
  }

  if ('name' in data && typeof data.name !== 'string' && data.name !== undefined) {
    logger.logDebug('isApiOrgConfigExperiment: name is not a string', undefined, {
      data,
    });
    return false;
  }

  if ('rule_id' in data && typeof data.rule_id !== 'string' && data.rule_id !== undefined) {
    logger.logDebug('isApiOrgConfigExperiment: rule_id is not a string', undefined, {
      data,
    });
    return false;
  }

  if ('value' in data && typeof data.value !== 'object' && data.value !== undefined) {
    logger.logDebug('isApiOrgConfigExperiment: value is not an object', undefined, {
      data,
    });
    return false;
  }

  return true;
};

const isApiOrgConfigFeatureGate = (data: unknown): data is ApiOrgConfigFeatureGate => {
  if (data == null || typeof data !== 'object') {
    logger.logDebug('isApiOrgConfigFeatureGate: data is not an object', undefined, {
      data,
    });
    return false;
  }

  if ('name' in data && typeof data.name !== 'string' && data.name !== undefined) {
    logger.logDebug('isApiOrgConfigFeatureGate: name is not a string', undefined, {
      data,
    });
    return false;
  }

  if ('rule_id' in data && typeof data.rule_id !== 'string' && data.rule_id !== undefined) {
    logger.logDebug('isApiOrgConfigFeatureGate: rule_id is not a string', undefined, {
      data,
    });
    return false;
  }

  if ('value' in data && typeof data.value !== 'boolean' && data.value !== undefined) {
    logger.logDebug('isApiOrgConfigFeatureGate: value is not a boolean', undefined, {
      data,
    });
    return false;
  }

  return true;
};

const isApiOrganization = (data: unknown): data is ApiOrganization => {
  if (data == null || typeof data !== 'object') {
    logger.logDebug('isApiOrganization: data is not an object', undefined, {
      data,
    });
    return false;
  }

  if (!('id' in data) || typeof data.id !== 'string') {
    logger.logDebug('isApiOrganization: id is not a string', undefined, {
      data,
    });
    return false;
  }

  if (!('display_name' in data) || typeof data.display_name !== 'string') {
    logger.logDebug('isApiOrganization: display_name is not a string', undefined, {
      data,
    });
    return false;
  }

  if (!('domain' in data) || typeof data.domain !== 'string') {
    logger.logDebug('isApiOrganization: domain is not a string', undefined, {
      data,
    });
    return false;
  }

  if (!('short_name' in data) || typeof data.short_name !== 'string') {
    logger.logDebug('isApiOrganization: short_name is not a string', undefined, {
      data,
    });
    return false;
  }

  if (
    !('status' in data) ||
    !Object.values(OrganizationStatusEnum).includes(data.status as OrganizationStatusEnum)
  ) {
    logger.logDebug(
      'isApiOrganization: status is not a valid OrganizationStatusEnum value',
      undefined,
      {
        data,
      },
    );
    return false;
  }

  if (
    'created_at' in data &&
    !(data.created_at instanceof Date) &&
    typeof data.created_at !== 'string' &&
    data.created_at !== undefined
  ) {
    logger.logDebug('isApiOrganization: created_at is not a Date', undefined, {
      data,
    });
    return false;
  }

  if (
    'updated_at' in data &&
    !(data.updated_at instanceof Date) &&
    typeof data.updated_at !== 'string' &&
    data.updated_at !== undefined
  ) {
    logger.logDebug('isApiOrganization: updated_at is not a Date', undefined, {
      data,
    });
    return false;
  }

  return true;
};

const isApiOrgConfigOrganizationSettings = (
  data: unknown,
): data is ApiOrgConfigOrganizationSettings => {
  if (data == null || typeof data !== 'object') {
    logger.logDebug('isApiOrgConfigOrganizationSettings: data is not an object', undefined, {
      data,
    });
    return false;
  }

  if (!('org' in data) || !isApiOrganization(data.org)) {
    logger.logDebug('isApiOrgConfigOrganizationSettings: org is not an object', undefined, {
      data,
    });
    return false;
  }

  // skip validation for 'settings' for now

  return true;
};

/**
 *
 * @param data
 * @returns
 */
export const isApiOrgConfigResults = (data: unknown): data is Required<ApiOrgConfigResults> => {
  if (data == null || typeof data !== 'object') {
    logger.logDebug('isApiOrgConfigResults: data is not an object', undefined, {
      data,
    });
    return false;
  }

  if (
    !('configs' in data) ||
    !Array.isArray(data.configs) ||
    !data.configs.every(config => isApiOrganizationConfig(config))
  ) {
    logger.logDebug('isApiOrgConfigResults: configs is not an array', undefined, {
      data,
    });
    return false;
  }

  if (
    'experiments' in data &&
    data.experiments !== undefined &&
    (!Array.isArray(data.experiments) ||
      !data.experiments.every(exp => isApiOrgConfigExperiment(exp)))
  ) {
    logger.logDebug(
      'isApiOrgConfigResults: experiments is not an array or contains invalid items',
      undefined,
      {
        data,
      },
    );
    return false;
  }

  if (
    !('gates' in data) ||
    !Array.isArray(data.gates) ||
    !data.gates.every(gate => isApiOrgConfigFeatureGate(gate))
  ) {
    logger.logDebug(
      'isApiOrgConfigResults: gates is not an array or contains invalid items',
      undefined,
      {
        data,
      },
    );
    return false;
  }

  if (!('org' in data) || !isApiOrgConfigOrganizationSettings(data.org)) {
    logger.logDebug(
      'isApiOrgConfigResults: org is not an object or has invalid fields',
      undefined,
      {
        data,
      },
    );

    return false;
  }

  return true;
};
