import { defHttp } from '#/api/request';

export type SourceStatus = 'DRAFT' | 'PUBLISHED';

export interface SourcePropertyVersion {
  dataType: string;
  definitionJson?: string;
  displayName: string;
  editVersion: number;
  id: string;
  propertyCode: string;
  publishedAt?: string;
  publishedBy?: string;
  revision: number;
  status: SourceStatus;
  validationSampleId?: string;
}

export interface SourcePropertyReference {
  dataType: string;
  displayName: string;
  enabled: boolean;
  propertyCode: string;
  revision: number;
}

export interface SourceDatasetVersion {
  code: string;
  definitionJson?: string;
  displayName: string;
  editVersion: number;
  id: string;
  publishedAt?: string;
  publishedBy?: string;
  revision: number;
  status: SourceStatus;
  validationSampleId?: string;
}

export interface SourcePropertyDraft {
  dataType: string;
  definition: {
    datasetCode: string;
    datasetRevision: number;
    fieldId: string;
  };
  displayName: string;
  propertyCode: string;
}

export interface SourcePublication {
  expectedEditVersion: number;
  sampleId: string;
}

export interface SourceBusinessObject {
  displayName: string;
  id: string;
  rootAnchor: boolean;
}

export interface SourceCandidateField {
  dataType: string;
  displayName: string;
  displayNameAvailable?: boolean;
  id: string;
  nameOptions?: null | Record<string, string>;
  nameRuleConflict: boolean;
}

export interface SourceDatasetSelection {
  enumSource?: {
    labelFieldId: string;
    objectId: string;
    valueFieldId: string;
  };
  fieldId: string;
  format: 'DATE_ONLY' | 'ISO_DATE' | 'PLAIN_DECIMAL' | 'RAW';
  step: number;
  valueMode: 'DISPLAY_NAME' | 'RAW';
}

export interface SourceDatasetDraft {
  code: string;
  conditions: { field: string; operator: 'EQ' | 'IN' | 'IS_NOT_NULL' | 'IS_NULL'; values: string[] }[];
  displayName: string;
  fields: Record<string, SourceDatasetSelection>;
  relations: { fromFieldId: string; fromStep: number; objectId: string; targetFieldId: string }[];
  rootObjectId: string;
  scopeMode: 'ALL' | 'ANY';
}

export interface SourceDatasetValidation {
  previewValidated: boolean;
  structureValid: boolean;
}

export interface SourceDatasetPreview {
  dataType: string;
  outcomeCode: string;
  propertyCode: string;
  value: unknown;
}

export interface SourceDataItem {
  dataType: string;
  displayName: string;
  editVersion: number;
  enabled: boolean;
  id: string;
  outputKey: string;
  outputName: string;
  propertyCode: string;
  publishedAt?: string;
  publishedBy?: string;
  returnContent: string;
  revision: number;
  scope: string;
  sourcePath: string;
  sourcePathId: string;
  status: SourceStatus;
}

export interface SourcePathOutput {
  dataType: string;
  displayName: string;
  key: string;
  path: string;
  returnContent: string;
}

export interface SourcePath {
  code: string;
  displayName: string;
  editVersion: number;
  id: string;
  outputs: SourcePathOutput[];
  path: string;
  publishedAt?: string;
  publishedBy?: string;
  revision: number;
  scope: string;
  status: SourceStatus;
}

export interface SourcePathDraft {
  code: string;
  displayName: string;
  fromFieldId?: string;
  outputFieldId: string;
  outputKey: string;
  rootObjectId: string;
  sampleId: string;
  targetFieldId?: string;
  targetObjectId: string;
}

export interface SourceDataItemDraft {
  displayName: string;
  expectedEditVersion?: number;
  outputKey: string;
  propertyCode: string;
  sourcePathId: string;
}

export interface SourcePreviewSample {
  batchNo?: string;
  id: string;
  sampleName?: string;
  testName?: string;
  testNo?: string;
}

interface ApiResult<T> {
  code: number;
  data: T;
  msg?: string;
}

const SOURCE_PREFIX = '/api/lims/eln/sources';

export function getSourceDataItems() {
  return defHttp.get<ApiResult<SourceDataItem[]>>({ url: `${SOURCE_PREFIX}/dataItems` });
}

export function getSourcePaths() {
  return defHttp.get<ApiResult<SourcePath[]>>({ url: `${SOURCE_PREFIX}/sourcePaths` });
}

export function createSourcePath(data: SourcePathDraft) {
  return defHttp.post<ApiResult<SourcePath>>({ data, url: `${SOURCE_PREFIX}/sourcePaths` });
}

export function createSourceDataItem(data: SourceDataItemDraft) {
  return defHttp.post<ApiResult<SourceDataItem>>({ data, url: `${SOURCE_PREFIX}/dataItems` });
}

export function saveSourceDataItem(id: string, data: SourceDataItemDraft) {
  return defHttp.put<ApiResult<SourceDataItem>>({ data, url: `${SOURCE_PREFIX}/dataItems/${id}` });
}

