import { DatasourceConfiguration } from '../datasource/index.js';
import { buildCommonMetadata, ResourceMetadata } from '../metadata/index.js';
import { IntegrationKind } from '../plugin/index.js';
import { ActionTypeEnum, CreatorDto } from '../rbac/index.js';

export class IntegrationConfigurationDto {
  id: string;
  // Created date could be used for sorting
  created: Date;
  integrationId: string;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  configuration: Record<string, any>; // DatasourceConfiguration;
  isDefault: boolean;

  // The profiles associated with this configuration.
  // This should be undefined or empty when isDefault is true.
  profileIds?: string[];
  profileNames?: string[];

  constructor({
    id,
    created,
    integrationId,
    configuration,
    isDefault,
    profileIds,
    profileNames
  }: {
    id: string;
    created: Date;
    integrationId: string;
    configuration: DatasourceConfiguration;
    isDefault: boolean;
    profileIds?: string[];
    profileNames?: string[];
  }) {
    this.id = id;
    this.created = created;
    this.integrationId = integrationId;
    this.configuration = configuration;
    this.isDefault = isDefault;
    this.profileIds = profileIds;
    this.profileNames = profileNames;
  }
}

// this is needed due to the migration from ts -> proto objects
// in this case, the configuration is less strict than the original class
export class IntegrationConfigurationDtoProtobuf {
  id: string;
  // Created date could be used for sorting
  created: Date;
  integrationId: string;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  configuration: Record<string, any>;
  isDefault: boolean;

  // The profiles associated with this configuration.
  // This should be undefined or empty when isDefault is true.
  profileIds?: string[];

  constructor({
    id,
    created,
    integrationId,
    configuration,
    isDefault,
    profileIds
  }: {
    id: string;
    created: Date;
    integrationId: string;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    configuration: Record<string, any>;
    isDefault: boolean;
    profileIds?: string[];
  }) {
    this.id = id;
    this.created = created;
    this.integrationId = integrationId;
    this.configuration = configuration;
    this.isDefault = isDefault;
    this.profileIds = profileIds;
  }
}

class IntegrationBaseDto {
  id: string;
  name: string;
  pluginId: string;
  organizationId: string;
  applicationId?: string | null;
  isUserConfigured: boolean;
  demoIntegrationId?: string;
  managedBy?: string | null;
  // Mirrors the non-nullable `user_editable` integration column (default true). Required here so
  // consumers (e.g. the edit UI) never have to treat `undefined` as a third state; subclass
  // constructors default an absent value to true.
  userEditable: boolean;
}

export class SupersetIntegrationDto extends IntegrationBaseDto {
  kind: IntegrationKind;
  created?: Date;
  updated?: Date;
  configurations: IntegrationConfigurationDto[];
  slug?: string;
  ownerEmail?: string;
  readOnly: boolean;
  editable: boolean;
  metadata: ResourceMetadata;
  permissions?: ActionTypeEnum[];
  creator?: CreatorDto;
  enabledForV2?: boolean;

  constructor({
    id,
    created,
    updated,
    deactivated,
    name,
    pluginId,
    kind,
    organizationId,
    configurations,
    demoIntegrationId,
    isUserConfigured,
    ownerEmail,
    slug,
    readOnly,
    editable,
    permissions,
    creator,
    enabledForV2,
    applicationId,
    managedBy,
    userEditable
  }: {
    id: string;
    created: Date;
    updated: Date;
    deactivated: Date | null;
    name: string;
    pluginId: string;
    kind: IntegrationKind;
    organizationId: string;
    configurations: IntegrationConfigurationDto[];
    demoIntegrationId?: string;
    isUserConfigured: boolean;
    ownerEmail?: string;
    slug?: string;
    readOnly: boolean;
    editable: boolean;
    permissions?: ActionTypeEnum[];
    creator?: CreatorDto;
    enabledForV2?: boolean;
    applicationId?: string | null;
    managedBy?: string | null;
    userEditable?: boolean;
  }) {
    super();
    this.id = id;
    this.created = created;
    this.updated = updated;
    this.name = name;
    this.pluginId = pluginId;
    this.kind = kind;
    this.organizationId = organizationId;
    this.applicationId = applicationId;
    this.configurations = configurations;
    this.demoIntegrationId = demoIntegrationId;
    this.isUserConfigured = isUserConfigured;
    this.managedBy = managedBy;
    this.userEditable = userEditable ?? true;
    this.ownerEmail = ownerEmail;
    this.slug = slug;
    this.readOnly = readOnly;
    this.editable = editable;
    this.metadata = buildCommonMetadata({
      id: id,
      organization: organizationId,
      type: 'integration',
      timestamp: {
        created: created,
        updated: updated,
        deactivated: deactivated
      }
    });
    this.permissions = permissions;
    this.creator = creator;
    this.enabledForV2 = enabledForV2;
  }
}

export class IntegrationDto extends IntegrationBaseDto {
  kind: IntegrationKind;
  // Dates could be used for sorting
  created: Date;
  updated: Date;
  configurations: IntegrationConfigurationDto[];
  slug?: string;
  ownerEmail?: string;
  creator?: CreatorDto;
  enabledForV2?: boolean;

  constructor({
    id,
    created,
    updated,
    name,
    pluginId,
    organizationId,
    configurations,
    demoIntegrationId,
    isUserConfigured,
    ownerEmail,
    creator,
    kind,
    slug,
    enabledForV2,
    applicationId,
    managedBy,
    userEditable
  }: {
    id: string;
    created: Date;
    updated: Date;
    name: string;
    pluginId: string;
    organizationId: string;
    configurations: IntegrationConfigurationDto[];
    demoIntegrationId?: string;
    isUserConfigured: boolean;
    ownerEmail?: string;
    creator?: CreatorDto;
    kind: IntegrationKind;
    slug?: string;
    enabledForV2?: boolean;
    applicationId?: string | null;
    managedBy?: string | null;
    userEditable?: boolean;
  }) {
    super();
    this.id = id;
    this.created = created;
    this.updated = updated;
    this.name = name;
    this.pluginId = pluginId;
    this.organizationId = organizationId;
    this.applicationId = applicationId;
    this.demoIntegrationId = demoIntegrationId;
    this.configurations = configurations;
    this.isUserConfigured = isUserConfigured;
    this.managedBy = managedBy;
    this.userEditable = userEditable ?? true;
    this.ownerEmail = ownerEmail;
    this.creator = creator;
    this.kind = kind;
    this.slug = slug;
    this.enabledForV2 = enabledForV2;
  }
}
