import { FileDiffContent } from "@codeflash-ai/code-suggester/build/src/types.js"

export interface StagingStorageContext {
  userId: string
  traceId: string
  baseBranch: string
  owner?: string
  repo?: string
  diffContents?: Map<string, FileDiffContent>
  prCommentFields: Record<string, unknown>
  metadata: Record<string, unknown>
  originalLineProfiler?: string
  optimizedLineProfiler?: string
}

export interface StagingStorageResult {
  success: boolean
  storageType: "plain_text" | "git_branch"
  branchName?: string
  error?: string
}

export abstract class StagingStorageStrategy {
  abstract getStorageType(): "plain_text" | "git_branch"
  abstract save(context: StagingStorageContext): Promise<StagingStorageResult>
}

export function parseSpeedupValue(value: unknown, suffix: "x" | "%"): number | null {
  if (value === undefined || value === null || value === "") {
    return null
  }

  let stringValue = String(value).trim().toLowerCase()

  if (stringValue.endsWith(suffix)) {
    stringValue = stringValue.slice(0, -1)
  }

  const parsed = parseFloat(stringValue.replace(",", ""))
  return isNaN(parsed) ? null : parsed
}

export type BuildMergedMetadataOptions =
  | { storageType: "git_branch"; stagingBranchName: string }
  | { storageType: "plain_text"; diffContents?: Map<string, unknown> }

export interface LineProfilerData {
  originalLineProfiler?: string
  optimizedLineProfiler?: string
}

export function buildMergedMetadata(
  existingMetadata: unknown,
  requestMetadata: Record<string, unknown>,
  options: BuildMergedMetadataOptions,
  lineProfilerData?: LineProfilerData,
) {
  const existing = (
    existingMetadata && typeof existingMetadata === "object" ? existingMetadata : {}
  ) as Record<string, unknown>

  const preservedFields = {
    codeflash_version: existing.codeflash_version ?? undefined,
    num_optimizations: existing.num_optimizations ?? undefined,
    experiment_metadata: existing.experiment_metadata ?? undefined,
  }

  const { prCommentFields, traceId, diffContents: _, ...restMetadata } = requestMetadata

  const sanitizedPrFields = prCommentFields
    ? { ...(prCommentFields as Record<string, unknown>) }
    : {}
  delete sanitizedPrFields.function_name
  delete sanitizedPrFields.file_path
  delete sanitizedPrFields.speedup_x
  delete sanitizedPrFields.speedup_pct

  const baseMetadata = {
    ...preservedFields,
    ...restMetadata,
    prCommentFields: {
      ...((existing.prCommentFields as Record<string, unknown>) ?? {}),
      ...sanitizedPrFields,
    },
    // Include line profiler data if provided
    ...(lineProfilerData?.originalLineProfiler && {
      originalLineProfiler: lineProfilerData.originalLineProfiler,
    }),
    ...(lineProfilerData?.optimizedLineProfiler && {
      optimizedLineProfiler: lineProfilerData.optimizedLineProfiler,
    }),
  }

  if (options.storageType === "git_branch") {
    return {
      ...baseMetadata,
      staging_storage_type: "git_branch" as const,
      staging_branch_name: options.stagingBranchName,
    }
  } else {
    const diffContentsObj = options.diffContents
      ? Object.fromEntries(options.diffContents)
      : requestMetadata.diffContents

    return {
      ...baseMetadata,
      staging_storage_type: "plain_text" as const,
      diffContents: diffContentsObj ?? undefined,
    }
  }
}
