import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
import { STUDENT_REGISTRATION, STUDENT_REGISTRATION_ORDER } from '@/enums'

const STORAGE_KEY = 'student-registration'

const emptyState = () => ({
  isProfileCompleted: false,
  personal: {
    avatar: null,
    avatarId: '',
    name: '',
    birthday: '',
    nationalCode: '',
    maritalStatus: '',
    gender: '',
    phoneNumber: '',
    provinceId: null,
    cityId: null,
    address: '',
    postalCode: '',
    virtualPhoneNumber: '',
    seminaryCode: '',
    seminaryServiceCenterCode: '',
    childrenCount: '',
  },
  educational: {
    educationStatus: '',
    seminaryLevel: '',
    universityLevel: '',
    universityName: '',
    fieldOfStudy: '',
    activitySummary: '',
  },
  professional: {
    propagationExperienceYears: 0,
    propagationMethodDescription: '',
    specializedTopics: '',
    propagationPlatforms: [],
  },
  skill1: {
    responseToLowSatisfaction: '',
    responseToLowSatisfactionDescription: '',
  },
  skill2: {
    responseToSessionCancellation: '',
    responseToSessionCancellationDescription: '',
  },
  skill3: {
    responseToAudienceConflict: '',
    responseToAudienceConflictDescription: '',
  },
  skill4: {
    responseToCompetingPropagator: '',
    responseToCompetingPropagatorDescription: '',
  },
  skill5: {
    responseToUnqualifiedAdvisors: '',
    relevantCertificates: '',
    hijabApproach: '',
  },
  skill6: {
    faithProductionAudio: null,
    faithProductionId: '',
  },
  skill7: {
    leaderMessageVideo: null,
    leaderMessageId: '',
  },
  currentStep: STUDENT_REGISTRATION.PERSONAL_INFORMATION,
  completedSteps: [],
  registrationMedia: {},
})

// Each field is owned by exactly one section. Used to route GET /me/register-data
// values back into the matching slice on hydration.
const SECTION_FIELDS = {
  personal: [
    'avatar',
    'avatarId',
    'name',
    'birthday',
    'nationalCode',
    'maritalStatus',
    'gender',
    'phoneNumber',
    'provinceId',
    'cityId',
    'address',
    'postalCode',
    'virtualPhoneNumber',
    'seminaryCode',
    'seminaryServiceCenterCode',
    'childrenCount',
  ],
  educational: [
    'educationStatus',
    'seminaryLevel',
    'universityLevel',
    'universityName',
    'fieldOfStudy',
    'activitySummary',
  ],
  professional: [
    'propagationExperienceYears',
    'propagationMethodDescription',
    'specializedTopics',
    'propagationPlatforms',
  ],
  skill1: ['responseToLowSatisfaction', 'responseToLowSatisfactionDescription'],
  skill2: ['responseToSessionCancellation', 'responseToSessionCancellationDescription'],
  skill3: ['responseToAudienceConflict', 'responseToAudienceConflictDescription'],
  skill4: ['responseToCompetingPropagator', 'responseToCompetingPropagatorDescription'],
  skill5: ['responseToUnqualifiedAdvisors', 'relevantCertificates', 'hijabApproach'],
  skill6: ['faithProductionAudio', 'faithProductionId'],
  skill7: ['leaderMessageVideo', 'leaderMessageId'],
}

const FIELD_TO_SECTION = Object.entries(SECTION_FIELDS).reduce((acc, [section, fields]) => {
  fields.forEach((field) => {
    acc[field] = section
  })
  return acc
}, {})

// Register-data travels as a flat `{ field: value }` object. Legacy payloads
// were a `[{ key, value }]` list — tolerate both when reading.
export const toRegisterDataObject = (input) => {
  if (Array.isArray(input)) {
    return input.reduce((acc, item) => {
      if (item && typeof item === 'object' && 'key' in item) acc[item.key] = item.value
      return acc
    }, {})
  }
  return input && typeof input === 'object' ? input : {}
}

const readPersisted = () => {
  try {
    const raw = localStorage.getItem(STORAGE_KEY)
    if (!raw) return null
    return JSON.parse(raw)
  } catch {
    return null
  }
}

const normalizeCompletedSteps = (steps) =>
  Array.isArray(steps) ? STUDENT_REGISTRATION_ORDER.filter((step) => steps.includes(step)) : []

const firstIncompleteIndex = (steps) => {
  const index = STUDENT_REGISTRATION_ORDER.findIndex((step) => !steps.includes(step))
  return index === -1 ? STUDENT_REGISTRATION_ORDER.length - 1 : index
}

const resolveCurrentStep = (candidate, completed) => {
  const candidateIndex = STUDENT_REGISTRATION_ORDER.indexOf(candidate)
  const reachableIndex = firstIncompleteIndex(completed)
  if (candidateIndex >= 0 && candidateIndex <= reachableIndex) return candidate
  return STUDENT_REGISTRATION_ORDER[reachableIndex]
}

