import { readonly, shallowRef, computed, type ShallowRef } from 'vue';

import {
  StudentGradeInDB, ResourceInDB, ResourceStoreMutationOp,
  type ClassroomResource, type TeacherResource, type StudentResource,
} from '../sharedworker/datastores/resourcestore';
import type { Database } from './database';
import { comparerByKey } from '../common/utils';


export type StudentGrade = StudentGradeInDB;
export type Resource = ClassroomResource | TeacherResource | (
  Omit<StudentResource, 'grade'> & { grade: StudentGrade }
);

export function studentGradeOrdering(studentGrade: StudentGrade) {
  return studentGrade.label;
}

export function resourceOrdering(resource: Resource) {
  const x = resource;
  return [['classroom', 'teacher', 'student'].indexOf(x.type), ...(
    x.type === 'classroom' ? [x.label] :
    x.type === 'teacher' ? [x.lastNameKana, x.firstNameKana] : [
      x.grade.label, x.lastNameKana, x.firstNameKana,
    ]
  )];
}

export function useResourceStore(database: Database) {
  const studentGrades = shallowRef<StudentGradeInDB[]>([]);
  const resources = shallowRef<ResourceInDB[]>([]);

  async function mutate(ops: ResourceStoreMutationOp[]) {
    return await database.mutate('resource', ops);
  }

  async function load() {
    const resp = await database.query('resource', {}) as {
      studentGrades: any[], resources: any[],
    };
    studentGrades.value = resp.studentGrades.map(x => ({
      id: x.id, label: x.label,
    })).sort(comparerByKey(studentGradeOrdering));
    resources.value = resp.resources.map(x => ({
      id: x.id, multiplicity: x.multiplicity, disabled: x.disabled,
      type: x.type, ...({
        classroom: { label: x.label },
        teacher: {
          firstName: x.firstName, lastName: x.lastName,
          firstNameKana: x.firstNameKana, lastNameKana: x.lastNameKana,
        },
        student: {
          firstName: x.firstName, lastName: x.lastName, grade: x.grade,
          firstNameKana: x.firstNameKana, lastNameKana: x.lastNameKana,
        },
      }[x.type])
    }));
  }

  return {
    studentGrades: computed<StudentGrade[]>(() => studentGrades.value.sort(
      comparerByKey(studentGradeOrdering)
    )),
    resources: computed<Resource[]>(() => resources.value.map(x => ({
      ...x, ...(x.type === 'student' ? { grade: studentGrades.value.find(
        g => g.id === x.grade
     )! } : {}),
    }) as Resource).sort(comparerByKey(resourceOrdering))),
    mutate, load,
  };
}

export type ResourceStore = Awaited<ReturnType<typeof useResourceStore>>;
