/**
 * Image Tools Page - Upload, filter, and download images
 * Supports chaining multiple filters with dynamic parameter schemas
 */
const ImageToolsPage = () => {
  const { 
    Box, Typography, Card, CardContent, Button, 
    Select, MenuItem, FormControl, InputLabel, Slider,
    CircularProgress, Alert, Chip, Paper, Checkbox, FormControlLabel
  } = MaterialUI;

  // State
  const [availableFilters, setAvailableFilters] = React.useState([]);
  const [filtersLoading, setFiltersLoading] = React.useState(true);
  const [selectedFile, setSelectedFile] = React.useState(null);
  const [previewUrl, setPreviewUrl] = React.useState(null);
  const [resultUrl, setResultUrl] = React.useState(null);
  const [selectedFilter, setSelectedFilter] = React.useState('');
  const [pendingParams, setPendingParams] = React.useState({});
  const [filterChain, setFilterChain] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState(null);

  // Fetch filter definitions from API on mount
  React.useEffect(() => {
    const fetchFilters = async () => {
      try {
        const response = await fetch('/image/filters');
        if (!response.ok) throw new Error('Failed to fetch filters');
        const filters = await response.json();
        setAvailableFilters(filters);
        if (filters.length > 0) {
          setSelectedFilter(filters[0].id);
          setPendingParams(getDefaultParams(filters[0]));
        }
      } catch (err) {
        setError('Failed to load filters: ' + err.message);
      } finally {
        setFiltersLoading(false);
      }
    };
    fetchFilters();
  }, []);

  // Get current filter config from dropdown
  const currentFilterConfig = availableFilters.find(f => f.id === selectedFilter);

  // Get default params for a filter
  const getDefaultParams = (filterDef) => {
    const defaults = {};
    (filterDef?.parameters || []).forEach(p => {
      defaults[p.id] = p.default;
    });
    return defaults;
  };

  // Check if a parameter should be visible based on showWhen condition
  const isParamVisible = (param, currentParams) => {
    if (!param.showWhen) return true;
    const { param: dependsOn, values } = param.showWhen;
    return values.includes(currentParams[dependsOn]);
  };

  // Handle filter selection change
  const handleFilterChange = (newFilterId) => {
    setSelectedFilter(newFilterId);
    const filterDef = availableFilters.find(f => f.id === newFilterId);
    setPendingParams(getDefaultParams(filterDef));
  };

  // Handle parameter value change
  const handleParamChange = (paramId, value) => {
    setPendingParams(prev => ({ ...prev, [paramId]: value }));
  };

  // Generate unique ID for filter chain items
  const generateUid = () => Date.now().toString(36) + Math.random().toString(36).substr(2);

  // Add filter to chain
  const handleAddFilter = () => {
    if (!currentFilterConfig) return;

    setFilterChain(prev => [...prev, {
      id: currentFilterConfig.id,
      name: currentFilterConfig.name,
      params: { ...pendingParams },
      uid: generateUid()
    }]);
  };

  // Remove filter from chain by uid
  const handleRemoveFilter = (uid) => {
    setFilterChain(prev => prev.filter(f => f.uid !== uid));
  };

  // Format filter label for display in chain
  const formatFilterLabel = (filter) => {
    const filterDef = availableFilters.find(f => f.id === filter.id);
    if (!filterDef || !filterDef.parameters || filterDef.parameters.length === 0) {
      return filter.name;
    }
    // Show key param values
    const paramValues = filterDef.parameters
      .filter(p => isParamVisible(p, filter.params))
      .map(p => {
        const val = filter.params[p.id];
        if (p.type === 'checkbox') return val ? p.label : null;
        if (p.type === 'slider') return `${p.label}: ${Number(val).toFixed(1)}`;
        return `${val}`;
      })
      .filter(Boolean)
      .slice(0, 2); // Show max 2 params
    return paramValues.length > 0 
      ? `${filter.name} (${paramValues.join(', ')})` 
      : filter.name;
  };

  // Render parameter input based on schema
  const renderParamInput = (param) => {
    if (!isParamVisible(param, pendingParams)) return null;

    const value = pendingParams[param.id];

    switch (param.type) {
      case 'slider':
        return (
          <Box key={param.id} sx={{ minWidth: 180, flex: 1, maxWidth: 250 }}>
            <Typography variant="body2" gutterBottom>
              {param.label}: {Number(value).toFixed(param.step < 1 ? 1 : 0)}
            </Typography>
            <Slider
              value={value}
              onChange={(e, v) => handleParamChange(param.id, v)}
              min={param.min}
              max={param.max}
              step={param.step}
              size="small"
            />
          </Box>
        );

      case 'dropdown':
        return (
          <FormControl key={param.id} size="small" sx={{ minWidth: 150 }}>
            <InputLabel>{param.label}</InputLabel>
            <Select
              value={value}
              label={param.label}
              onChange={(e) => handleParamChange(param.id, e.target.value)}
            >
              {param.options.map(opt => (
                <MenuItem key={opt.value} value={opt.value}>{opt.label}</MenuItem>
              ))}
            </Select>
          </FormControl>
        );

      case 'checkbox':
        return (
          <FormControlLabel
            key={param.id}
            control={
              <Checkbox
                checked={!!value}
                onChange={(e) => handleParamChange(param.id, e.target.checked)}
                size="small"
              />
            }
            label={param.label}
          />
        );

      default:
        return null;
    }
  };

  // Handle file selection
  const handleFileSelect = (event) => {
    const file = event.target.files[0];
    if (!file) return;

    // Validate file type
    const allowedTypes = ['image/png', 'image/jpeg', 'image/webp'];
    if (!allowedTypes.includes(file.type)) {
      setError('Please select a PNG, JPEG, or WebP image');
      return;
    }

    setSelectedFile(file);
    setError(null);
    setResultUrl(null);

    // Revoke old preview URL to free memory
    if (previewUrl) {
      URL.revokeObjectURL(previewUrl);
    }

    // Create new preview URL
    const url = URL.createObjectURL(file);
    setPreviewUrl(url);
  };

  // Handle drag and drop
  const handleDrop = (event) => {
    event.preventDefault();
    const file = event.dataTransfer.files[0];
    if (file) {
      handleFileSelect({ target: { files: [file] } });
    }
  };

  const handleDragOver = (event) => {
    event.preventDefault();
  };

  // Apply all filters in chain
  const handleApplyFilters = async () => {
    if (!selectedFile) {
      setError('Please select an image first');
      return;
    }

    if (filterChain.length === 0) {
      setError('Please add at least one filter to the chain');
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const formData = new FormData();
      formData.append('file', selectedFile);
      formData.append('filters', JSON.stringify(filterChain.map(f => ({
        filter: f.id,
        params: f.params
      }))));

      const response = await fetch('/image/apply-filters', {
        method: 'POST',
        body: formData
      });

      if (!response.ok) {
        const text = await response.text();
        throw new Error(text || 'Failed to process image');
      }

      // Get the processed image as a blob
      const blob = await response.blob();
      
      // Revoke old result URL
      if (resultUrl) {
        URL.revokeObjectURL(resultUrl);
      }

      // Create URL for the result
      const url = URL.createObjectURL(blob);
      setResultUrl(url);

    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  // Download result
  const handleDownload = () => {
    if (!resultUrl) return;

    const filterNames = filterChain.map(f => f.id).join('-');
    const link = document.createElement('a');
    link.href = resultUrl;
    link.download = `filtered-${filterNames}-${selectedFile?.name || 'image.png'}`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };

  // Cleanup URLs on unmount
  React.useEffect(() => {
    return () => {
      if (previewUrl) URL.revokeObjectURL(previewUrl);
      if (resultUrl) URL.revokeObjectURL(resultUrl);
    };
  }, []);

  return (
    <Box sx={{maxWidth: 1200, margin: '0 auto'}}>
      <Typography variant="h4" gutterBottom>
        Image Tools
      </Typography>
      <Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
        Upload an image, build a filter chain, and download the result.
      </Typography>

      {error && (
        <Alert severity="error" sx={{ mb: 2 }} onClose={() => setError(null)}>
          {error}
        </Alert>
      )}

      {/* Upload Area */}
      <Card sx={{ mb: 3 }}>
        <CardContent>
          <Typography variant="h6" gutterBottom>
            1. Select Image
          </Typography>
          <Box
            onDrop={handleDrop}
            onDragOver={handleDragOver}
            sx={{
              border: '2px dashed',
              borderColor: 'divider',
              borderRadius: 2,
              p: 4,
              textAlign: 'center',
              cursor: 'pointer',
              '&:hover': { borderColor: 'primary.main', bgcolor: 'action.hover' }
            }}
            onClick={() => document.getElementById('file-input').click()}
          >
            <input
              id="file-input"
              type="file"
              accept="image/png,image/jpeg,image/webp"
              onChange={handleFileSelect}
              style={{ display: 'none' }}
            />
            <Typography variant="body1" color="text.secondary">
              {selectedFile ? selectedFile.name : 'Click or drag an image here'}
            </Typography>
            <Typography variant="caption" color="text.secondary">
              Supports PNG, JPEG, WebP
            </Typography>
          </Box>
        </CardContent>
      </Card>

      {/* Filter Selection */}
      <Card sx={{ mb: 3 }}>
        <CardContent>
          <Typography variant="h6" gutterBottom>
            2. Build Filter Chain
          </Typography>
          
          {filtersLoading ? (
            <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
              <CircularProgress size={24} />
              <Typography>Loading filters...</Typography>
            </Box>
          ) : (
            <>
              {/* Add filter controls */}
              <Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap', alignItems: 'flex-start', mb: 2 }}>
                <FormControl sx={{ minWidth: 200 }} size="small">
                  <InputLabel>Filter</InputLabel>
                  <Select
                    value={selectedFilter}
                    label="Filter"
                    onChange={(e) => handleFilterChange(e.target.value)}
                  >
                    {availableFilters.map(f => (
                      <MenuItem key={f.id} value={f.id}>{f.name}</MenuItem>
                    ))}
                  </Select>
                </FormControl>

                {/* Dynamic parameter inputs */}
                {currentFilterConfig?.parameters?.map(param => renderParamInput(param))}

                <Button
                  variant="outlined"
                  onClick={handleAddFilter}
                  sx={{ height: 40 }}
                >
                  + Add Filter
                </Button>
              </Box>
            </>
          )}

          {/* Filter chain display */}
          {filterChain.length > 0 && (
            <Paper variant="outlined" sx={{ p: 2, mb: 2 }}>
              <Typography variant="subtitle2" gutterBottom>
                Filter Chain ({filterChain.length} filter{filterChain.length !== 1 ? 's' : ''}):
              </Typography>
              <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap', alignItems: 'center' }}>
                {filterChain.map((filter, index) => (
                  <React.Fragment key={filter.uid}>
                    {index > 0 && (
                      <Typography variant="body2" color="text.secondary">→</Typography>
                    )}
                    <Chip
                      label={formatFilterLabel(filter)}
                      onDelete={() => handleRemoveFilter(filter.uid)}
                      color="primary"
                      variant="outlined"
                    />
                  </React.Fragment>
                ))}
              </Box>
            </Paper>
          )}

          {/* Apply button */}
          <Button
            variant="contained"
            onClick={handleApplyFilters}
            disabled={!selectedFile || loading || filterChain.length === 0}
            sx={{ height: 40 }}
          >
            {loading ? <CircularProgress size={24} /> : 'Apply Filters'}
          </Button>
        </CardContent>
      </Card>

      {/* Preview and Result */}
      <Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
        {/* Original Preview */}
        {previewUrl && (
          <Card sx={{ flex: 1, minWidth: 300 }}>
            <CardContent>
              <Typography variant="h6" gutterBottom>
                Original
              </Typography>
              <Box
                component="img"
                src={previewUrl}
                alt="Original"
                sx={{
                  width: '100%',
                  maxHeight: 400,
                  objectFit: 'contain',
                  borderRadius: 1,
                  bgcolor: 'grey.100'
                }}
              />
            </CardContent>
          </Card>
        )}

        {/* Processed Result */}
        {resultUrl && (
          <Card sx={{ flex: 1, minWidth: 300 }}>
            <CardContent>
              <Typography variant="h6" gutterBottom>
                Result
              </Typography>
              <Box
                component="img"
                src={resultUrl}
                alt="Processed"
                sx={{
                  width: '100%',
                  maxHeight: 400,
                  objectFit: 'contain',
                  borderRadius: 1,
                  bgcolor: 'grey.100'
                }}
              />
              <Button
                variant="outlined"
                onClick={handleDownload}
                sx={{ mt: 2 }}
                fullWidth
              >
                Download Result
              </Button>
            </CardContent>
          </Card>
        )}
      </Box>
    </Box>
  );
};

// Expose globally for app.jsx
window.ImageToolsPage = ImageToolsPage;
