<template>
  <div class="login-page page">
      <div>
        <div class="background-img">
          <p>
            어서오세요.<br />
            로그인하세요.
          </p>
        </div>
        <div class="login-wrap">
            <div class="login">
              <div
                :class="{
                  'login-title': true,
                  'user-login': !isAdminPage,
                }"
              >
                LOGIN
              </div>
              <div class="form-group">
                <label for="id" class="login-label">아이디</label>
                <input
                  type="text"
                  name=""
                  id="id"
                  class="form-control md"
                  placeholder="아이디를 입력하세요"
                  v-model="member['lgnId']"
                />
              </div>
              <div class="form-group">
                <label for="pw" class="login-label">비밀번호</label>
                <input
                  type="password"
                  name=""
                  id="pw"
                  class="form-control md"
                  placeholder="비밀번호를 입력하세요"
                  v-model="member['pswd']"
                  @keydown.enter="fnLogin"
                />
              </div>
              <button
                class="btn md main user-btn"
                v-if="!isAdminPage"
                @click="fnLogin"
                @keydown.enter="fnLogin"
              >
                로그인
              </button>
              <button
                class="btn md main"
                v-else
                @click="fnLogin"
                @keydown.enter="fnLogin"
              >
                로그인
              </button>

              <div
                class="input-group"
                v-if="!isAdminPage"
              >
                <p class="pl10 pr10 cursor" @click="moveSearchId">아이디찾기</p>
                <p class="pl10 pr0 cursor" @click="moveResetPswd">비밀번호 초기화</p>
              </div>
              
              <!-- OAuth2 로그인 버튼들 -->
              <div v-if="!isAdminPage">
                <div>
                  <span>또는</span>
                </div>
                <div>
                  <button @click="fnOAuthLogin('kakao')" :disabled="isOAuthLoading">
                    카카오로 로그인
                  </button>
                  
                  <button  @click="fnOAuthLogin('naver')" :disabled="isOAuthLoading">
                    네이버로 로그인
                  </button>
                  
                  <button @click="fnOAuthLogin('google')" :disabled="isOAuthLoading">
                    구글로 로그인
                  </button>
                </div>
              </div>
            </div>
        </div>
      </div>
    </div>
</template>

<script>
import { useStore } from "vuex";
import store from "../AppStore";
import { loginProc, getUserInfo, oauthLogin } from "../../../resources/api/login";
import queryParams from "../../../resources/js/queryParams";

