import { useEffect, useState } from "react";
import { jsonschemaProvider } from "../providers/jsonschema-provider";
import { GridColDef, GridColumnVisibilityModel, GridValidRowModel } from "@mui/x-data-grid";

type ResourceSchemaType = "create" | "update" | "card";

export function useResourceSchema(schemaName: string, type: ResourceSchemaType) {
  const [schema, setSchema] = useState({});
  const [schemaLoading, setSchemaLoading] = useState(true);

  useEffect(() => {
    const fetchSchema = async () => {
      try {
        let resourceSchema
        if (type == "create") {
          resourceSchema = await jsonschemaProvider.getCreateResourceSchema(schemaName);
        } else if (type == "card") {
          resourceSchema = await jsonschemaProvider.getCardResourceSchema(schemaName);
        } else {
          resourceSchema = await jsonschemaProvider.getUpdateResourceSchema(schemaName);
        }
        setSchema(resourceSchema);
        setSchemaLoading(false);
      } catch (error) {
        console.error(`Error while retrieving schema: ${schemaName} `, error);
        setSchemaLoading(false);
      }
    };
    fetchSchema();
  }, []);

  return { schema, schemaLoading }
}

type ColumnSchema<T extends GridValidRowModel> = {
  columns: GridColDef<T>[],
  columnVisibilityModel: GridColumnVisibilityModel
}

type ColumnDefinition = {
  field: string,
  column: Partial<GridColDef>,
  hide?: boolean
}

export function useResourceColumns<T extends GridValidRowModel>(schemaName: string, columnDefinitions: ColumnDefinition[]) {
  const [columnSchema, setColumnSchema] = useState<ColumnSchema<T>>()
  const [columnLoading, setColumnLoading] = useState(true);
  useEffect(() => {
    const fetchSchema = async () => {
      try {
        const resourceColumns = await jsonschemaProvider.getReadResourceColumns(schemaName)
        const definedColumns = computeColumnSchema<T>(columnDefinitions, resourceColumns)
        setColumnSchema(definedColumns);
        setColumnLoading(false);
      } catch (error) {
        console.error('Error while retrieving columns schema:', error);
        setColumnLoading(false);
      }
    };
    fetchSchema();
  }, []);

  return { columnSchema, columnLoading }
}

function computeColumnSchema<T extends GridValidRowModel>(definitionColumns: ColumnDefinition[], resourceColumns: GridColDef[]): ColumnSchema<T> {
  //reorder resourceColumns as in definition
  definitionColumns.slice().reverse().forEach(first => {
     resourceColumns.sort(function(x,y){ return x.field == first.field ? -1 : y.field == first.field ? 1 : 0; });
  })

  let visibilityModel: GridColumnVisibilityModel = {}
  resourceColumns.forEach((resource, index) =>{
    visibilityModel[resource.field] = definitionColumns.some(col => col.field == resource.field && !col.hide)
    definitionColumns.forEach((def) => {
      if (def.field == resource.field) {
        resourceColumns[index] = {...resource, ...def.column};
      }
    })
  })

  return {
    columns: resourceColumns,
    columnVisibilityModel: visibilityModel
  }
}

export function useResourceFilter(resourceName: string, resourcePath: string) {
  const [hasSearch, setHasSearch] = useState(false)
  const [filtersSchema, setFiltersSchema] = useState<any[]>([])
  const [filtersLoading, setFiltersLoading] = useState(true);
  useEffect(() => {
    const fetchSchema = async () => {
      try {
        setHasSearch(await jsonschemaProvider.hasSearch(resourcePath))
        const resourceFilters = await jsonschemaProvider.getListFilters(resourceName, resourcePath)
        setFiltersSchema(resourceFilters);
        setFiltersLoading(false);
      } catch (error) {
        console.error('Error while retrieving filter schema:', error);
        setFiltersLoading(false);
      }
    };
    fetchSchema();
  }, []);

  return { hasSearch, filtersSchema, filtersLoading }
}
