import { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from "react"

type FlowName = "login" | "signup" | "forgotPassword"
export type CooldownKey =
  | "loginOtpSend"
  | "signupOtpSend"
  | "forgotPasswordOtpSend"
  | "loginPassword"
  | "loginOtpVerify"

interface FlowBranchState {
  mobile: string
  code: string
}

interface CooldownState {
  loginOtpSend: number
  signupOtpSend: number
  forgotPasswordOtpSend: number
  loginPassword: number
  loginOtpVerify: number
}

interface AuthFlowState {
  login: FlowBranchState
  signup: FlowBranchState
  forgotPassword: FlowBranchState
  cooldowns: CooldownState
}

interface AuthFlowContextValue {
  state: AuthFlowState
  setMobile: (flow: FlowName, mobile: string) => void
  setCode: (flow: FlowName, code: string) => void
  setCooldown: (key: CooldownKey, seconds: number) => void
  clearCooldown: (key: CooldownKey) => void
  resetFlow: (flow: FlowName) => void
}

const STORAGE_KEY = "auth_flow_state:v1"

const defaultState: AuthFlowState = {
  login: {
    mobile: "",
    code: "",
  },
  signup: {
    mobile: "",
    code: "",
  },
  forgotPassword: {
    mobile: "",
    code: "",
  },
  cooldowns: {
    loginOtpSend: 0,
    signupOtpSend: 0,
    forgotPasswordOtpSend: 0,
    loginPassword: 0,
    loginOtpVerify: 0,
  },
}

const AuthFlowContext = createContext<AuthFlowContextValue | null>(null)

const parseStoredState = (): AuthFlowState => {
  if (typeof window === "undefined") {
    return defaultState
  }

  const raw = window.sessionStorage.getItem(STORAGE_KEY)
  if (!raw) {
    return defaultState
  }

  try {
    const parsed = JSON.parse(raw) as Partial<AuthFlowState>

    return {
      login: {
        mobile: parsed.login?.mobile ?? "",
        code: parsed.login?.code ?? "",
      },
      signup: {
        mobile: parsed.signup?.mobile ?? "",
        code: parsed.signup?.code ?? "",
      },
      forgotPassword: {
        mobile: parsed.forgotPassword?.mobile ?? "",
        code: parsed.forgotPassword?.code ?? "",
      },
      cooldowns: {
        loginOtpSend: parsed.cooldowns?.loginOtpSend ?? 0,
        signupOtpSend: parsed.cooldowns?.signupOtpSend ?? 0,
        forgotPasswordOtpSend: parsed.cooldowns?.forgotPasswordOtpSend ?? 0,
        loginPassword: parsed.cooldowns?.loginPassword ?? 0,
        loginOtpVerify: parsed.cooldowns?.loginOtpVerify ?? 0,
      },
    }
  } catch {
    return defaultState
  }
}

export function AuthFlowProvider({ children }: { children: ReactNode }) {
  const [state, setState] = useState<AuthFlowState>(parseStoredState)

  useEffect(() => {
    window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state))
  }, [state])

  useEffect(() => {
    if (!Object.values(state.cooldowns).some((value) => value > 0)) {
      return
    }

    const timer = window.setInterval(() => {
      setState((current) => ({
        ...current,
        cooldowns: {
          loginOtpSend: Math.max(0, current.cooldowns.loginOtpSend - 1),
          signupOtpSend: Math.max(0, current.cooldowns.signupOtpSend - 1),
          forgotPasswordOtpSend: Math.max(0, current.cooldowns.forgotPasswordOtpSend - 1),
          loginPassword: Math.max(0, current.cooldowns.loginPassword - 1),
          loginOtpVerify: Math.max(0, current.cooldowns.loginOtpVerify - 1),
        },
      }))
    }, 1000)

    return () => window.clearInterval(timer)
  }, [state.cooldowns])

  const value = useMemo<AuthFlowContextValue>(
    () => ({
      state,
      setMobile: (flow, mobile) => {
        setState((current) => ({
          ...current,
          [flow]: {
            ...current[flow],
            mobile,
          },
        }))
      },
      setCode: (flow, code) => {
        setState((current) => ({
          ...current,
          [flow]: {
            ...current[flow],
            code,
          },
        }))
      },
      setCooldown: (key, seconds) => {
        setState((current) => ({
          ...current,
          cooldowns: {
            ...current.cooldowns,
            [key]: Math.max(current.cooldowns[key], seconds),
          },
        }))
      },
      clearCooldown: (key) => {
        setState((current) => ({
          ...current,
          cooldowns: {
            ...current.cooldowns,
            [key]: 0,
          },
        }))
      },
      resetFlow: (flow) => {
        setState((current) => ({
          ...current,
          [flow]: {
            mobile: "",
            code: "",
          },
        }))
      },
    }),
    [state],
  )

  return <AuthFlowContext.Provider value={value}>{children}</AuthFlowContext.Provider>
}

export function useAuthFlow() {
  const context = useContext(AuthFlowContext)

  if (!context) {
    throw new Error("useAuthFlow must be used within an AuthFlowProvider")
  }

  return context
}