export const useStudentRegistrationStore = defineStore('studentRegistration', () => {
  const persisted = readPersisted() || {}
  const initial = { ...emptyState(), ...persisted }

  const isProfileCompleted = ref(initial.isProfileCompleted)
  const personal = ref({ ...emptyState().personal, ...persisted.personal })
  const educational = ref({ ...emptyState().educational, ...persisted.educational })
  const professional = ref({ ...emptyState().professional, ...persisted.professional })
  const skill1 = ref({ ...emptyState().skill1, ...persisted.skill1 })
  const skill2 = ref({ ...emptyState().skill2, ...persisted.skill2 })
  const skill3 = ref({ ...emptyState().skill3, ...persisted.skill3 })
  const skill4 = ref({ ...emptyState().skill4, ...persisted.skill4 })
  const skill5 = ref({ ...emptyState().skill5, ...persisted.skill5 })
  const skill6 = ref({ ...emptyState().skill6, ...persisted.skill6 })
  const skill7 = ref({ ...emptyState().skill7, ...persisted.skill7 })
  const completedSteps = ref(normalizeCompletedSteps(initial.completedSteps))
  const currentStep = ref(resolveCurrentStep(initial.currentStep, completedSteps.value))
  const registrationMedia = ref(initial.registrationMedia || {})

  const sectionRefs = {
    personal,
    educational,
    professional,
    skill1,
    skill2,
    skill3,
    skill4,
    skill5,
    skill6,
    skill7,
  }

  const snapshot = computed(() => ({
    isProfileCompleted: isProfileCompleted.value,
    personal: personal.value,
    educational: educational.value,
    professional: professional.value,
    skill1: skill1.value,
    skill2: skill2.value,
    skill3: skill3.value,
    skill4: skill4.value,
    skill5: skill5.value,
    skill6: skill6.value,
    skill7: skill7.value,
    currentStep: currentStep.value,
    completedSteps: completedSteps.value,
    registrationMedia: registrationMedia.value,
  }))

  watch(
    snapshot,
    (value) => {
      try {
        localStorage.setItem(STORAGE_KEY, JSON.stringify(value))
      } catch {
        /* storage may be unavailable */
      }
    },
    { deep: true }
  )

  const markStepAsCompleted = (stepKey) => {
    if (STUDENT_REGISTRATION_ORDER.includes(stepKey) && !completedSteps.value.includes(stepKey)) {
      completedSteps.value = [...completedSteps.value, stepKey]
    }
  }

  const updateCurrentStep = (stepKey) => {
    if (canGoToStep(stepKey)) currentStep.value = stepKey
  }

  const updateSection = (section, value) => {
    const target = sectionRefs[section]
    if (!target || !value || typeof value !== 'object') return
    target.value = { ...target.value, ...value }
  }

  const setRegistrationMedia = (value) => {
    if (!value || typeof value !== 'object') return
    registrationMedia.value = { ...registrationMedia.value, ...value }
  }

  const goToNextStep = () => {
    const idx = STUDENT_REGISTRATION_ORDER.indexOf(currentStep.value)
    if (
      idx >= 0 &&
      idx < STUDENT_REGISTRATION_ORDER.length - 1 &&
      completedSteps.value.includes(currentStep.value)
    ) {
      currentStep.value = STUDENT_REGISTRATION_ORDER[idx + 1]
    }
  }

  const goToPrevStep = () => {
    const idx = STUDENT_REGISTRATION_ORDER.indexOf(currentStep.value)
    if (idx > 0) currentStep.value = STUDENT_REGISTRATION_ORDER[idx - 1]
  }

  const canGoToStep = (stepKey) => {
    const targetIndex = STUDENT_REGISTRATION_ORDER.indexOf(stepKey)
    return targetIndex >= 0 && targetIndex <= firstIncompleteIndex(completedSteps.value)
  }

  const buildCompletePayload = () => ({
    ...personal.value,
    ...educational.value,
    ...professional.value,
    ...skill1.value,
    ...skill2.value,
    ...skill3.value,
    ...skill4.value,
    ...skill5.value,
    ...skill6.value,
    ...skill7.value,
    avatarId: personal.value.avatar?.uploadId
      ? Number.parseInt(personal.value.avatar.uploadId)
      : personal.value.avatarId,
  })

  // Take the flat `{ field: value }` map from GET /me/register-data and slot
  // each value into the right section ref, leaving anything we don't
  // recognise alone.
  const hydrateFromRegisterData = (input) => {
    const flat = toRegisterDataObject(input)
    const buckets = {}
    Object.entries(flat).forEach(([key, value]) => {
      const section = FIELD_TO_SECTION[key]
      if (!section) return
      buckets[section] = { ...buckets[section], [key]: value }
    })
    Object.entries(buckets).forEach(([section, patch]) => {
      const target = sectionRefs[section]
      if (target) target.value = { ...target.value, ...patch }
    })
  }

  const reset = () => {
    const fresh = emptyState()
    isProfileCompleted.value = fresh.isProfileCompleted
    personal.value = fresh.personal
    educational.value = fresh.educational
    professional.value = fresh.professional
    skill1.value = fresh.skill1
    skill2.value = fresh.skill2
    skill3.value = fresh.skill3
    skill4.value = fresh.skill4
    skill5.value = fresh.skill5
    skill6.value = fresh.skill6
    skill7.value = fresh.skill7
    currentStep.value = fresh.currentStep
    completedSteps.value = fresh.completedSteps
    registrationMedia.value = fresh.registrationMedia
    try {
      localStorage.removeItem(STORAGE_KEY)
    } catch {
      /* ignore */
    }
  }

  return {
    isProfileCompleted,
    personal,
    educational,
    professional,
    skill1,
    skill2,
    skill3,
    skill4,
    skill5,
    skill6,
    skill7,
    currentStep,
    completedSteps,
    registrationMedia,
    markStepAsCompleted,
    updateCurrentStep,
    updateSection,
    setRegistrationMedia,
    goToNextStep,
    goToPrevStep,
    canGoToStep,
    buildCompletePayload,
    hydrateFromRegisterData,
    reset,
  }
})
