import { computed, ref, watch } from 'vue'
import { useMutation, useQuery } from '@tanstack/vue-query'
import { isKbxProblem, type KbxImportMapping, type KbxImportSession, type KbxProblem } from '@kbx/contracts'
import { orderImportApi } from './orderImportApi'
import { kbxTelemetry } from '../../../telemetry/kbxTelemetryClient'
import { orderImportScreen } from './order-import.definition'

export function useOrderExcelImport() {
  const sessionId = ref<string | null>(null)
  const localSession = ref<KbxImportSession | null>(null)
  let importStartedAt:number|undefined
  let terminalRecorded=false
  const problem=ref<KbxProblem|null>(null)
  let retryAction:(()=>Promise<unknown>)|null=null

  const sessionQuery = useQuery({
    queryKey: computed(() => ['excel-import', sessionId.value]),
    queryFn: () => orderImportApi.getSession(sessionId.value!),
    enabled: computed(() => !!sessionId.value),
    refetchInterval: query => {
      const status = query.state.data?.status
      return status === 'validating' || status === 'committing' ? 1500 : false
    },
  })

  const session = computed(() => sessionQuery.data.value ?? localSession.value)

  const uploadMutation = useMutation({
    mutationFn: orderImportApi.createSession,
    onMutate() { importStartedAt=performance.now(); terminalRecorded=false; kbxTelemetry.track('excel.import.start',{screenId:orderImportScreen.id,screenVersion:orderImportScreen.version,attributes:{importType:'oms-order',rowCountBucket:'unknown'}}) },
    onSuccess(value) { sessionId.value = value.id; localSession.value = value },
    onError() { kbxTelemetry.track('excel.import.failed',{screenId:orderImportScreen.id,screenVersion:orderImportScreen.version,durationMs:Math.round(performance.now()-(importStartedAt??performance.now())),attributes:{importType:'oms-order',reasonCode:'UPLOAD_FAILED',rowCountBucket:'unknown'}}); terminalRecorded=true },
  })

  const mappingMutation = useMutation({
    mutationFn: ({ id, mappings }: { id: string; mappings: KbxImportMapping[] }) => orderImportApi.saveMapping(id, mappings),
    onSuccess(value) { localSession.value = value },
  })

  const savedMappingMutation = useMutation({
    mutationFn: ({ id, name, mappings }: { id: string; name: string; mappings: KbxImportMapping[] }) => orderImportApi.saveNamedMapping(id, name, mappings),
  })

  const validationMutation = useMutation({
    mutationFn: orderImportApi.validate,
    onSuccess(value) { localSession.value = value; void sessionQuery.refetch() },
  })

  const commitMutation = useMutation({
    mutationFn: orderImportApi.commit,
    onSuccess(value) { localSession.value = value; void sessionQuery.refetch() },
    onError() { kbxTelemetry.track('excel.import.failed',{screenId:orderImportScreen.id,screenVersion:orderImportScreen.version,durationMs:Math.round(performance.now()-(importStartedAt??performance.now())),attributes:{importType:'oms-order',reasonCode:'COMMIT_REQUEST_FAILED',rowCountBucket:'unknown'}}); terminalRecorded=true },
  })


  async function runProblemAware<T>(action:()=>Promise<T>):Promise<T|null>{
    problem.value=null; retryAction=null
    try{return await action()}catch(error){if(isKbxProblem(error)){problem.value=error;retryAction=()=>runProblemAware(action);return null}throw error}
  }
  async function retryProblem(){const retry=retryAction;problem.value=null;retryAction=null;if(retry)await retry()}
  function dismissProblem(){problem.value=null;retryAction=null}

  watch(session, value => {
    if(!value || terminalRecorded || importStartedAt==null) return
    const bucket=value.totalRows<1000?'0-999':value.totalRows<10000?'1k-9k':value.totalRows<100000?'10k-99k':'100k+'
    const durationMs=Math.round(performance.now()-importStartedAt)
    if(value.status==='completed'||value.status==='partially-completed'){kbxTelemetry.track('excel.import.completed',{screenId:orderImportScreen.id,screenVersion:orderImportScreen.version,durationMs,attributes:{importType:'oms-order',result:value.status,rowCountBucket:bucket}});terminalRecorded=true}
    if(value.status==='failed'){kbxTelemetry.track('excel.import.failed',{screenId:orderImportScreen.id,screenVersion:orderImportScreen.version,durationMs,attributes:{importType:'oms-order',reasonCode:'JOB_FAILED',rowCountBucket:bucket}});terminalRecorded=true}
  })

  return {
    session,
    sessionId,
    problem,
    busy: computed(() => uploadMutation.isPending.value || mappingMutation.isPending.value || validationMutation.isPending.value || commitMutation.isPending.value),
    upload: (file: File) => runProblemAware(()=>uploadMutation.mutateAsync(file)),
    saveMapping: (mappings: KbxImportMapping[]) => sessionId.value ? runProblemAware(()=>mappingMutation.mutateAsync({ id: sessionId.value!, mappings })) : Promise.resolve(null),
    saveNamedMapping: (name: string, mappings: KbxImportMapping[]) => sessionId.value ? runProblemAware(()=>savedMappingMutation.mutateAsync({ id: sessionId.value!, name, mappings })) : Promise.resolve(null),
    validate: () => sessionId.value ? runProblemAware(()=>validationMutation.mutateAsync(sessionId.value!)) : Promise.resolve(null),
    commit: () => sessionId.value ? runProblemAware(()=>commitMutation.mutateAsync(sessionId.value!)) : Promise.resolve(null),
    downloadTemplate: () => runProblemAware(()=>orderImportApi.downloadTemplate()),
    downloadErrors: () => sessionId.value ? runProblemAware(()=>orderImportApi.downloadErrors(sessionId.value!)) : Promise.resolve(null),
    reset: () => { sessionId.value = null; localSession.value = null; problem.value=null; retryAction=null },
    retryProblem,
    dismissProblem,
  }
}
