import { ClientApplication } from '../client/types.js';
import { I18nApplication } from '../languages/types.js';
import { SpringBootApplication } from '../server/types.js';
import { DeterministicOptionWithDerivedProperties, OptionWithDerivedProperties } from './application-options.js';

export type BaseApplication = {
  jhipsterVersion: string;
  baseName: string;
  capitalizedBaseName: string;
  dasherizedBaseName: string;
  humanizedBaseName: string;
  camelizedBaseName: string;
  hipster: string;
  lowercaseBaseName: string;
  upperFirstCamelCaseBaseName: string;
  documentationArchiveUrl: string;

  projectVersion: string;
  projectDescription: string;

  jhiPrefix: string;
  entitySuffix: string;
  dtoSuffix: string;

  skipCommitHook: boolean;
  skipJhipsterDependencies: boolean;
  fakerSeed?: string;

  nodeVersion: string;
  nodePackageManager: string;
  nodeDependencies: Record<string, string>;

  skipClient?: boolean;
  skipServer?: boolean;

  /** Customize templates sourceFile and destinationFile */
  customizeTemplatePaths: Array<
    (file: {
      namespace: string;
      sourceFile: string;
      resolvedSourceFile: string;
      destinationFile: string;
      templatesRoots: string[];
    }) => undefined | { sourceFile: string; resolvedSourceFile: string; destinationFile: string; templatesRoots: string[] }
  >;

  // add by begcode start
  ormTool?: string;
  userIdType?: string;
  useLombok?: boolean;
  useMultiTenant?: boolean;
  smsProvider?: string;
  ossProvider?: string;
  useCommonTable?: boolean;
  useBigScreen?: boolean;
  frontOrBack?: string;
  workflow?: string;
  onlyLowcode?: boolean;
  // add by begcode end
} & I18nApplication;

/* ApplicationType Start */
type MicroservicesArchitectureApplication = {
  microfrontend: boolean;
  gatewayServerPort: number;
};

type GatewayApplication = MicroservicesArchitectureApplication & {
  microfrontends: string[];
};

type ApplicationType = DeterministicOptionWithDerivedProperties<
  'applicationType',
  ['monolith', 'gateway', 'microservice', 'gatewaywithall', 'commonmodule'],
  [Record<string, never>, GatewayApplication, MicroservicesArchitectureApplication]
>;

/* ApplicationType End */

/* AuthenticationType Start */
type UserManagement =
  | {
      skipUserManagement: true;
      generateUserManagement: false;
      generateBuiltInUserEntity?: false;
      generateBuiltInAuthorityEntity: false;
    }
  | {
      skipUserManagement: false;
      generateBuiltInUserEntity?: boolean;
      generateUserManagement: true;
      user: any;
      userManagement: any;
      generateBuiltInAuthorityEntity: boolean;
      authority: any;
    };

type JwtApplication = UserManagement & {
  jwtSecretKey: string;
};

type Oauth2Application = {
  jwtSecretKey: string;
  generateBuiltInUserEntity?: boolean;
  user: any;
  generateBuiltInAuthorityEntity: false;
  generateUserManagement: false;
};

type SessionApplication = UserManagement & {
  rememberMeKey: string;
};

type AuthenticationType = DeterministicOptionWithDerivedProperties<
  'authenticationType',
  ['jwt', 'oauth2', 'session'],
  [JwtApplication, Oauth2Application, SessionApplication]
>;

/* AuthenticationType End */

type QuirksApplication = {
  cypressBootstrapEntities?: boolean;
};

export type CommonClientServerApplication = BaseApplication &
  QuirksApplication &
  AuthenticationType &
  SpringBootApplication &
  ClientApplication &
  ApplicationType & {
    clientRootDir: string;
    clientSrcDir: string;
    clientTestDir?: string;
    clientDistDir?: string;
    clientDir?: string;
    devServerPort: number;
    devServerPorts: number[];
    pages: string[];

    serverPort: number;
    backendType?: string;
    backendTypeJavaAny?: boolean;
    backendTypeSpringBoot?: boolean;
    temporaryDir?: string;

    hipsterName?: string;
    hipsterProductName?: string;
    hipsterHomePageProductName?: string;
    hipsterStackOverflowProductName?: string;
    hipsterBugTrackerProductName?: string;
    hipsterChatProductName?: string;
    hipsterTwitterUsername?: string;
    hipsterDocumentationLink?: string;
    hipsterTwitterLink?: string;
    hipsterProjectLink?: string;
    hipsterStackoverflowLink?: string;
    hipsterBugTrackerLink?: string;
    hipsterChatLink?: string;

    dockerServicesDir?: string;
    dockerServices?: string[];
    prettierExtensions?: string;

    skipUserManagement?: boolean;
    syncUserWithIdp?: boolean;
    generateUserManagement?: boolean;
    builtInServices?: string[];
  };

type ServiceDiscoveryApplication = OptionWithDerivedProperties<'serviceDiscoveryType', ['no', 'eureka', 'consul']>;

type MonitoringApplication = OptionWithDerivedProperties<'monitoring', ['no', 'elk', 'prometheus']>;

export type PlatformApplication = ServiceDiscoveryApplication & MonitoringApplication;
