import { defineStore } from 'pinia';
import { api } from 'boot/axios';
import { IRoles, IRolesDisplay, IUser, IUserDisplay, IUserRolesDisplay, IUserSubmit } from 'src/types/UserTypes';
import { Notify } from 'quasar'
import { IResponse } from 'src/types/BaseTypes';


export const useUserStore = defineStore('user', {
  state: () => ({
    users: [] as IUserRolesDisplay[],
    userIds: new Set<number>(),
    roles: [] as IRolesDisplay[],
  }),
  actions: {
    // -------------------------- users --------------------------
    async loadUsers() {
      this.reset('users');
      try {
        const { data } = await api.get<IResponse<IUser[]>>('api/v1/users');
        this.users = data.data.map((item) => {
          this.userIds.add(item.id);
          return userToUserRolesDisplay(item)
        }).sort((a, b) => a.id - b.id); // set default order
      } catch (error) {
        Notify.create({
          icon: 'error',
          color: 'negative',
          message: 'ユーザー一覧の読み込みに失敗しました'
        })
      }
    },

    getUserById(id: number) {
      if (!this.userIds.has(id)) {
        return null;
      }
      return this.users.find((item: IUserDisplay) => item.id === id);
    },

    async addUser(user: IUserSubmit) {
      return await api.post('api/v1/users', user);
    },

    async editUser(user: IUserSubmit) {
      const id = user.id;
      delete user['id']
      return await api.put(`api/v1/users/${id}`, user);
    },

    async deleteUser(userId: number) {
      try {
        await api.delete(`api/v1/users/${userId}`)
      } catch (error) {
        console.error(error);
        Notify.create({
          icon: 'error',
          color: 'negative',
          message: 'ユーザーの削除に失敗しました'
        });
        return false;
      }
      return true;
    },

    // -------------------------- roles --------------------------
    async loadRoles() {
      this.reset('roles');
      try {
        const { data } = await api.get<IResponse<IRoles[]>>('api/v1/roles');
        this.roles = data.data.map((item) => {
          return roleToRoleDisplay(item)
        }).sort((a, b) => a.id - b.id); // set default order
      } catch (error) {
        Notify.create({
          icon: 'error',
          color: 'negative',
          message: 'ロール一覧の読み込みに失敗しました'
        })
      }
    },

    async addRole(user: IUserRolesDisplay, role: IRolesDisplay) {
      return await this.updateUserRole(user, user.roleIds ? user.roleIds.concat(role.id) : [role.id]);
    },

    async removeRole(user: IUserRolesDisplay, role: IRolesDisplay) {
      return await this.updateUserRole(user, user.roleIds ? user.roleIds.filter(e => e !== role.id) : []);
    },

    async updateUserRole(user: IUserRolesDisplay, roleids: number[]) {
      return await api.post('api/v1/userrole', {
        userid: user.id,
        roleids
      });
    },

    reset(target?: 'users'|'roles') {
      if (!target) {
        this.reset('users');
        this.reset('roles');
        return;
      }
      if (target == 'roles') {
        this.roles = [];
      } else if (target == 'users') {
        this.users = [];
        this.userIds.clear();
      }
    },
  },
});

export function userToUserDisplay(user: IUser): IUserDisplay {
  return {
    id: user.id,
    firstName: user.first_name,
    lastName: user.last_name,
    fullNameSearch: (user.last_name + user.first_name).toLowerCase(),
    fullName: user.last_name + ' ' + user.first_name,
    email: user.email,
    isActive: user.is_active,
    isSuperuser: user.is_superuser,
  };
}

export function userToUserRolesDisplay(user: IUser): IUserRolesDisplay {
  if (!user) return {} as IUserRolesDisplay;
  const userRolesDisplay = userToUserDisplay(user) as IUserRolesDisplay;
  const roles: IRolesDisplay[] = [];
  const roleIds: number[] = [];
  user.roles.sort((a, b) => a.level - b.level).forEach((role) => {
    roles.push(roleToRoleDisplay(role));
    roleIds.push(role.id);
  });
  userRolesDisplay.roles = roles;
  userRolesDisplay.roleIds = roleIds;
  return userRolesDisplay;
}

export function roleToRoleDisplay(roles: IRoles): IRolesDisplay {
  return {
    id: roles.id,
    name: roles.description,
    key: roles.name,
    level: roles.level
  };
}