import { createSlice, createAsyncThunk, type PayloadAction } from '@reduxjs/toolkit'

/**
 * 用户信息接口
 */
export interface User {
  id: string
  username: string
  role?: 'superadmin' | 'leader' | 'member'
  groupId?: string
  groupName?: string
  allowBuild?: boolean
  lastLoginAt?: Date
}

/**
 * 认证状态接口
 */
interface AuthState {
  isAuthenticated: boolean
  token: string | null
  user: User | null
  loading: boolean
  error: string | null
  loginAttempts: number
  lastLoginAttempt: number | null
}

/**
 * 登录请求参数接口
 */
interface LoginRequest {
  username: string
  password: string
}

/**
 * 登录响应接口
 */
interface LoginResponse {
  success: boolean
  message?: string
  token?: string
  user?: User
}

/**
 * Token验证响应接口
 */
interface VerifyTokenResponse {
  valid: boolean
  user?: User
  error?: string
}

const initialState: AuthState = {
  isAuthenticated: false,
  token: null,
  user: null,
  loading: false,
  error: null,
  loginAttempts: 0,
  lastLoginAttempt: null
}

/**
 * 判断字符串是否为IP地址
 */
const isIPAddress = (hostname: string): boolean => {
  // IPv4地址正则表达式
  const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/
  
  // IPv6地址正则表达式（简化版）
  const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/
  
  return ipv4Regex.test(hostname) || ipv6Regex.test(hostname)
}

/**
 * 获取服务器URL
 */
const getServerUrl = (): string => {
  // 判断hostname是否为IP地址
  const isIP = isIPAddress(window.location.hostname)
  
  if (isIP) {
    // 如果是IP地址，添加3001端口
    return `${window.location.protocol}//${window.location.hostname}:3001`
  } else {
    // 如果是域名，直接使用域名（通常域名会通过反向代理处理端口）
    return `${window.location.protocol}//${window.location.hostname}`
  }
}

/**
 * 异步登录操作
 */
export const login = createAsyncThunk<
  LoginResponse,
  LoginRequest,
  { rejectValue: string }
>('auth/login', async ({ username, password }, { rejectWithValue }) => {
  try {
    const serverUrl = getServerUrl()
    const response = await fetch(`${serverUrl}/api/auth/login`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username, password }),
    })

    const data = await response.json()

    if (!response.ok) {
      return rejectWithValue(data.message || '登录失败')
    }

    return data
  } catch (error: any) {
    console.error('登录请求失败:', error)
    return rejectWithValue(error.message || '网络连接失败')
  }
})

/**
 * 异步验证token操作
 */
export const verifyToken = createAsyncThunk<
  VerifyTokenResponse,
  string,
  { rejectValue: string }
>('auth/verifyToken', async (token, { rejectWithValue }) => {
  try {
    const serverUrl = getServerUrl()
    const response = await fetch(`${serverUrl}/api/auth/verify`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`,
      },
    })

    const data = await response.json()

    if (!response.ok) {
      return rejectWithValue(data.error || 'Token验证失败')
    }

    return data
  } catch (error: any) {
    console.error('Token验证失败:', error)
    return rejectWithValue(error.message || '网络连接失败')
  }
})

/**
 * 异步登出操作
 */
export const logout = createAsyncThunk<
  void,
  void,
  { rejectValue: string }
>('auth/logout', async () => {
  try {
    const serverUrl = getServerUrl()
    const token = localStorage.getItem('auth_token')
    
    if (token) {
      await fetch(`${serverUrl}/api/auth/logout`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`,
        },
      })
    }
  } catch (error: any) {
    console.error('登出请求失败:', error)
    // 即使服务器登出失败，也继续清除本地状态
  }
})

/**
 * 认证管理 Slice
 */
