import { create } from 'zustand'
import { scriptsApi } from '@/api'
import type {
  ScriptCategoryResponse,
  ScriptTemplateListItem,
  ScriptTemplateDetail,
  ScriptParametersSchema,
} from '@/types'

interface ScriptGeneratorState {
  // Template browsing
  categories: ScriptCategoryResponse[]
  templates: ScriptTemplateListItem[]
  selectedTemplate: ScriptTemplateDetail | null
  searchQuery: string
  activeCategoryId: string | null  // null = "All"
  tabFilters: { mine?: boolean; shared?: boolean }  // current tab's ownership filter
  isLoadingTemplates: boolean      // drives skeleton in ScriptTemplateList
  isLoadingDetail: boolean         // drives spinner in ScriptConfigurePane

  // Form
  paramValues: Record<string, string>  // keyed by ScriptParameter.key; booleans as 'true'/'false'
  formErrors: Record<string, string>   // keyed by ScriptParameter.key

  // Output
  generatedScript: string | null
  generationId: string | null
  generationWarnings: string[]
  isGenerating: boolean
  generateError: string | null

  // Actions
  loadCategories: () => Promise<void>
  loadTemplates: (filters?: { mine?: boolean; shared?: boolean }) => Promise<void>
  selectTemplate: (id: string) => Promise<void>
  setCategory: (id: string | null) => void
  setSearch: (query: string) => void
  setParamValue: (key: string, value: string) => void
  validate: () => boolean
  generate: (sessionId?: string) => Promise<void>
  clearOutput: () => void
  reset: () => void
}

export const useScriptGeneratorStore = create<ScriptGeneratorState>()((set, get) => ({
  // Initial state
  categories: [],
  templates: [],
  selectedTemplate: null,
  searchQuery: '',
  activeCategoryId: null,
  tabFilters: {},
  isLoadingTemplates: false,
  isLoadingDetail: false,
  paramValues: {},
  formErrors: {},
  generatedScript: null,
  generationId: null,
  generationWarnings: [],
  isGenerating: false,
  generateError: null,

  loadCategories: async () => {
    try {
      const categories = await scriptsApi.getCategories()
      set({ categories })
    } catch {
      // silently ignore — categories remain empty, UI degrades gracefully
    }
  },

  loadTemplates: async (filters) => {
    // When filters are provided (e.g. tab change), persist them so that
    // subsequent setCategory/setSearch calls reuse the same ownership filter.
    const resolvedFilters = filters !== undefined ? filters : get().tabFilters
    if (filters !== undefined) set({ tabFilters: filters })
    set({ isLoadingTemplates: true })
    try {
      const { activeCategoryId, categories, searchQuery } = get()
      const category = categories.find(c => c.id === activeCategoryId)
      const params: { category_slug?: string; search?: string; mine?: boolean; shared?: boolean } = {}
      if (category) params.category_slug = category.slug
      if (searchQuery) params.search = searchQuery
      if (resolvedFilters.mine) params.mine = true
      if (resolvedFilters.shared) params.shared = true
      const templates = await scriptsApi.getTemplates(params)
      set({ templates, isLoadingTemplates: false })
    } catch {
      set({ isLoadingTemplates: false })
    }
  },

  selectTemplate: async (id: string) => {
    set({ isLoadingDetail: true })
    try {
      const detail = await scriptsApi.getTemplateDetail(id)
      // Populate paramValues from parameter defaults
      const schema = detail.parameters_schema as ScriptParametersSchema
      const parameters = schema?.parameters ?? []
      const paramValues: Record<string, string> = {}
      for (const param of parameters) {
        const d = param.default
        if (d === null || d === undefined) paramValues[param.key] = ''
        else if (typeof d === 'boolean') paramValues[param.key] = d ? 'true' : 'false'
        else paramValues[param.key] = String(d)
      }
      set({
        selectedTemplate: detail,
        paramValues,
        formErrors: {},
        generatedScript: null,
        generationId: null,
        generationWarnings: [],
        generateError: null,
        isLoadingDetail: false,
      })
    } catch {
      set({ isLoadingDetail: false })
    }
  },

  setCategory: (id: string | null) => {
    set({ activeCategoryId: id })
    get().loadTemplates()
  },

  setSearch: (query: string) => {
    set({ searchQuery: query })
    get().loadTemplates()
  },

  setParamValue: (key: string, value: string) => {
    set(state => ({
      paramValues: { ...state.paramValues, [key]: value },
      formErrors: { ...state.formErrors, [key]: '' }, // clear error on change
    }))
  },

  validate: () => {
    const { selectedTemplate, paramValues } = get()
    if (!selectedTemplate) return true
    const schema = selectedTemplate.parameters_schema as ScriptParametersSchema
    const parameters = schema?.parameters ?? []
    const errors: Record<string, string> = {}
    for (const param of parameters) {
      if (param.required && !paramValues[param.key]) {
        errors[param.key] = `${param.label} is required`
      }
    }
    set({ formErrors: errors })
    return Object.keys(errors).length === 0
  },

  generate: async (sessionId?: string) => {
    const { selectedTemplate, paramValues } = get()
    if (!selectedTemplate) return
    if (!get().validate()) return

    set({ isGenerating: true, generateError: null })
    try {
      const response = await scriptsApi.generate({
        template_id: selectedTemplate.id,
        parameters: paramValues,
        ...(sessionId ? { session_id: sessionId } : {}),
      })
      set({
        generatedScript: response.script,
        generationId: response.id,
        generationWarnings: response.warnings,
        isGenerating: false,
      })
    } catch (error: unknown) {
      const axiosErr = error as { response?: { data?: { detail?: string } } }
      const message = axiosErr.response?.data?.detail ?? 'Failed to generate script'
      set({ generateError: message, isGenerating: false })
    }
  },

  clearOutput: () => {
    set({
      generatedScript: null,
      generationId: null,
      generationWarnings: [],
      generateError: null,
    })
  },

  // Exposed for Phase 3 callers (session execution context).
  // Does NOT clear selectedTemplate, categories, templates, or browsing state.
  reset: () => {
    set({
      paramValues: {},
      formErrors: {},
      generatedScript: null,
      generationId: null,
      generationWarnings: [],
      generateError: null,
    })
  },
}))
