// =============================================================================
// TOM Generator Reducer
// Action types and state reducer for the TOM Generator Wizard
// =============================================================================

import {
  TOMGeneratorState,
  TOMGeneratorStepId,
  CompanyProfile,
  DataProfile,
  ArchitectureProfile,
  SecurityProfile,
  RiskProfile,
  EvidenceDocument,
  DerivedTOM,
  GapAnalysisResult,
  ExportRecord,
  WizardStep,
  createInitialTOMGeneratorState,
  calculateProtectionLevel,
  isDSFARequired,
  hasSpecialCategories,
} from './types'

// =============================================================================
// ACTION TYPES
// =============================================================================

export type TOMGeneratorAction =
  | { type: 'INITIALIZE'; payload: { tenantId: string; state?: TOMGeneratorState } }
  | { type: 'RESET'; payload: { tenantId: string } }
  | { type: 'SET_CURRENT_STEP'; payload: TOMGeneratorStepId }
  | { type: 'SET_COMPANY_PROFILE'; payload: CompanyProfile }
  | { type: 'UPDATE_COMPANY_PROFILE'; payload: Partial<CompanyProfile> }
  | { type: 'SET_DATA_PROFILE'; payload: DataProfile }
  | { type: 'UPDATE_DATA_PROFILE'; payload: Partial<DataProfile> }
  | { type: 'SET_ARCHITECTURE_PROFILE'; payload: ArchitectureProfile }
  | { type: 'UPDATE_ARCHITECTURE_PROFILE'; payload: Partial<ArchitectureProfile> }
  | { type: 'SET_SECURITY_PROFILE'; payload: SecurityProfile }
  | { type: 'UPDATE_SECURITY_PROFILE'; payload: Partial<SecurityProfile> }
  | { type: 'SET_RISK_PROFILE'; payload: RiskProfile }
  | { type: 'UPDATE_RISK_PROFILE'; payload: Partial<RiskProfile> }
  | { type: 'COMPLETE_STEP'; payload: { stepId: TOMGeneratorStepId; data: unknown } }
  | { type: 'UNCOMPLETE_STEP'; payload: TOMGeneratorStepId }
  | { type: 'ADD_EVIDENCE'; payload: EvidenceDocument }
  | { type: 'UPDATE_EVIDENCE'; payload: { id: string; data: Partial<EvidenceDocument> } }
  | { type: 'DELETE_EVIDENCE'; payload: string }
  | { type: 'SET_DERIVED_TOMS'; payload: DerivedTOM[] }
  | { type: 'UPDATE_DERIVED_TOM'; payload: { id: string; data: Partial<DerivedTOM> } }
  | { type: 'SET_GAP_ANALYSIS'; payload: GapAnalysisResult }
  | { type: 'ADD_EXPORT'; payload: ExportRecord }
  | { type: 'BULK_UPDATE_TOMS'; payload: { updates: Array<{ id: string; data: Partial<DerivedTOM> }> } }
  | { type: 'LOAD_STATE'; payload: TOMGeneratorState }

// =============================================================================
// REDUCER
// =============================================================================

