import { PerformanceParseOptions } from 'performance-results-parser';
import PerformanceTestResult from 'performance-results-parser/src/models/PerformanceTestResult';
import { Schedule, User } from 'rosters';
import { ParseOptions } from 'test-results-parser';
import TestResult from 'test-results-parser/src/models/TestResult';

export { TestResult };

export interface ITarget {
  name: TargetName;
  enable?: string | boolean;
  condition?: Condition;
  inputs?: SlackInputs | TeamsInputs | ChatInputs | IGitHubInputs | IGitHubOutputInputs | ICustomTargetInputs | InfluxDBTargetInputs;
  extensions?: IExtension[];
}

export interface IExtension {
  name: ExtensionName;
  enable?: string | boolean;
  condition?: Condition;
  hook?: Hook;
  order?: number;
  inputs?: ReportPortalAnalysisInputs | ReportPortalHistoryInputs | HyperlinkInputs | MentionInputs | QuickChartTestSummaryInputs | PercyAnalysisInputs | CustomExtensionInputs | MetadataInputs | CIInfoInputs | AIFailureSummaryInputs | BrowserstackInputs | FailureSignaturesInputs | ErrorClustersInputs;
}

export type ExtensionName = 'report-portal-analysis' | 'hyperlinks' | 'mentions' | 'report-portal-history' | 'quick-chart-test-summary' | 'metadata' | 'ci-info' | 'custom' | 'ai-failure-summary' | 'failure-signatures' | 'error-clusters';
export type Hook = 'start' | 'end' | 'after-summary';
export type TargetName = 'slack' | 'teams' | 'chat' | 'github' | 'github-output' | 'custom' | 'delay';
export type PublishReportType = 'test-summary' | 'test-summary-slim' | 'failure-details';

export interface ConditionFunctionContext {
  target: ITarget;
  extension?: IExtension,
  result: TestResult;
}
export type ConditionFunction = (ctx: ConditionFunctionContext) => boolean | Promise<boolean>;
export type Condition = 'pass' | 'fail' | 'passOrFail' | 'always' | 'never' | ConditionFunction;

/**
 * Extensions
 */

export interface ExtensionInputs {
  title?: string;
  title_link?: string;
  separator?: boolean;
  data?: any;
}

export interface ReportPortalAnalysisInputs extends ExtensionInputs {
  url: string;
  api_key: string;
  project: string;
  launch_id?: string;
  launch_name?: string;
}

export interface ReportPortalHistoryInputs extends ExtensionInputs {
  url: string;
  api_key: string;
  project: string;
  launch_id?: string;
  launch_name?: string;
  history_depth?: number;
  link_history_via?: string;
}

export interface QuickChartTestSummaryInputs {
  url: string;
}

export interface MentionInputs extends ExtensionInputs {
  users?: User[];
  schedule?: Schedule;
}

export interface CIInfoInputs extends ExtensionInputs {
  show_repository_non_common?: boolean;
  show_repository?: boolean;
  show_repository_branch?: boolean;
  show_build?: boolean;
  data?: Metadata[];
}

export interface AIFailureSummaryInputs extends ExtensionInputs {
  failure_summary: string;
}

export interface FailureSignaturesInputs extends ExtensionInputs {
  data?: Array<{
    id: string;
    signature: string;
    failure_type: string;
    count: number;
  }>;
}

export interface ErrorClustersInputs extends ExtensionInputs {
  data?: Array<{
    test_failure_id: string;
    failure: string;
    count: number;
  }>;
}

export interface BrowserStackAutomationBuild {
  name: string;
  hashed_id: string;
  duration: number;
  status: string;
  build_tag: string;
  public_url: string;
}

export interface BrowserStackAutomationSession {
  name: string;
  duration: number;
  os: string;
  os_version: string;
  browser_version: string;
  browser: string;
  device: string;
  status: string;
  hashed_id: string;
  reason: string;
  build_name: string;
  project_name: string;
  build_hashed_id: string;
  test_priority: string;
  logs: string;
  browserstack_status: string;
  created_at: string;
  browser_url: string;
  public_url: string;
  video_url: string;
  browser_console_logs_url: string;
  har_logs_url: string;
  selenium_logs_url: string;
  session_terminal_logs_url: string;
  build_terminal_logs_url: string;
}

export interface BrowserstackInputs extends ExtensionInputs {
  url?: string;
  username?: string;
  access_key?: string;
  automation_build_name?: string;
  automation_build?: BrowserStackAutomationBuild;
  automation_sessions?: BrowserStackAutomationSession[];
}

export interface PercyAnalysisInputs extends ExtensionInputs {
  url?: string;
  token?: string;
  retries?: number;
  build_id?: string;
  project_id?: string;
  project_name?: string;
  organization_uid?: string;
  title_link_to_build?: boolean;
}

export interface PercyAnalysisOutputs {
  build?: object;
  project?: object;
}

