import * as React from 'react';
import {
  Box,
  Button,
  Typography,
  Divider,
  CircularProgress,
} from '@mui/material';
import { ResourceConfig } from '../types/config';
import { useUpload } from '../providers/UploadProvider';
import { useQueries } from '@tanstack/react-query';
import { useResource } from '../hooks/useResource';
import FormField from './fields/FormField';
import { ConfigContext } from '../App';

interface GenericFormProps {
  config: ResourceConfig;
  initialData?: any;
  onSave: (data: any) => Promise<void>;
  onCancel: () => void;
  loading?: boolean;
  readOnly?: boolean;
  onEditClick?: () => void;
}

export default function GenericForm({
  config,
  initialData = {},
  onSave,
  onCancel,
  loading: saving,
  readOnly = false,
  onEditClick,
}: GenericFormProps) {
  initialData = initialData || {};
  const [formData, setFormData] = React.useState(initialData);
  const { uploadFile, uploading } = useUpload();
  const appConfig = React.useContext(ConfigContext);

  // 1. Identify all unique relations in the schema (including nested ones)
  const getRelationFields = (fields: Record<string, any>): string[] => {
    let relations: string[] = [];
    Object.values(fields).forEach(field => {
      if (field.relation) relations.push(field.relation);
      if (field.schema) relations = [...relations, ...getRelationFields(field.schema)];
    });
    return Array.from(new Set(relations));
  };

  const allRelations = React.useMemo(() => getRelationFields(config.fields), [config.fields]);

  // 2. Parallel fetch for all related resource lists
  const queries = useQueries({
    queries: allRelations.map(relName => {
        const relatedRes = appConfig?.resources.find(r => r.name === relName);
        // eslint-disable-next-line react-hooks/rules-of-hooks
        const { getListQueryOptions } = useResource(relatedRes!);
        return {
            ...getListQueryOptions(),
            enabled: !!relatedRes,
        };
    }),
  });

  const isLoadingRelations = queries.some(q => q.isLoading);

  const relationDataMap = React.useMemo(() => {
    const map: Record<string, any[]> = {};
    allRelations.forEach((relName, index) => {
        map[relName] = queries[index].data || [];
    });
    return map;
  }, [allRelations, queries]);

  const handleChange = (key: string, value: any) => {
    if (readOnly) return;
    setFormData((prev: any) => ({ ...prev, [key]: value }));
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (readOnly) return;
    onSave(formData);
  };

  const getTitle = () => {
    if (readOnly) return `View ${config.label}`;
    return initialData[config.primaryKey] ? `Edit ${config.label}` : `New ${config.label}`;
  };

  if (isLoadingRelations) {
    return (
        <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', p: 8, gap: 2 }}>
            <CircularProgress />
            <Typography variant="body2" color="text.secondary">Loading relationships...</Typography>
        </Box>
    );
  }

  return (
    <Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
      <Typography variant="h5">
        {getTitle()}
      </Typography>
      <Divider />

      {Object.entries(config.fields).map(([key, field]) => (
        <FormField
          key={key}
          name={key}
          field={field}
          value={formData[key]}
          onChange={(val: any) => handleChange(key, val)}
          disabled={readOnly || field.readOnly}
          uploadFile={uploadFile}
          uploading={uploading}
          baseUrl={appConfig?.baseUrl || ""}
          relationDataMap={relationDataMap}
        />
      ))}

      <Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, mt: 4 }}>
        <Button variant="outlined" onClick={onCancel} disabled={saving}>
          {readOnly ? 'Back to List' : 'Cancel'}
        </Button>
        {readOnly ? (
            <Button variant="contained" color="primary" onClick={onEditClick}>
                Edit {config.label}
            </Button>
        ) : (
            <Button variant="contained" type="submit" loading={saving} disabled={saving || uploading}>
              Save {config.label}
            </Button>
        )}
      </Box>
    </Box>
  );
}
