'use client'

/**
 * useCallback factories extracted from ComplianceProvider.
 *
 * Each function creates and returns a memoised callback so provider.tsx
 * stays under 300 LOC.
 */

import { useCallback, RefObject } from 'react'
import type {
  SDKState,
  CheckpointStatus,
  UseCaseAssessment,
  Risk,
  Control,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient, StateSyncManager } from '@breakpilot/compliance-sdk-core'
import { SDK_STORAGE_KEY } from './provider-context'

// =============================================================================
// CHECKPOINT CALLBACKS
// =============================================================================

export function useValidateCheckpoint(
  state: SDKState,
  enableBackendSync: boolean,
  client: ComplianceClient,
  dispatch: React.Dispatch<{ type: string; payload?: unknown }>
) {
  return useCallback(
    async (checkpointId: string): Promise<CheckpointStatus> => {
      if (enableBackendSync) {
        try {
          const result = await client.validateCheckpoint(checkpointId, state)
          const status: CheckpointStatus = {
            checkpointId: result.checkpointId,
            passed: result.passed,
            validatedAt: new Date(result.validatedAt),
            validatedBy: result.validatedBy,
            errors: result.errors,
            warnings: result.warnings,
          }
          dispatch({ type: 'SET_CHECKPOINT_STATUS', payload: { id: checkpointId, status } })
          return status
        } catch {
          // Fall through to local validation
        }
      }

      const status: CheckpointStatus = {
        checkpointId,
        passed: true,
        validatedAt: new Date(),
        validatedBy: 'SYSTEM',
        errors: [],
        warnings: [],
      }
      dispatch({ type: 'SET_CHECKPOINT_STATUS', payload: { id: checkpointId, status } })
      return status
    },
    [state, enableBackendSync, client, dispatch]
  )
}

export function useOverrideCheckpoint(
  state: SDKState,
  dispatch: React.Dispatch<{ type: string; payload?: unknown }>
) {
  return useCallback(
    async (checkpointId: string, reason: string): Promise<void> => {
      const existingStatus = state.checkpoints[checkpointId]
      const overriddenStatus: CheckpointStatus = {
        ...existingStatus,
        checkpointId,
        passed: true,
        overrideReason: reason,
        overriddenBy: state.userId,
        overriddenAt: new Date(),
        errors: [],
        warnings: existingStatus?.warnings || [],
      }
      dispatch({ type: 'SET_CHECKPOINT_STATUS', payload: { id: checkpointId, status: overriddenStatus } })
    },
    [state.checkpoints, state.userId, dispatch]
  )
}

export function useGetCheckpointStatus(state: SDKState) {
  return useCallback(
    (checkpointId: string): CheckpointStatus | undefined => state.checkpoints[checkpointId],
    [state.checkpoints]
  )
}

// =============================================================================
// STATE UPDATE CALLBACKS
// =============================================================================

export function useUpdateUseCase(dispatch: React.Dispatch<{ type: string; payload?: unknown }>) {
  return useCallback(
    (id: string, data: Partial<UseCaseAssessment>) => {
      dispatch({ type: 'UPDATE_USE_CASE', payload: { id, data } })
    },
    [dispatch]
  )
}

export function useAddRisk(dispatch: React.Dispatch<{ type: string; payload?: unknown }>) {
  return useCallback(
    (risk: Risk) => {
      dispatch({ type: 'ADD_RISK', payload: risk })
    },
    [dispatch]
  )
}

export function useUpdateControl(dispatch: React.Dispatch<{ type: string; payload?: unknown }>) {
  return useCallback(
    (id: string, data: Partial<Control>) => {
      dispatch({ type: 'UPDATE_CONTROL', payload: { id, data } })
    },
    [dispatch]
  )
}

// =============================================================================
// PERSISTENCE CALLBACKS
// =============================================================================

export function useSaveState(
  state: SDKState,
  tenantId: string,
  enableBackendSync: boolean,
  syncManagerRef: RefObject<StateSyncManager | null>,
  setError: (e: Error) => void
) {
  return useCallback(async (): Promise<void> => {
    try {
      if (typeof window !== 'undefined') {
        localStorage.setItem(`${SDK_STORAGE_KEY}-${tenantId}`, JSON.stringify(state))
      }

      if (enableBackendSync && syncManagerRef.current) {
        await syncManagerRef.current.forceSync(state)
      }
    } catch (err) {
      setError(err as Error)
      throw err
    }
  }, [state, tenantId, enableBackendSync, syncManagerRef, setError])
}

export function useLoadState(
  tenantId: string,
  enableBackendSync: boolean,
  syncManagerRef: RefObject<StateSyncManager | null>,
  setIsLoading: (v: boolean) => void,
  dispatch: React.Dispatch<{ type: string; payload?: unknown }>,
  setError: (e: Error) => void
) {
  return useCallback(async (): Promise<void> => {
    setIsLoading(true)
    try {
      if (enableBackendSync && syncManagerRef.current) {
        const serverState = await syncManagerRef.current.loadFromServer()
        if (serverState) {
          dispatch({ type: 'SET_STATE', payload: serverState })
          return
        }
      }

      if (typeof window !== 'undefined') {
        const stored = localStorage.getItem(`${SDK_STORAGE_KEY}-${tenantId}`)
        if (stored) {
          dispatch({ type: 'SET_STATE', payload: JSON.parse(stored) })
        }
      }
    } catch (err) {
      setError(err as Error)
      throw err
    } finally {
      setIsLoading(false)
    }
  }, [tenantId, enableBackendSync, syncManagerRef, setIsLoading, dispatch, setError])
}

export function useResetState(
  tenantId: string,
  dispatch: React.Dispatch<{ type: string; payload?: unknown }>
) {
  return useCallback(() => {
    dispatch({ type: 'RESET_STATE' })
    if (typeof window !== 'undefined') {
      localStorage.removeItem(`${SDK_STORAGE_KEY}-${tenantId}`)
    }
  }, [tenantId, dispatch])
}

// =============================================================================
// SYNC & EXPORT CALLBACKS
// =============================================================================

export function useForceSyncToServer(
  state: SDKState,
  enableBackendSync: boolean,
  syncManagerRef: RefObject<StateSyncManager | null>
) {
  return useCallback(async (): Promise<void> => {
    if (enableBackendSync && syncManagerRef.current) {
      await syncManagerRef.current.forceSync(state)
    }
  }, [state, enableBackendSync, syncManagerRef])
}

export function useExportState(state: SDKState, client: ComplianceClient) {
  return useCallback(
    async (format: 'json' | 'pdf' | 'zip'): Promise<Blob> => {
      if (format === 'json') {
        return new Blob([JSON.stringify(state, null, 2)], { type: 'application/json' })
      }
      return client.exportState(format)
    },
    [state, client]
  )
}
