import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { get, post } from "@/utils/request";

interface AuthUserView {
  id: number;
  username: string;
  fullName?: string;
  email?: string;
  avatarUrl?: string;
  organization?: string;
}

interface AuthLoginPayload {
  token: string;
  tokenType: string;
  expiresInSeconds: number;
  user: AuthUserView;
  roles: string[];
  permissions: string[];
}

interface AuthCurrentUserPayload {
  user: AuthUserView;
  roles: string[];
  permissions: string[];
}

interface ApiResponse<T> {
  code: string;
  message: string;
  data: T;
}

interface AuthState {
  user: AuthUserView | null;
  token: string | null;
  roles: string[];
  permissions: string[];
  isAuthenticated: boolean;
  initialized: boolean;
  loading: boolean;
  error: string | null;
}

interface LoginCredentials {
  username: string;
  password: string;
}

const extractErrorMessage = (error: unknown): string => {
  if (error instanceof Error) {
    const nestedMessage = (error as { data?: { message?: string } }).data?.message;
    return nestedMessage ?? error.message;
  }
  return "登录失败，请稍后重试";
};

export const loginUser = createAsyncThunk<
  AuthLoginPayload,
  LoginCredentials,
  { rejectValue: string }
>("auth/login", async (credentials, { rejectWithValue }) => {
  try {
    const response = (await post("/api/auth/login", credentials)) as ApiResponse<AuthLoginPayload>;
    if (!response?.data?.token) {
      return rejectWithValue(response?.message ?? "登录失败");
    }
    return response.data;
  } catch (error) {
    return rejectWithValue(extractErrorMessage(error));
  }
});

export const fetchCurrentUser = createAsyncThunk<
  AuthCurrentUserPayload,
  void,
  { rejectValue: string }
>("auth/fetchCurrentUser", async (_, { rejectWithValue }) => {
  try {
    const response = (await get("/api/auth/me")) as ApiResponse<AuthCurrentUserPayload>;
    if (!response?.data?.user) {
      return rejectWithValue(response?.message ?? "用户信息加载失败");
    }
    return response.data;
  } catch (error) {
    return rejectWithValue(extractErrorMessage(error));
  }
});

const initialToken = localStorage.getItem("token");

const initialState: AuthState = {
  user: null,
  token: initialToken,
  roles: [],
  permissions: [],
  isAuthenticated: Boolean(initialToken),
  initialized: false,
  loading: false,
  error: null,
};

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    logout: (state) => {
      state.user = null;
      state.token = null;
      state.roles = [];
      state.permissions = [];
      state.isAuthenticated = false;
      state.error = null;
      state.initialized = true;
      localStorage.removeItem("token");
    },
    clearError: (state) => {
      state.error = null;
    },
    markInitialized: (state) => {
      state.initialized = true;
    },
  },
  extraReducers: (builder) => {
    builder
      .addCase(loginUser.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(loginUser.fulfilled, (state, action) => {
        state.loading = false;
        state.initialized = true;
        state.user = action.payload.user;
        state.token = action.payload.token;
        state.roles = action.payload.roles ?? [];
        state.permissions = action.payload.permissions ?? [];
        state.isAuthenticated = true;
        state.error = null;
        localStorage.setItem("token", action.payload.token);
      })
      .addCase(loginUser.rejected, (state, action) => {
        state.loading = false;
        state.initialized = true;
        state.user = null;
        state.roles = [];
        state.permissions = [];
        state.isAuthenticated = false;
        state.token = null;
        state.error = action.payload ?? "登录失败";
        localStorage.removeItem("token");
      })
      .addCase(fetchCurrentUser.pending, (state) => {
        state.loading = true;
        state.error = null;
      })
      .addCase(fetchCurrentUser.fulfilled, (state, action) => {
        state.loading = false;
        state.initialized = true;
        state.user = action.payload.user;
        state.roles = action.payload.roles ?? [];
        state.permissions = action.payload.permissions ?? [];
        state.isAuthenticated = Boolean(state.token);
        state.error = null;
      })
      .addCase(fetchCurrentUser.rejected, (state, action) => {
        state.loading = false;
        state.initialized = true;
        state.user = null;
        state.roles = [];
        state.permissions = [];
        state.isAuthenticated = false;
        state.token = null;
        state.error = action.payload ?? "登录状态已失效";
        localStorage.removeItem("token");
      });
  },
});

export const { logout, clearError, markInitialized } = authSlice.actions;
export default authSlice.reducer;
