import { defineStore } from 'pinia';
import { api } from 'boot/axios';
import { router } from 'src/router';
import { IDomain, IDomainInfo } from '../types/DomainTypes';
import { jwtDecode } from 'jwt-decode';
import { useAppStore } from './useAppStore';
import { userToUserRolesDisplay, useUserStore } from './useUserStore';
import { IRolesDisplay, IUser, IUserRolesDisplay } from 'src/types/UserTypes';
import { IResponse } from 'src/types/BaseTypes';

interface IPermission {
  id: number,
  menu: string,
  function: string,
  privilege: string,
  link: string
}

type IPermissions = { [key: string]: string };

export interface IUserState {
  token?: string;
  returnUrl: string;
  currentDomain: IDomainInfo;
  LeftDrawer: boolean;
  userInfo: IUserRolesDisplay;
  tenant: string;
  permissions: IPermissions;
}

export const useAuthStore = defineStore('auth', {
  state: (): IUserState => ({
    token: '',
    returnUrl: '',
    LeftDrawer: false,
    currentDomain: {} as IDomainInfo,
    userInfo: {} as IUserRolesDisplay,
    tenant: '',
    permissions: {} as IPermissions
  }),
  getters: {
    userId(): number {
      return this.userInfo.id;
    },
    hasDomain(): boolean {
      return this.currentDomain.id !== undefined;
    },
    roles(): IRolesDisplay[] {
      return this.userInfo.roles;
    },
    isSuperAdmin(): boolean {
      return this.userInfo.isSuperuser;
    }
  },
  actions: {
    setLeftMenu(value:boolean){
      this.LeftDrawer=value;
    },
    toggleLeftMenu() {
      this.LeftDrawer = !this.LeftDrawer;
    },
    async login(username: string, password: string) {
      const params = new URLSearchParams();
      params.append('username', username);
      params.append('password', password);
      try {
        const result = await api.post('api/token', params);
        // console.info(result);
        this.token = result.data.access_token;
        const tokenJson = jwtDecode<{sub: number, tenant: string, roles: string}>(result.data.access_token);
        this.tenant = tokenJson.tenant;
        this.userInfo.id = tokenJson.sub;
        this.userInfo.isSuperuser = tokenJson.roles === 'super';
        api.defaults.headers['Authorization'] = 'Bearer ' + this.token;
        await Promise.all([
          this.loadCurrentDomain(),
          this.loadUserInfo(),
          this.loadPermission()
        ]);
        await router.push(this.returnUrl || '/');
        this.returnUrl = '';
        return true;
      } catch (e) {
        console.error(e);
        return false;
      }
    },
    async loadCurrentDomain() {
      const resp = await api.get<IResponse<IDomain>>('api/defaultdomain');
      const activedomain = resp?.data?.data;
      if (!activedomain) {
        this.currentDomain = {} as IDomainInfo;
      } else {
        this.currentDomain = {
          id: activedomain.id,
          domainName: activedomain.name,
          kintoneUrl: activedomain.url,
        };
      }
    },
    async loadUserInfo() {
      const resp = (await api.get<IResponse<IUser>>('api/v1/users/me'))?.data?.data;
      this.userInfo = userToUserRolesDisplay(resp)
    },
    async loadPermission() {
      this.permissions = {} as IPermissions;
      if (this.isSuperAdmin) return;
      const resp = (await api.get<IResponse<IPermission[]>>('api/v1/userpermssions')).data.data;
      resp.forEach((permission) => {
        this.permissions[permission.link] = permission.menu;
        this.permissions[permission.privilege] = permission.function;
      });
    },
    async logout() {
      this.token = '';
      this.currentDomain = {} as IDomainInfo; // 清空当前域
      useAppStore().reset();
      useUserStore().reset();
      await router.push('/login');
      this.tenant = '';
      this.userInfo = {} as IUserRolesDisplay;
      this.permissions = {} as IPermissions;
    },
    async setCurrentDomain(domain?: IDomainInfo) {
      if (!domain) {
        this.currentDomain = {} as IDomainInfo;
        return;
      }
      if (domain.id === this.currentDomain.id) {
        return;
      }
      await api.put(`api/defaultdomain/${domain.id}`);
      this.currentDomain = domain;
    },
  },
  persist: {
    afterRestore: (ctx) => {
      api.defaults.headers['Authorization'] = 'Bearer ' + ctx.store.token;

      //axios例外キャプチャー
      api.interceptors.response.use(
        (response) => response,
        (error) => {
          if (error.response && error.response.status === 401) {
            // 認証エラーの場合再ログインする
            console.error('(; ﾟДﾟ)/認証エラー(401)：', error);
            ctx.store.logout();
          }
          return Promise.reject(error);
        }
      );
    },
  },
});
