import { Store } from 'pinia'
import {AnyJson} from "~/types/enum/data";
import {
  ABILITIES,
  GENDER,
  TYPE_ALERT,
} from '~/types/enum/enums'
import {Ref} from "@vue/reactivity";
import {MenuGroup, MenuItem} from "~/types/layout";

declare module '@vuex-orm/core' {
  interface Query {
    getAllRelations: () => Array<string>
  }
}

interface AbilitiesType {
  action: ABILITIES

  subject: string
  /** an array of fields to which user has (or not) access */
  fields?: string[]
  /** an object of conditions which restricts the rule scope */
  conditions?: any
  /** indicates whether rule allows or forbids something */
  inverted?: boolean
  /** message which explains why rule is forbidden */
  reason?: string
}

interface Alert {
  type: TYPE_ALERT
  messages: Array<string>
}

type AnyStore = Store<any>

interface EnumChoice {
  value: string
  label: string
}

interface Filter {
  readonly key: string
  readonly value: string | boolean | number
}

type EnumChoices = Array<EnumChoice>

interface HookProvider {
  invoke(args: DataProviderArgs): Promise<any>
}
interface HookPersister {
  invoke(args: DataPersisterArgs): Promise<any>
}
interface HookDeleter {
  invoke(args: DataDeleterArgs): Promise<any>
}

interface Processor {
  process(data: AnyJson): Promise<any>
}

interface Encoder {
  encode(data: AnyJson): string
  decode(input: string): AnyJson
}
interface Historical {
  future: boolean
  past: boolean
  present: boolean
  dateStart?: string | null
  dateEnd?: string | null
}

interface BaseAccessProfile {
  id: number | null
  name: string | null
  givenName: string | null
  gender: GENDER | null
  avatarId: number | null
}

interface BaseOrganizationProfile {
  id: number | null
  name: string | null
  website?: string | null
}

interface OrignalAccessProfile extends BaseAccessProfile {
  isSuperAdminAccess: boolean
  organization: BaseOrganizationProfile
}

interface AccessProfile extends BaseAccessProfile {
  bearer: string | null
  switchId: number | null
  activityYear: number | null
  historical: Historical | Array<string>
  roles: Array<string>
  abilities: Array<AbilitiesType>
  isAdminAccess: boolean | null
  isSuperAdminAccess: boolean | null
  isAdmin: boolean | null
  isAdministratifManager: boolean | null
  isPedagogicManager: boolean | null
  isFinancialManager: boolean | null
  isCaMember: boolean | null
  isStudent: boolean | null
  isTeacher: boolean | null
  isMember: boolean | null
  isOther: boolean | null
  isGuardian: boolean | null
  isPayer: boolean | null
  multiAccesses: Array<BaseOrganizationProfile>
  familyAccesses: Array<BaseAccessProfile>
  originalAccess: OrignalAccessProfile | null
}

// TODO: y'a un problème entre l'interface AccessProfile et celle organizationState, les noms sont construits différemment,
//       il faut tout remettre sur le même modèle
interface organizationState extends BaseOrganizationProfile {
  id: number | null
  parametersId: number | null
  name: string | null
  product?: string | null
  currentActivityYear?: number | null
  modules?: Array<string>
  hasChildren?: boolean | null
  showAdherentList?: boolean | null
  legalStatus?: string | null
  networks: Array<string>
  parents: Array<BaseOrganizationProfile>
}

interface DolibarrContractLine {
  id: number
  contractId: number
  dateStart: Date
  dateEnd: Date
  serviceRef: string
  serviceLabel: string
}

interface DolibarrContract {
  ref: string
  socId: number
  lines: Array<DolibarrContractLine>
}

interface DolibarrBill {
  id: number
  ref: string
  socId: number
  date: Date
  taxExcludedAmount: number
  taxIncludedAmount: number
  paid: boolean
}

interface DolibarrAccount {
  organizationId: number
  socId: number
  clientNumber: string
  product:
      | 'PRODUCT_ARTIST'
      | 'PRODUCT_ARTIST_PREMIUM'
      | 'PRODUCT_SCHOOL'
      | 'PRODUCT_SCHOOL_PREMIUM'
      | 'PRODUCT_MANAGER'
  contract: DolibarrContract
  bills: Array<DolibarrBill>
}

interface MobytUserStatus {
  organizationId: number
  active: boolean
  amount: number
  money: number
}

interface MercureEntityUpdate {
  iri: string
  operation: 'create' | 'delete' | 'update'
  data: any
}

interface SseState {
  connected: boolean
  events: Array<MercureEntityUpdate>
}

interface LayoutState {
  menus: Record<string, MenuGroup | MenuItem>
  menusOpened: Record<string, boolean>
}
