import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import { authAPI } from '../services/authAPI';

// API Response Types
interface LoginSuccessResponse {
  status: 'success';
  message: string;
  data: {
    accessToken: string;
    refreshToken: string;
    user: AuthUser;
  };
  timestamp: string;
}

interface LoginErrorResponse {
  status: 'error';
  message: string;
  errorCode: string;
  timestamp: string;
}

interface RefreshTokenSuccessResponse {
  status: 'success';
  message: string;
  data: {
    accessToken: string;
  };
  timestamp: string;
}

interface RefreshTokenErrorResponse {
  status: 'error';
  message: string;
  errorCode: 'INVALID_REFRESH';
  timestamp: string;
}

interface RegisterSuccessResponse {
  status: 'success';
  message: string;
  data: {
    uuid: string;
    email: string;
  };
  timestamp: string;
}

interface RegisterErrorResponse {
  status: 'error';
  message: string;
  errorCode: string;
  timestamp: string;
}

type LoginResponse = LoginSuccessResponse | LoginErrorResponse;
type RefreshTokenResponse = RefreshTokenSuccessResponse | RefreshTokenErrorResponse;
type RegisterResponse = RegisterSuccessResponse | RegisterErrorResponse;

export interface AuthUser {
  id: number;
  uuid: string;
  email: string;
  displayName: string;
  role: string;
}

export interface AuthState {
  user: AuthUser | null;
  accessToken: string | null;
  refreshToken: string | null;
  loading: boolean;
  error: string | null;
  isAuthenticated: boolean;
}

const initialState: AuthState = {
  user: null,
  accessToken: null,
  refreshToken: null,
  loading: false,
  error: null,
  isAuthenticated: false,
};

export const login = createAsyncThunk(
  'auth/login',
  async (payload: { email: string; password: string }, { rejectWithValue }) => {
    try {
      const response = await authAPI.login(payload.email, payload.password);
      console.log('login response igot',response)
      const data = response.data as LoginResponse;
      
      if (data.status === 'success') {
        return {
          accessToken: data.data.accessToken,
          refreshToken: data.data.refreshToken,
          user: data.data.user,
        };
      } else {
        return rejectWithValue(data.message || 'Login failed');
      }
    } catch (error: any) {
      // Handle network errors or API errors
      if (error.response?.data?.status === 'error') {
        const errorData = error.response.data as LoginErrorResponse;
        return rejectWithValue(errorData.message || 'Login failed');
      }
      return rejectWithValue(error.message || 'Network error occurred');
    }
  },
);

export const refreshToken = createAsyncThunk(
  'auth/refreshToken',
  async (refreshTokenValue: string, { rejectWithValue }) => {
    try {
      const response = await authAPI.refreshToken(refreshTokenValue);
      const data = response.data as RefreshTokenResponse;
      console.log('refresh token response got',data)
      
      if (data.status === 'success') {
        return {
          accessToken: data.data.accessToken,
        };
      } else {
        return rejectWithValue(data.message || 'Token refresh failed');
      }
    } catch (error: any) {
      // Handle network errors or API errors
      if (error.response?.data?.status === 'error') {
        const errorData = error.response.data as RefreshTokenErrorResponse;
        return rejectWithValue(errorData.message || 'Token refresh failed');
      }
      return rejectWithValue(error.message || 'Network error occurred');
    }
  },
);

export const register = createAsyncThunk(
  'auth/register',
  async (payload: { email: string; password: string; firstName: string; lastName: string }, { rejectWithValue }) => {
    try {
      const response = await authAPI.register(payload);
      const data = response.data as RegisterResponse;
      console.log('register response got', data);
      
      if (data.status === 'success') {
        return {
          uuid: data.data.uuid,
          email: data.data.email,
          message: data.message,
        };
      } else {
        return rejectWithValue(data.message || 'Registration failed');
      }
    } catch (error: any) {
      // Handle network errors or API errors
      if (error.response?.data?.status === 'error') {
        const errorData = error.response.data as RegisterErrorResponse;
        return rejectWithValue(errorData.message || 'Registration failed');
      }
      return rejectWithValue(error.message || 'Network error occurred');
    }
  },
);

const authSlice = createSlice({
  name: 'auth',
  initialState,
  reducers: {
    logout: state => {
      state.user = null;
      state.accessToken = null;
      state.refreshToken = null;
      state.error = null;
      state.isAuthenticated = false;
    },
    clearError: state => {
      state.error = null;
    },
    updateAccessToken: (state, action: PayloadAction<string>) => {
      state.accessToken = action.payload;
    },
  },
  extraReducers: builder => {
    builder
      .addCase(login.pending, state => {
        state.loading = true;
        state.error = null;
      })
      .addCase(login.fulfilled, (state, action) => {
        state.loading = false;
        state.accessToken = action.payload.accessToken;
        state.refreshToken = action.payload.refreshToken;
        state.user = action.payload.user;
        state.isAuthenticated = true;
        state.error = null;
      })
      .addCase(login.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || 'Login failed';
        state.isAuthenticated = false;
      })
      .addCase(refreshToken.pending, state => {
        // Don't set loading to true for refresh token to avoid UI flicker
        state.error = null;
      })
      .addCase(refreshToken.fulfilled, (state, action) => {
        state.accessToken = action.payload.accessToken;
        state.error = null;
      })
      .addCase(refreshToken.rejected, (state, action) => {
        // If refresh token fails, logout the user
        state.user = null;
        state.accessToken = null;
        state.refreshToken = null;
        state.error = action.payload as string || 'Token refresh failed';
        state.isAuthenticated = false;
      })
      .addCase(register.pending, state => {
        state.loading = true;
        state.error = null;
      })
      .addCase(register.fulfilled, (state, action) => {
        state.loading = false;
        state.error = null;
        // Note: Registration doesn't automatically log in the user
        // They need to login separately after successful registration
      })
      .addCase(register.rejected, (state, action) => {
        state.loading = false;
        state.error = action.payload as string || 'Registration failed';
      });
  },
});

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


