import * as React from 'react';
import { Box, Paper, CircularProgress } from '@mui/material';
import { ResourceConfig } from '../types/config';
import type { ResourceField } from '../types/config';
import { FieldComponents } from '../types/overrides';
import { useResource } from '../hooks/useResource';
import { resolveTemplate } from '../utils/options';
import EnhancedTable from './EnhancedTable';
import FilterBar from './FilterBar';
import { useParams, useLocation, useNavigate } from 'react-router-dom';

interface ResourceViewProps {
  config: ResourceConfig;
  onNavigateToResource?: (resourceName: string, id: string) => void;
  fieldComponents: FieldComponents;
}

import { GridPaginationModel } from '@mui/x-data-grid';

function getDisplayString(item: any, field: ResourceField): string {
  if (item == null || typeof item !== 'object') return String(item ?? '');
  if (field.enumOption?.value) return resolveTemplate(field.enumOption.value, item);
  if (field.displayFormat) return resolveTemplate(field.displayFormat, item);
  throw new Error('cannot get display string')
}

function applyClientFilters(
  data: any[],
  filters: Record<string, any>,
  fields: Record<string, ResourceField>
): any[] {
  const entries = Object.entries(filters).filter(([_, v]) => {
    if (v == null || v === "" || (Array.isArray(v) && v.length === 0)) return false;
    if (typeof v === "object" && !Array.isArray(v) && Object.values(v).every((x) => x == null || x === "")) return false;
    return true;
  });

  if (entries.length === 0) return data;

  return data.filter((item) =>
    entries.every(([fieldName, filterValue]) => {
      const field = fields[fieldName];
      if (!field) return true;

      const itemValue = item[fieldName];

      if (typeof filterValue === "object" && !Array.isArray(filterValue)) {
        if (field.type === "number") {
          if (filterValue.min != null && filterValue.min !== "" && Number(itemValue) < Number(filterValue.min)) return false;
          if (filterValue.max != null && filterValue.max !== "" && Number(itemValue) > Number(filterValue.max)) return false;
          return true;
        }
        if (field.type === "datetime" || field.type === "date") {
          const itemTime = new Date(itemValue).getTime();
          if (filterValue.start && new Date(filterValue.start).getTime() > itemTime) return false;
          if (filterValue.end && new Date(filterValue.end).getTime() < itemTime) return false;
          return true;
        }
        return true;
      }

      if (Array.isArray(filterValue)) {
        if (field.type === "array" && Array.isArray(itemValue)) {
          return itemValue.some((el: any) =>
            filterValue.includes(getDisplayString(el, field))
          );
        }
        if (itemValue && typeof itemValue === "object") {
          return filterValue.includes(getDisplayString(itemValue, field));
        }
        return filterValue.includes(String(itemValue));
      }

      if (!filterValue) return true;

      if (field.type === "boolean") {
        return String(itemValue) === filterValue;
      }

      if (field.type === "array" && Array.isArray(itemValue)) {
        return itemValue.some((el: any) =>
          getDisplayString(el, field) === String(filterValue)
        );
      }

      if (itemValue && typeof itemValue === "object") {
        return getDisplayString(itemValue, field) === String(filterValue);
      }

      return String(itemValue) === String(filterValue);
    })
  );
}

export default function ResourceView({ config, onNavigateToResource, fieldComponents }: ResourceViewProps) {
  const { id } = useParams();
  const location = useLocation();
  const navigate = useNavigate();

  const isCreate = location.pathname.endsWith('/create');
  const isEdit = location.pathname.includes('/edit/');
  const isView = !!id && !isEdit;
  const isList = !id && !isCreate;

  const isServer = config.filterOptions?.mode !== "client";

  const [paginationModel, setPaginationModel] = React.useState<GridPaginationModel>({
    page: 0,
    pageSize: 10,
  });

  const [appliedFilters, setAppliedFilters] = React.useState<Record<string, any>>({});

  const { useList, useRead, useCreate, useUpdate, useDelete, components } = useResource(config, { fieldComponents });

  const queryParams = React.useMemo(() => {
    if (!isServer) return { limit: 10000 };
    return {
      skip: paginationModel.page * paginationModel.pageSize,
      limit: paginationModel.pageSize,
    };
  }, [isServer, paginationModel]);

  const listQuery = useList(queryParams);
  const itemQuery = useRead(id || "");

  const rawData = listQuery.data?.data || [];
  const totalCount = listQuery.data?.total;

  const filteredData = React.useMemo(
    () => (isServer ? rawData : applyClientFilters(rawData, appliedFilters, config.fields)),
    [isServer, rawData, appliedFilters, config.fields]
  );

  const createMutation = useCreate();
  const updateMutation = useUpdate();
  const deleteMutation = useDelete();

  const handleEdit = (item: any) => {
    navigate(`/admin/${config.name}/edit/${item[config.primaryKey]}`);
  };

  const handleCreate = () => {
    navigate(`/admin/${config.name}/create`);
  };

  const handleSave = async (formData: any) => {
    try {
      if (isEdit) {
        await updateMutation.mutateAsync({ id: id!, data: formData });
      } else {
        await createMutation.mutateAsync(formData);
      }
      navigate(`/admin/${config.name}`);
    } catch (err) {
      console.error('Save failed:', err);
    }
  };

  const handleDelete = async (itemId: string) => {
    if (window.confirm('Are you sure you want to delete this item?')) {
      await deleteMutation.mutateAsync(itemId);
    }
  };

  if (isList && listQuery.isLoading) return <CircularProgress />;
  if ((isEdit || isView) && itemQuery.isLoading) return <CircularProgress />;

  return (
    <Box>
      {isList ? (
        <Box>
          {!isServer && config.filterOptions?.fields && config.filterOptions.fields.length > 0 && (
            <FilterBar
              fields={config.fields}
              filterableFields={config.filterOptions.fields}
              mode={config.filterOptions?.mode || "server"}
              data={rawData}
              appliedValues={appliedFilters}
              onApply={setAppliedFilters}
              onClear={() => setAppliedFilters({})}
              fieldComponents={components}
            />
          )}
          <EnhancedTable
            config={config}
            data={filteredData}
            total={isServer ? totalCount : filteredData.length}
            paginationModel={isServer ? paginationModel : undefined}
            onPaginationModelChange={isServer ? setPaginationModel : undefined}
            loading={listQuery.isFetching}
            onEdit={handleEdit}
            onDelete={handleDelete}
            onCreate={handleCreate}
            onNavigateToResource={(res, id) => navigate(`/admin/${res}/${id}`)}
          />
        </Box>
      ) : (
        <Paper sx={{ p: 4 }}>
          {components && <components.GenericForm
            config={config}
            initialData={isCreate ? null : itemQuery.data}
            onSave={handleSave}
            onCancel={() => navigate(`/admin/${config.name}`)}
            loading={createMutation.isPending || updateMutation.isPending}
            readOnly={isView}
            onEditClick={() => navigate(`/admin/${config.name}/edit/${id}`)}
          />}
        </Paper>
      )}
    </Box>
  );
}