const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    // 清除错误
    clearError: (state) => {
      state.error = null
    },
    
    // 重置登录尝试次数
    resetLoginAttempts: (state) => {
      state.loginAttempts = 0
      state.lastLoginAttempt = null
    },
    
    // 从本地存储恢复认证状态
    restoreAuthState: (state) => {
      const token = localStorage.getItem('auth_token')
      const userStr = localStorage.getItem('auth_user')
      
      if (token && userStr) {
        try {
          const user = JSON.parse(userStr)
          state.token = token
          state.user = user
          state.isAuthenticated = true
        } catch (error) {
          console.error('恢复认证状态失败:', error)
          localStorage.removeItem('auth_token')
          localStorage.removeItem('auth_user')
        }
      }
    },
    
    // 清除认证状态
    clearAuthState: (state) => {
      state.isAuthenticated = false
      state.token = null
      state.user = null
      state.error = null
      localStorage.removeItem('auth_token')
      localStorage.removeItem('auth_user')
    },
    
    // 更新用户信息
    updateUser: (state, action: PayloadAction<Partial<User>>) => {
      if (state.user) {
        state.user = { ...state.user, ...action.payload }
        localStorage.setItem('auth_user', JSON.stringify(state.user))
      }
    }
  },
  extraReducers: (builder) => {
    // 登录
    builder
      .addCase(login.pending, (state) => {
        state.loading = true
        state.error = null
      })
      .addCase(login.fulfilled, (state, action) => {
        state.loading = false
        state.error = null
        state.loginAttempts = 0
        state.lastLoginAttempt = null
        
        if (action.payload.success && action.payload.token && action.payload.user) {
          state.isAuthenticated = true
          state.token = action.payload.token
          state.user = action.payload.user
          
          // 保存到本地存储
          localStorage.setItem('auth_token', action.payload.token)
          localStorage.setItem('auth_user', JSON.stringify(action.payload.user))
        }
      })
      .addCase(login.rejected, (state, action) => {
        state.loading = false
        state.error = action.payload || '登录失败'
        state.loginAttempts += 1
        state.lastLoginAttempt = Date.now()
        state.isAuthenticated = false
        state.token = null
        state.user = null
      })
    
    // Token验证
    builder
      .addCase(verifyToken.pending, (state) => {
        state.loading = true
        state.error = null
      })
      .addCase(verifyToken.fulfilled, (state, action) => {
        state.loading = false
        state.error = null
        
        if (action.payload.valid && action.payload.user) {
          state.isAuthenticated = true
          state.user = action.payload.user
          // token已经在state中，不需要重新设置
        } else {
          // Token无效，清除状态
          state.isAuthenticated = false
          state.token = null
          state.user = null
          localStorage.removeItem('auth_token')
          localStorage.removeItem('auth_user')
        }
      })
      .addCase(verifyToken.rejected, (state, action) => {
        state.loading = false
        state.error = action.payload || 'Token验证失败'
        state.isAuthenticated = false
        state.token = null
        state.user = null
        localStorage.removeItem('auth_token')
        localStorage.removeItem('auth_user')
      })
    
    // 登出
    builder
      .addCase(logout.pending, (state) => {
        state.loading = true
      })
      .addCase(logout.fulfilled, (state) => {
        state.loading = false
        state.isAuthenticated = false
        state.token = null
        state.user = null
        state.error = null
        localStorage.removeItem('auth_token')
        localStorage.removeItem('auth_user')
      })
      .addCase(logout.rejected, (state) => {
        state.loading = false
        // 即使登出失败，也清除本地状态
        state.isAuthenticated = false
        state.token = null
        state.user = null
        state.error = null
        localStorage.removeItem('auth_token')
        localStorage.removeItem('auth_user')
      })
  },
})

export const {
  clearError,
  resetLoginAttempts,
  restoreAuthState,
  clearAuthState,
  updateUser
} = authSlice.actions

export default authSlice.reducer

// 选择器（先定义接口，避免循环导入）
interface RootStateForAuth {
  auth: AuthState
}

export const selectAuth = (state: RootStateForAuth) => state.auth
export const selectIsAuthenticated = (state: RootStateForAuth) => state.auth.isAuthenticated
export const selectUser = (state: RootStateForAuth) => state.auth.user
export const selectToken = (state: RootStateForAuth) => state.auth.token
export const selectAuthLoading = (state: RootStateForAuth) => state.auth.loading
export const selectAuthError = (state: RootStateForAuth) => state.auth.error 