export default {
  mixins: [queryParams],
  
  data() {
    return {
      member: { lgnId: null, pswd: null },
      store: useStore(),
      isAdminPage: false,
      isOAuthLoading: false,
      // oauthProviders: [
      //   { name: 'kakao', label: '카카오로 로그인' },
      //   { name: 'naver', label: '네이버로 로그인' },
      //   { name: 'google', label: '구글로 로그인' }
      // ]
    };
  },

  async created() {
    this.checkAdminPage();
  },

  async mounted() {
    await this.$nextTick();
    if (this.hasOAuthParams()) {
      await this.handleOAuthCallback();
    }
  },

  beforeUnmount() {
    this.isOAuthLoading = false;
  },

  watch: {
    '$route'(to) {
      if (to.query.oauth_success || to.query.error) {
        this.handleOAuthCallback();
      }
    }
  },

  methods: {
    // ========== 초기화 및 유틸리티 ==========
    checkAdminPage() {
      const redirect = this.restoreRedirect("redirect");
      this.isAdminPage = redirect && redirect.includes("/adm/");
    },

    hasOAuthParams() {
      return window.location.search.includes('oauth_success') || 
             window.location.search.includes('error') ||
             this.$route.query.oauth_success || 
             this.$route.query.error;
    },

    // ========== 일반 로그인 ==========
    async fnLogin() {
      try {
        const res = await loginProc(this.member);
        if (res.status !== 200) return;

        const loginType = res.headers['login-type'];
        
        if (loginType === 'J') {
          this.handleJWTLogin(res);
        } else if (loginType === 'S') {
          this.handleSessionLogin(res);
        } else {
          alert("알 수 없는 로그인 방식입니다.");
          return;
        }

        await this.handleLoginSuccess();
        
      } catch (error) {
        alert(error.response?.data?.message || "로그인에 실패했습니다.");
      }
    },

    handleJWTLogin(res) {
      const token = res.headers.authorization;
      const userInfo = this.parseJWT(token);
      
      this.setAuthInfo("J", token, userInfo);
    },

    handleSessionLogin(res) {
      const userInfo = res.data;
      const roles = userInfo.roles.map(r => ({ authority: r.authrtCd }));
      
      this.setAuthInfo("S", null, { ...userInfo, roles });
    },

    parseJWT(token) {
      const base64String = token.split(".")[1];
      const base64 = base64String.replace(/-/g, "+").replace(/_/g, "/");
      const jsonPayload = decodeURIComponent(
        atob(base64).split("").map((c) => {
          return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
        }).join("")
      );
      return JSON.parse(jsonPayload);
    },

    setAuthInfo(loginMode, token, userInfo) {
      // Vuex 상태 저장
      store.commit("setLoginMode", loginMode);
      store.commit("setAuthorization", token);
      store.commit("setMbrId", userInfo.mbrId);
      store.commit("setMbrNm", userInfo.mbrNm);
      store.commit("setRoles", userInfo.roles);
      
      // localStorage 저장
      localStorage.setItem("loginMode", loginMode);
      localStorage.setItem("mbrId", userInfo.mbrId);
      localStorage.setItem("mbrNm", userInfo.mbrNm);
      localStorage.setItem("roles", JSON.stringify(userInfo.roles));
      
      if (token) {
        localStorage.setItem("authorization", token);
      } else {
        localStorage.removeItem("authorization");
      }
    },

    // ========== OAuth2 로그인 ==========
    fnOAuthLogin(provider) {
      const redirectUrl = this.restoreRedirect("redirect") || this.$route.fullPath;
      sessionStorage.setItem('oauth_redirect', redirectUrl);
      oauthLogin(provider);
    },

    async handleOAuthCallback() {
      const { error, errorMessage, oauthSuccess, loginMode } = this.parseOAuthParams();
      
      if (error) {
        this.handleOAuthError(error, errorMessage);
        return;
      }
      
      if (oauthSuccess !== 'true' && oauthSuccess !== true) return;
      
      try {
        store.commit("setLoginMode", loginMode || "J");
        localStorage.setItem("loginMode", loginMode || "J");
        
        if (loginMode === 'J') {
          await this.handleOAuthJWT();
        } else if (loginMode === 'S') {
          await this.handleOAuthSession();
        } else {
          throw new Error('알 수 없는 로그인 모드: ' + loginMode);
        }
        
        this.cleanupOAuth();
        await this.$nextTick();
        await this.handleLoginSuccess();
        
      } catch (error) {
        this.handleOAuthError('processing_error', error.message);
      }
    },

    parseOAuthParams() {
      const urlParams = new URLSearchParams(window.location.search);
      const routeQuery = this.$route.query;
      
      return {
        error: urlParams.get('error') || routeQuery.error,
        errorMessage: urlParams.get('message') || routeQuery.message,
        oauthSuccess: urlParams.get('oauth_success') || routeQuery.oauth_success,
        loginMode: urlParams.get('loginMode') || routeQuery.loginMode
      };
    },

    async handleOAuthJWT() {
      const oauthToken = this.getCookie('oauth_access_token');
      if (!oauthToken) {
        throw new Error('OAuth 토큰을 찾을 수 없습니다.');
      }
      
      const fullToken = oauthToken.startsWith('Bearer ') ? oauthToken : `Bearer ${oauthToken}`;
      store.commit("setAuthorization", fullToken);
      localStorage.setItem("authorization", fullToken);
      this.deleteCookie('oauth_access_token');
      
      try {
        const userInfo = this.parseJWT(fullToken.replace('Bearer ', ''));
        this.setAuthInfo("J", fullToken, userInfo);
      } catch (jwtError) {
        await this.fetchUserInfoFromServer();
      }
    },

    async handleOAuthSession() {
      store.commit("setAuthorization", null);
      localStorage.removeItem("authorization");
      this.deleteCookie('oauth_access_token');
      
      await this.fetchUserInfoFromServer();
    },

    async fetchUserInfoFromServer() {
      const userInfoRes = await getUserInfo();
      if (!userInfoRes || userInfoRes.status !== 200) {
        throw new Error('사용자 정보를 가져올 수 없습니다.');
      }
      
      const userInfo = userInfoRes.data.data;
      const roles = Array.isArray(userInfo.roles) ? 
        userInfo.roles.map(r => ({ authority: r.authrtCd || r.authority })) : 
        userInfo.roles;
      
      const loginMode = localStorage.getItem("loginMode");
      const token = userInfo.token || localStorage.getItem("authorization");
      
      this.setAuthInfo(loginMode, token, { ...userInfo, roles });
    },

    // ========== 로그인 성공 후 처리 ==========
    async handleLoginSuccess() {
      const isAdmin = store.state.roles.some(role => role.authority === "ROLE_ADMIN");
      let redirectUrl = this.restoreRedirect("redirect") || sessionStorage.getItem('oauth_redirect');
      
      // 리다이렉트 URL 정리
      if (redirectUrl && this.shouldRedirectToMain(redirectUrl)) {
        redirectUrl = this.$filters.ctxPath("/");
      }
      
      // Context Path 처리
      if (redirectUrl && !redirectUrl.startsWith(store.state.contextPath) && store.state.contextPath) {
        redirectUrl = this.$filters.ctxPath(redirectUrl);
      }
      
      // 라우터 존재 여부 확인 후 이동
      const targetPath = this.getValidRedirectPath(redirectUrl, isAdmin);
      await this.$nextTick();
      this.$router.push({ path: targetPath });
      
      // 세션 정리
      sessionStorage.removeItem("redirect");
      sessionStorage.removeItem("oauth_redirect");
    },

    shouldRedirectToMain(url) {
      return url.includes("/searchId.page") || 
             url.includes("/resetPswd.page") || 
             url.includes("/login.page");
    },

    getValidRedirectPath(redirectUrl, isAdmin) {
      if (redirectUrl) {
        const routeExists = this.$router.getRoutes().some(route => route.path === redirectUrl);
        if (routeExists) return redirectUrl;
      }
      
      return isAdmin ? 
        this.$filters.ctxPath("/adm/main.page") : 
        this.$filters.ctxPath("/");
    },

    // ========== 에러 처리 및 정리 ==========
    handleOAuthError(error, errorMessage) {
      this.isOAuthLoading = false;
      this.cleanupOAuth();
      
      const message = decodeURIComponent(errorMessage || error || 'OAuth 로그인에 실패했습니다.');
      alert(`소셜 로그인 실패: ${message}`);
      
      this.$router.push({ path: this.$filters.ctxPath("/login.page") });
    },

    cleanupOAuth() {
      sessionStorage.removeItem('oauth_redirect');
      sessionStorage.removeItem('oauth_provider');
      sessionStorage.removeItem('oauth_start_time');
      this.isOAuthLoading = false;
      
      const cleanUrl = window.location.pathname;
      window.history.replaceState({}, document.title, cleanUrl);
    },

    // ========== 유틸리티 메서드 ==========
    getCookie(name) {
      const value = `; ${document.cookie}`;
      const parts = value.split(`; ${name}=`);
      return parts.length === 2 ? parts.pop().split(';').shift() : null;
    },

    deleteCookie(name) {
      document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
    },

    moveSearchId() {
      this.$router.push({
        path: this.$filters.ctxPath("/resetPswd.page"),
        query: { tab: "id" }
      });
    },
    
    moveResetPswd() { 
      this.$router.push({
        path: this.$filters.ctxPath("/resetPswd.page"),
        query: { tab: "pw" }
      });
    }
  }
};
</script>