/**
 * Composable for starter deck selection.
 *
 * Provides state and actions for the starter deck selection flow that
 * new users must complete before accessing the main app.
 *
 * Includes a development mock fallback when the backend API is not yet
 * available, allowing the full UI flow to be tested.
 */
import { ref, computed, readonly } from 'vue'
import { useRouter } from 'vue-router'

import { useAuthStore } from '@/stores/auth'
import { apiClient } from '@/api/client'
import { ApiError } from '@/api/types'
import { config } from '@/config'
import type { CardType, Deck } from '@/types'

/** Starter deck type options */
export type StarterType = Extract<CardType, 'grass' | 'fire' | 'water' | 'psychic' | 'lightning'>

/** Starter deck metadata for display */
export interface StarterDeck {
  type: StarterType
  name: string
  description: string
  cardCount: number
}

/** API request payload for selecting a starter deck */
interface SelectStarterRequest {
  starter_type: StarterType
}

/** Predefined starter deck options */
export const STARTER_DECKS: StarterDeck[] = [
  {
    type: 'grass',
    name: 'Forest Guardians',
    description: 'Growth and healing focused deck',
    cardCount: 40,
  },
  {
    type: 'fire',
    name: 'Flame Warriors',
    description: 'Aggressive damage-focused deck',
    cardCount: 40,
  },
  {
    type: 'water',
    name: 'Tidal Force',
    description: 'Balanced control and damage',
    cardCount: 40,
  },
  {
    type: 'psychic',
    name: 'Mind Masters',
    description: 'Status effects and manipulation',
    cardCount: 40,
  },
  {
    type: 'lightning',
    name: 'Storm Riders',
    description: 'Fast, high-damage strikes',
    cardCount: 40,
  },
]

/** Result of starter deck selection */
export interface SelectStarterResult {
  success: boolean
  deck?: Deck
  error?: string
  wasMocked?: boolean
}

/**
 * Development mock for starter deck selection.
 *
 * Simulates a successful API response when the backend endpoint
 * is not yet available. Only used when the real API fails.
 */
function createMockDeck(starterType: StarterType): Deck {
  const starter = STARTER_DECKS.find(s => s.type === starterType)
  return {
    id: `mock-starter-${starterType}`,
    name: starter?.name ?? `${starterType} Starter`,
    cards: [],
    isValid: true,
    cardCount: 40,
  }
}

/**
 * Starter deck selection composable.
 *
 * Manages the state and API interactions for selecting a starter deck.
 * Includes loading/error states and handles the post-selection navigation.
 *
 * @example
 * ```vue
 * <script setup lang="ts">
 * import { useStarter, STARTER_DECKS } from '@/composables/useStarter'
 *
 * const { isLoading, error, selectStarter } = useStarter()
 *
 * async function handleSelect(type: StarterType) {
 *   await selectStarter(type)
 * }
 * </script>
 * ```
 */
export function useStarter() {
  const router = useRouter()
  const authStore = useAuthStore()

  // Local state
  const isLoading = ref(false)
  const error = ref<string | null>(null)
  const selectedType = ref<StarterType | null>(null)

  // Computed
  const hasStarterDeck = computed(() => authStore.user?.hasStarterDeck ?? false)

  /**
   * Select a starter deck.
   *
   * Calls the backend API to assign the selected starter deck to the user.
   * On success, updates the auth store and redirects to the dashboard.
   *
   * If the API is not available (404/500), falls back to a mock response
   * in development mode to allow testing the UI flow.
   *
   * @param starterType - The type of starter deck to select
   * @returns Result indicating success/failure
   */
  async function selectStarter(starterType: StarterType): Promise<SelectStarterResult> {
    isLoading.value = true
    error.value = null
    selectedType.value = starterType

    try {
      // Attempt real API call
      const deck = await apiClient.post<Deck>('/api/users/me/starter-deck', {
        starter_type: starterType,
      } satisfies SelectStarterRequest)

      // Update auth store to reflect starter deck selection
      if (authStore.user) {
        authStore.setUser({
          ...authStore.user,
          hasStarterDeck: true,
        })
      }

      // Redirect to dashboard
      router.push({ name: 'Dashboard' })

      return {
        success: true,
        deck,
      }
    } catch (e) {
      // Handle specific error cases
      if (e instanceof ApiError) {
        // Already has starter deck (backend returns 400 with detail message)
        const isAlreadySelected =
          e.status === 409 ||
          e.status === 400 && e.detail?.toLowerCase().includes('already selected') ||
          e.code === 'ALREADY_HAS_STARTER'

        if (isAlreadySelected) {
          // Update local state and redirect anyway
          if (authStore.user) {
            authStore.setUser({
              ...authStore.user,
              hasStarterDeck: true,
            })
          }
          router.push({ name: 'Dashboard' })
          return {
            success: true,
            error: 'You already have a starter deck.',
          }
        }

        // API not available - use dev mock in non-production
        if ((e.isNotFound || e.isServerError) && config.isDev) {
          console.warn('[useStarter] API not available, using mock response')

          const mockDeck = createMockDeck(starterType)

          // Update auth store with mock data
          if (authStore.user) {
            authStore.setUser({
              ...authStore.user,
              hasStarterDeck: true,
            })
          }

          // Redirect to dashboard
          router.push({ name: 'Dashboard' })

          return {
            success: true,
            deck: mockDeck,
            wasMocked: true,
          }
        }

        // Other API errors
        error.value = e.detail || e.message || 'Failed to select starter deck'
        return {
          success: false,
          error: error.value,
        }
      }

      // Unknown error
      const errorMessage = e instanceof Error ? e.message : 'An unexpected error occurred'
      error.value = errorMessage
      return {
        success: false,
        error: errorMessage,
      }
    } finally {
      isLoading.value = false
    }
  }

  /**
   * Clear the error state.
   */
  function clearError(): void {
    error.value = null
  }

  return {
    // State (readonly to prevent external mutation)
    isLoading: readonly(isLoading),
    error: readonly(error),
    selectedType: readonly(selectedType),
    hasStarterDeck,

    // Constants
    starterDecks: STARTER_DECKS,

    // Actions
    selectStarter,
    clearError,
  }
}

export type UseStarter = ReturnType<typeof useStarter>