export interface PercyAnalysisExtension extends IExtension {
  inputs?: PercyAnalysisInputs;
  outputs?: PercyAnalysisOutputs;
}

export interface CustomExtensionFunctionContext {
  target: ITarget;
  extension: IExtension,
  result: TestResult;
  payload: any;
  root_payload: any;
}

export type CustomExtensionFunction = (ctx: CustomExtensionFunctionContext) => void | Promise<void>;

export interface CustomExtensionInputs extends ExtensionInputs {
  load: string | CustomExtensionFunction;
}

export interface CustomExtension extends IExtension {
  inputs?: CustomExtensionInputs;
  outputs?: any;
}

export interface LinkUrlFunctionContext {
  target: ITarget;
  extension: HyperlinksExtension,
  result: TestResult;
}

export type LinkUrlFunction = (ctx: LinkUrlFunctionContext) => string | Promise<string>;

export interface Link {
  text: string;
  url: string | LinkUrlFunction;
  condition?: Condition;
}

export interface HyperlinkInputs extends ExtensionInputs {
  links: Link[];
}

export interface HyperlinksExtension extends IExtension {
  inputs?: HyperlinkInputs;
}

export interface Metadata {
  label?: string;
  key?: string;
  value: string;
  type?: string;
  condition?: Condition;
}

export interface MetadataInputs extends ExtensionInputs {
  data?: Metadata[];
}

export interface MetadataExtension extends IExtension {
  inputs?: MetadataInputs;
}

/**
 * Targets
 */

export interface MetricConfig {
  name: string;
  condition: Condition;
  fields: string[];
}

export interface TargetInputs {
  url: string;
  title?: string;
  title_suffix?: string;
  title_link?: string;
  duration?: string;
  publish?: PublishReportType;
  only_failures?: boolean;
  max_suites?: number;
  metrics?: MetricConfig[];
}

export interface SlackInputs extends TargetInputs {
  message_format?: 'blocks' | 'attachments';
  token?: string;
  channels?: string[];
}

export interface TeamsInputs extends TargetInputs {
  width?: string;
}

export interface ChatInputs extends TargetInputs { }

export interface IGitHubInputs extends TargetInputs {
  token?: string;
  owner?: string;
  repo?: string;
  pull_number?: string;
}

export interface IGitHubOutputInputs {
  output_file?: string;
  key?: string;
}

export interface InfluxDBTargetInputs {
  url: string;
  version?: string;
  db: string;
  username?: string;
  password?: string;
  org?: string;
  bucket?: string;
  precision?: string;
  token?: string;
  measurement_perf_run?: string;
  measurement_perf_transaction?: string;
  measurement_test_run?: string;
  measurement_test_suite?: string;
  measurement_test_case?: string;
  tags?: object;
  fields?: object;
}

export interface CustomTargetFunctionContext {
  target: ITarget;
  result: TestResult;
}

export type CustomTargetFunction = (ctx: CustomTargetFunctionContext) => void | Promise<void>;

export interface ICustomTargetInputs {
  load: string | CustomTargetFunction;
}

export interface IDelayTargetInputs {
  seconds: number;
}

export interface IHttpTargetInputs {
  url: string;
  method: string;
  headers: object;
}

export interface CustomResultOptions {
  type: string;
  result: TestResult | PerformanceTestResult;
}

export interface PublishReport {
  api_key?: string;
  project?: string;
  run?: string;
  metadata?: Record<string, string>;
  show_failure_summary?: boolean;
  show_failure_analysis?: boolean;
  show_smart_analysis?: boolean;
  /** @deprecated Use show_failure_signatures instead. Legacy feature - only enabled when explicitly set to true. */
  show_error_clusters?: boolean;
  show_failure_signatures?: boolean;
  targets?: ITarget[];
  extensions?: IExtension[];
  results?: ParseOptions[] | PerformanceParseOptions[] | CustomResultOptions[];
}

export interface PublishConfig {
  api_key?: string;
  project?: string;
  run?: string;
  metadata?: Record<string, string>;
  targets?: ITarget[];
  extensions?: IExtension[];
  results?: ParseOptions[] | PerformanceParseOptions[] | CustomResultOptions[];
}

export interface PublishOptions {
  config: string | PublishConfig;
}

export interface CommandLineOptions {
  config?: string | PublishConfig;
  project?: string;
  run?: string;
  'api-key'?: string;
  slack?: string;
  teams?: string;
  chat?: string;
  title?: string;
  'ci-info'?: boolean;
  'chart-test-summary'?: boolean;
  junit?: string;
  testng?: string;
  cucumber?: string;
  mocha?: string;
  nunit?: string;
  xunit?: string;
  mstest?: string;
  // Manual sync command options
  path?: string;
}

export type IExtensionDefaultOptions = {
  hook: Hook
  condition: Condition
}

export type ITargetDefaultOptions = {
  condition: Condition
}

export function publish(options: PublishOptions): Promise<any>
export function defineConfig(config: PublishConfig): PublishConfig