import React, { useEffect, useMemo, useState } from 'react';
import { experimentsApi } from '../api/client';
import Button from './ui/Button';
import Alert from './ui/Alert';
import { listExportableParams, buildSubjectSeriesMatrix, toCSV, csvFilename } from '../lib/dataExport';

const PARAM_GROUP_LABELS = { metrics: 'Session metrics', daily: 'Daily record fields' };

function triggerDownload(filename, text) {
  const blob = new Blob([text], { type: 'text/csv;charset=utf-8;' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 0);
}

export default function ExportDataModal({
  experimentTitle, experimentId, dailyTemplate, animals, subjectTemplate = [], groupField = '__none__', onClose,
}) {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [statuses, setStatuses] = useState([]);

  const [xField, setXField] = useState('__date__');
  const [dataId, setDataId] = useState(null);
  const [groupBy, setGroupBy] = useState(() => {
    const valid = groupField === '__none__' || groupField === '__name__' || groupField === '__id__'
      || subjectTemplate.some((f) => f.active && f.fieldId === groupField);
    return valid ? groupField : '__none__';
  });

  useEffect(() => {
    let alive = true;
    setLoading(true);
    setError(null);
    experimentsApi.getDailyStatuses(experimentId, {})
      .then((data) => { if (alive) setStatuses(data); })
      .catch((err) => { if (alive) setError(err.message); })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [experimentId]);

  const params = useMemo(() => listExportableParams(dailyTemplate ?? [], statuses), [dailyTemplate, statuses]);
  const effDataId = dataId ?? params[0]?.id ?? null;
  const dataParam = params.find((p) => p.id === effDataId) ?? params[0] ?? null;

  const activeDaily = useMemo(() => (dailyTemplate ?? []).filter((f) => f.active), [dailyTemplate]);
  const xOptions = useMemo(() => [
    { id: '__date__', label: 'Date' },
    { id: '__days__', label: '# Days Reach (ordinal)' },
    ...activeDaily.map((f) => ({ id: f.fieldId, label: f.label })),
  ], [activeDaily]);

  const matrix = useMemo(
    () => (dataParam
      ? buildSubjectSeriesMatrix({ xField, dataParam, groupField: groupBy }, { statuses, animals, dailyTemplate })
      : { columns: [], rows: [], context: { label: 'Data', value: '' }, corner: '', groupAxis: null }),
    [xField, dataParam, groupBy, statuses, animals, dailyTemplate],
  );
  const hasData = matrix.rows.length > 0;

  const groupedParams = useMemo(() => {
    const out = [];
    for (const p of params) {
      let g = out.find((x) => x.group === p.group);
      if (!g) { g = { group: p.group, items: [] }; out.push(g); }
      g.items.push(p);
    }
    return out;
  }, [params]);

  function handleExport() {
    if (!hasData || !dataParam) return;
    triggerDownload(csvFilename(experimentTitle, dataParam.label), toCSV(matrix));
    onClose();
  }

  if (loading) return <p className="text-sm text-gray-400" aria-live="polite">Loading data…</p>;
  if (error) return (
    <div className="space-y-4">
      <Alert type="error" message={error} />
      <div className="flex justify-end"><Button variant="secondary" onClick={onClose}>Close</Button></div>
    </div>
  );

  const selectCls = 'w-full border border-gray-200 rounded px-2 py-1.5 text-sm bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400';

  return (
    <div className="space-y-4">
      <p className="text-sm text-gray-500">
        One value per subject over an X axis — each column is a subject, each row an X value. Blank where a subject has no value.
      </p>

      <div>
        <label htmlFor="export-x" className="block text-xs font-medium text-gray-500 mb-1">X axis (rows)</label>
        <select id="export-x" value={xField} onChange={(e) => setXField(e.target.value)} className={selectCls}>
          {xOptions.map((o) => <option key={o.id} value={o.id}>{o.label}</option>)}
        </select>
      </div>

      <div>
        <label htmlFor="export-data" className="block text-xs font-medium text-gray-500 mb-1">Data (cells)</label>
        <select id="export-data" value={effDataId ?? ''} onChange={(e) => setDataId(e.target.value)} className={selectCls}>
          {groupedParams.map((g) => (
            <optgroup key={g.group} label={PARAM_GROUP_LABELS[g.group] ?? g.group}>
              {g.items.map((p) => <option key={p.id} value={p.id}>{p.label}</option>)}
            </optgroup>
          ))}
        </select>
      </div>

      <div>
        <label htmlFor="export-group" className="block text-xs font-medium text-gray-500 mb-1">Group by</label>
        <select id="export-group" value={groupBy} onChange={(e) => setGroupBy(e.target.value)} className={selectCls}>
          <option value="__none__">— None —</option>
          <option value="__name__">Name</option>
          <option value="__id__">Subject ID</option>
          {subjectTemplate.filter((f) => f.active).map((f) => (
            <option key={f.fieldId} value={f.fieldId}>{f.label}</option>
          ))}
        </select>
      </div>

      <p className="text-xs text-gray-400">
        {hasData
          ? `${matrix.rows.length} row${matrix.rows.length !== 1 ? 's' : ''} × ${matrix.columns.length} subject${matrix.columns.length !== 1 ? 's' : ''}`
          : 'No data for this selection yet.'}
      </p>

      <div className="flex justify-end gap-2 pt-2">
        <Button variant="secondary" onClick={onClose}>Cancel</Button>
        <Button onClick={handleExport} disabled={!hasData}>Export CSV</Button>
      </div>
    </div>
  );
}