export function tomGeneratorReducer(
  state: TOMGeneratorState,
  action: TOMGeneratorAction
): TOMGeneratorState {
  const updateState = (updates: Partial<TOMGeneratorState>): TOMGeneratorState => ({
    ...state,
    ...updates,
    updatedAt: new Date(),
  })

  switch (action.type) {
    case 'INITIALIZE': {
      if (action.payload.state) {
        return action.payload.state
      }
      return createInitialTOMGeneratorState(action.payload.tenantId)
    }

    case 'RESET': {
      return createInitialTOMGeneratorState(action.payload.tenantId)
    }

    case 'SET_CURRENT_STEP': {
      return updateState({ currentStep: action.payload })
    }

    case 'SET_COMPANY_PROFILE': {
      return updateState({ companyProfile: action.payload })
    }

    case 'UPDATE_COMPANY_PROFILE': {
      if (!state.companyProfile) return state
      return updateState({
        companyProfile: { ...state.companyProfile, ...action.payload },
      })
    }

    case 'SET_DATA_PROFILE': {
      const profile: DataProfile = {
        ...action.payload,
        hasSpecialCategories: hasSpecialCategories(action.payload.categories),
      }
      return updateState({ dataProfile: profile })
    }

    case 'UPDATE_DATA_PROFILE': {
      if (!state.dataProfile) return state
      const updatedProfile = { ...state.dataProfile, ...action.payload }
      if (action.payload.categories) {
        updatedProfile.hasSpecialCategories = hasSpecialCategories(
          action.payload.categories
        )
      }
      return updateState({ dataProfile: updatedProfile })
    }

    case 'SET_ARCHITECTURE_PROFILE': {
      return updateState({ architectureProfile: action.payload })
    }

    case 'UPDATE_ARCHITECTURE_PROFILE': {
      if (!state.architectureProfile) return state
      return updateState({
        architectureProfile: { ...state.architectureProfile, ...action.payload },
      })
    }

    case 'SET_SECURITY_PROFILE': {
      return updateState({ securityProfile: action.payload })
    }

    case 'UPDATE_SECURITY_PROFILE': {
      if (!state.securityProfile) return state
      return updateState({
        securityProfile: { ...state.securityProfile, ...action.payload },
      })
    }

    case 'SET_RISK_PROFILE': {
      const profile: RiskProfile = {
        ...action.payload,
        protectionLevel: calculateProtectionLevel(action.payload.ciaAssessment),
        dsfaRequired: isDSFARequired(state.dataProfile, action.payload),
      }
      return updateState({ riskProfile: profile })
    }

    case 'UPDATE_RISK_PROFILE': {
      if (!state.riskProfile) return state
      const updatedProfile = { ...state.riskProfile, ...action.payload }
      if (action.payload.ciaAssessment) {
        updatedProfile.protectionLevel = calculateProtectionLevel(
          action.payload.ciaAssessment
        )
      }
      updatedProfile.dsfaRequired = isDSFARequired(state.dataProfile, updatedProfile)
      return updateState({ riskProfile: updatedProfile })
    }

    case 'COMPLETE_STEP': {
      const updatedSteps = state.steps.map((step) =>
        step.id === action.payload.stepId
          ? {
              ...step,
              completed: true,
              data: action.payload.data,
              validatedAt: new Date(),
            }
          : step
      )
      return updateState({ steps: updatedSteps })
    }

    case 'UNCOMPLETE_STEP': {
      const updatedSteps = state.steps.map((step) =>
        step.id === action.payload
          ? { ...step, completed: false, validatedAt: null }
          : step
      )
      return updateState({ steps: updatedSteps })
    }

    case 'ADD_EVIDENCE': {
      return updateState({
        documents: [...state.documents, action.payload],
      })
    }

    case 'UPDATE_EVIDENCE': {
      const updatedDocuments = state.documents.map((doc) =>
        doc.id === action.payload.id ? { ...doc, ...action.payload.data } : doc
      )
      return updateState({ documents: updatedDocuments })
    }

    case 'DELETE_EVIDENCE': {
      return updateState({
        documents: state.documents.filter((doc) => doc.id !== action.payload),
      })
    }

    case 'SET_DERIVED_TOMS': {
      return updateState({ derivedTOMs: action.payload })
    }

    case 'UPDATE_DERIVED_TOM': {
      const updatedTOMs = state.derivedTOMs.map((tom) =>
        tom.id === action.payload.id ? { ...tom, ...action.payload.data } : tom
      )
      return updateState({ derivedTOMs: updatedTOMs })
    }

    case 'SET_GAP_ANALYSIS': {
      return updateState({ gapAnalysis: action.payload })
    }

    case 'ADD_EXPORT': {
      return updateState({
        exports: [...state.exports, action.payload],
      })
    }

    case 'BULK_UPDATE_TOMS': {
      let updatedTOMs = [...state.derivedTOMs]
      for (const update of action.payload.updates) {
        updatedTOMs = updatedTOMs.map((tom) =>
          tom.id === update.id ? { ...tom, ...update.data } : tom
        )
      }
      return updateState({ derivedTOMs: updatedTOMs })
    }

    case 'LOAD_STATE': {
      return action.payload
    }

    default:
      return state
  }
}