export function previewSourceDataItem(id: string, sampleId: string) {
  return defHttp.post<ApiResult<{ value: unknown }>>({ data: { sampleId }, url: `${SOURCE_PREFIX}/dataItems/${id}/preview` });
}

export function publishSourceDataItem(id: string, data: SourcePublication) {
  return defHttp.post<ApiResult<SourceDataItem>>({ data, url: `${SOURCE_PREFIX}/dataItems/${id}/publish` });
}

export function getSourcePreviewSamples(keyword = '') {
  return defHttp.get<ApiResult<SourcePreviewSample[]>>({ data: { keyword }, url: `${SOURCE_PREFIX}/previewSamples` });
}

export function getSourceProperties() {
  return defHttp.get<ApiResult<SourcePropertyVersion[]>>({ url: `${SOURCE_PREFIX}/properties` });
}

export function getSourceCatalog() {
  return defHttp.get<ApiResult<SourcePropertyVersion[]>>({ url: `${SOURCE_PREFIX}/catalog` });
}

export function getSourceReference(propertyCode: string, revision: number) {
  return defHttp.get<ApiResult<SourcePropertyReference>>({
    url: `${SOURCE_PREFIX}/references/${encodeURIComponent(propertyCode)}/${revision}`,
  });
}

export function getSourceDatasets() {
  return defHttp.get<ApiResult<SourceDatasetVersion[]>>({ url: `${SOURCE_PREFIX}/datasets` });
}

export function createSourceProperty(data: SourcePropertyDraft) {
  return defHttp.post<ApiResult<SourcePropertyVersion>>({ data, url: `${SOURCE_PREFIX}/properties` });
}

export function createSourcePropertyVersion(id: string, data: SourcePropertyDraft) {
  return defHttp.post<ApiResult<SourcePropertyVersion>>({ data, url: `${SOURCE_PREFIX}/properties/${id}/versions` });
}

export function updateSourceProperty(id: string, data: { draft: SourcePropertyDraft; expectedEditVersion: number }) {
  return defHttp.put<ApiResult<SourcePropertyVersion>>({
    data,
    url: `${SOURCE_PREFIX}/properties/${id}`,
  });
}

export function publishSourceProperty(id: string, data: SourcePublication) {
  return defHttp.post<ApiResult<SourcePropertyVersion>>({ data, url: `${SOURCE_PREFIX}/properties/${id}/publish` });
}

export function setSourcePropertyEnabled(propertyCode: string, enabled: boolean) {
  return defHttp.put<ApiResult<boolean>>({
    data: { enabled },
    url: `${SOURCE_PREFIX}/properties/${encodeURIComponent(propertyCode)}/enabled`,
  });
}

export function getSourceObjects() {
  return defHttp.get<ApiResult<SourceBusinessObject[]>>({ url: `${SOURCE_PREFIX}/objects` });
}

export function getSourceObjectFields(objectId: string) {
  return defHttp.get<ApiResult<SourceCandidateField[]>>({ url: `${SOURCE_PREFIX}/objects/${objectId}/fields` });
}

export function getSourceEnumObjects() {
  return defHttp.get<ApiResult<SourceBusinessObject[]>>({ url: `${SOURCE_PREFIX}/enumObjects` });
}

export function getSourceEnumOptions(data: { labelFieldId: string; objectId: string; valueFieldId: string }) {
  return defHttp.post<ApiResult<Record<string, string>>>({ data, url: `${SOURCE_PREFIX}/enumOptions` });
}

export function createSourceDataset(data: SourceDatasetDraft) {
  return defHttp.post<ApiResult<SourceDatasetVersion>>({ data, url: `${SOURCE_PREFIX}/datasets` });
}

export function createSourceDatasetVersion(id: string, data: SourceDatasetDraft) {
  return defHttp.post<ApiResult<SourceDatasetVersion>>({ data, url: `${SOURCE_PREFIX}/datasets/${id}/versions` });
}

export function updateSourceDataset(id: string, data: { draft: SourceDatasetDraft; expectedEditVersion: number }) {
  return defHttp.put<ApiResult<SourceDatasetVersion>>({ data, url: `${SOURCE_PREFIX}/datasets/${id}` });
}

export function validateSourceDataset(id: string) {
  return defHttp.post<ApiResult<SourceDatasetValidation>>({ url: `${SOURCE_PREFIX}/datasets/${id}/validate` });
}

export function previewSourceDataset(id: string, sampleId: string) {
  return defHttp.post<ApiResult<SourceDatasetPreview[]>>({ data: { sampleId }, url: `${SOURCE_PREFIX}/datasets/${id}/preview` });
}

export function publishSourceDataset(id: string, data: SourcePublication) {
  return defHttp.post<ApiResult<SourceDatasetVersion>>({ data, url: `${SOURCE_PREFIX}/datasets/${id}/publish` });
}
