import React, { useEffect, useState, useMemo } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { experimentsApi, animalsApi } from '../api/client';
import { ExperimentAnalysisCharts } from '../components/AnalysisCharts';
import Button from '../components/ui/Button';
import Modal from '../components/ui/Modal';
import AnimalForm from '../components/AnimalForm';
import TemplateEditor from '../components/TemplateEditor';
import Alert from '../components/ui/Alert';
import AuditLogSection from '../components/AuditLogSection';
import ExperimentCalendar from '../components/ExperimentCalendar';
import ExportDataModal from '../components/ExportDataModal';

function AnimalCardList({ animals, subjectTemplate, onNavigate, onEdit }) {
  return (
    <div className="grid gap-3">
      {animals.map((animal) => {
        const infoFields = subjectTemplate.filter((f) => f.active && animal.subject_info?.[f.fieldId] != null);
        return (
          <div
            key={animal.id}
            className="bg-white border border-gray-200 rounded-xl p-4 flex items-center justify-between hover:border-blue-300 hover:shadow-sm transition-all cursor-pointer group"
            onClick={() => onNavigate(animal)}
          >
            <div>
              <div className="font-semibold text-gray-900 group-hover:text-blue-700 transition-colors">
                {animal.animal_name}
              </div>
              <div className="text-sm text-gray-500">
                ID: {animal.animal_id_string} · {animal._count?.daily_statuses ?? 0} daily status entries
              </div>
              {infoFields.length > 0 && (
                <div className="flex flex-wrap gap-x-3 gap-y-0.5 mt-1">
                  {infoFields.map((f) => (
                    <span key={f.fieldId} className="text-xs text-gray-400">
                      <span className="font-medium text-gray-500">{f.label}:</span> {animal.subject_info[f.fieldId]}
                    </span>
                  ))}
                </div>
              )}
            </div>
            <div className="flex gap-2" onClick={(e) => e.stopPropagation()}>
              <Button size="sm" variant="secondary" onClick={() => onEdit(animal)}>Edit</Button>
            </div>
          </div>
        );
      })}
    </div>
  );
}

export default function ExperimentDetail() {
  const { id } = useParams();
  const navigate = useNavigate();

  const [experiment, setExperiment] = useState(null);
  const [animals, setAnimals] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [successMsg, setSuccessMsg] = useState(null);

  const [showAddAnimal, setShowAddAnimal] = useState(false);
  const [editAnimal, setEditAnimal] = useState(null);
  const [showTemplate, setShowTemplate] = useState(false);
  const [showSubjectTemplate, setShowSubjectTemplate] = useState(false);
  const [showExport, setShowExport] = useState(false);
  const [subjectTemplate, setSubjectTemplate] = useState([]);
  const [dailyTemplate, setDailyTemplate] = useState([]);
  const [experimentStatuses, setExperimentStatuses] = useState([]);

  const [displayMode, setDisplayMode] = useState(() => localStorage.getItem(`exp-display-mode-${id}`) ?? 'list');
  const [sortField,   setSortField]   = useState(() => localStorage.getItem(`exp-subject-sort-${id}`) ?? '__name__');
  const [sortDir,     setSortDir]     = useState(() => localStorage.getItem(`exp-subject-sort-dir-${id}`) ?? 'asc');
  const [groupField,  setGroupField]  = useState(() => localStorage.getItem(`exp-subject-group-${id}`) ?? '__name__');

  function updateDisplayMode(mode) {
    setDisplayMode(mode);
    localStorage.setItem(`exp-display-mode-${id}`, mode);
  }
  function updateSort(field, dir) {
    setSortField(field);
    setSortDir(dir);
    localStorage.setItem(`exp-subject-sort-${id}`, field);
    localStorage.setItem(`exp-subject-sort-dir-${id}`, dir);
  }
  function updateGroupField(field) {
    setGroupField(field);
    localStorage.setItem(`exp-subject-group-${id}`, field);
  }

  async function load() {
    setLoading(true);
    setError(null);
    try {
      const [exp, anims, subjTmpl, dailyTmpl, expStatuses] = await Promise.all([
        experimentsApi.get(id),
        animalsApi.list(id),
        experimentsApi.getSubjectTemplate(id),
        experimentsApi.getTemplate(id),
        // Only fetch statuses that have saved analysis_summary — charts are the only consumer,
        // and they filter for analysis_summary.total != null anyway.
        experimentsApi.getDailyStatuses(id, { analysisOnly: true }),
      ]);
      setExperiment(exp);
      setAnimals(anims);
      setSubjectTemplate(subjTmpl);
      setDailyTemplate(dailyTmpl);
      setExperimentStatuses(expStatuses);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => { load(); }, [id]);

  function flash(msg) {
    setSuccessMsg(msg);
    setTimeout(() => setSuccessMsg(null), 3000);
  }

  function handleAnimalSaved(animal) {
    setShowAddAnimal(false);
    setEditAnimal(null);
    load();
    flash(editAnimal ? `Animal "${animal.animal_name}" updated.` : `Animal "${animal.animal_name}" added.`);
  }

  function handleTemplateSaved(updatedTemplate) {
    setShowTemplate(false);
    if (updatedTemplate) {
      // Update local experiment state so everything downstream re-renders
      setExperiment((prev) => ({ ...prev, template: updatedTemplate }));
      flash('Record template updated.');
    }
  }

  const sortedAnimals = useMemo(() => {
    const sorted = [...animals].sort((a, b) => {
      let av, bv;
      if (sortField === '__name__') {
        av = a.animal_name ?? '';
        bv = b.animal_name ?? '';
      } else if (sortField === '__id__') {
        av = a.animal_id_string ?? '';
        bv = b.animal_id_string ?? '';
      } else {
        av = a.subject_info?.[sortField] ?? '';
        bv = b.subject_info?.[sortField] ?? '';
      }
      // numeric-aware comparison
      const an = parseFloat(av), bn = parseFloat(bv);
      const cmp = (!isNaN(an) && !isNaN(bn)) ? an - bn : String(av).localeCompare(String(bv));
      return sortDir === 'asc' ? cmp : -cmp;
    });
    return sorted;
  }, [animals, sortField, sortDir, subjectTemplate]);

  // Group mode: bucket sortedAnimals by the groupField value
  const groupedAnimals = useMemo(() => {
    if (displayMode !== 'group') return null;
    const getVal = (animal) => {
      if (groupField === '__name__') return animal.animal_name ?? '—';
      if (groupField === '__id__')   return animal.animal_id_string ?? '—';
      const v = animal.subject_info?.[groupField];
      return v != null && v !== '' ? String(v) : '—';
    };
    const buckets = new Map();
    for (const animal of sortedAnimals) {
      const key = getVal(animal);
      if (!buckets.has(key)) buckets.set(key, []);
      buckets.get(key).push(animal);
    }
    // Sort bucket keys numerically-aware
    return [...buckets.entries()].sort(([a], [b]) => {
      const an = parseFloat(a), bn = parseFloat(b);
      return (!isNaN(an) && !isNaN(bn)) ? an - bn : a.localeCompare(b);
    });
  }, [sortedAnimals, displayMode, groupField]);

  if (loading) return <div className="max-w-5xl mx-auto px-4 py-8 text-gray-400" aria-live="polite" aria-busy="true">Loading…</div>;
  if (error) return (
    <div className="max-w-5xl mx-auto px-4 py-8">
      <Alert type="error" message={error} />
      <Button variant="secondary" className="mt-4" onClick={() => navigate('/')}>← Back</Button>
    </div>
  );

  return (
    <div className="max-w-5xl mx-auto px-4 py-8">
      {/* Breadcrumb */}
      <nav className="text-sm text-gray-500 mb-4">
        <Link to="/" className="hover:text-blue-600">Experiments</Link>
        <span className="mx-2">/</span>
        <span className="text-gray-900 font-medium">{experiment.title}</span>
      </nav>

      <div className="flex items-start justify-between mb-6">
        <div>
          <h1 className="text-2xl font-bold text-gray-900">{experiment.title}</h1>
          <p className="text-sm text-gray-500 mt-0.5">
            {animals.length} animal{animals.length !== 1 ? 's' : ''} enrolled
          </p>
        </div>
        <div className="flex gap-2">
          <Button variant="secondary" onClick={() => setShowExport(true)}>Export data</Button>
          <Button onClick={() => setShowAddAnimal(true)}>+ Add Animal</Button>
        </div>
      </div>

      {successMsg && <Alert type="success" message={successMsg} />}
      {error && <Alert type="error" message={error} onDismiss={() => setError(null)} />}

      {/* Template strips */}
      <div className="mb-5 space-y-2">
        {/* Daily record template */}
        <div className="flex flex-wrap items-center gap-1.5">
          <span className="text-xs font-semibold text-gray-400 uppercase tracking-wide w-24 shrink-0">Daily record</span>
          {(experiment.template ?? []).map((f) => (
            <span
              key={f.key}
              className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border ${
                f.active ? 'bg-blue-50 border-blue-200 text-blue-700' : 'bg-gray-100 border-gray-200 text-gray-400'
              }`}
            >
              {f.active ? null : <span title="hidden">◌</span>}
              {f.label}
            </span>
          ))}
          <button
            onClick={() => setShowTemplate(true)}
            className="inline-flex items-center gap-1 text-xs text-gray-400 hover:text-blue-600 transition-colors"
          >
            <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15.232 5.232l3.536 3.536M9 13l6.586-6.586a2 2 0 112.828 2.828L11.828 15.828A2 2 0 0110 16.414V19h2.586a2 2 0 001.414-.586l6.5-6.5" />
            </svg>
            {(experiment.template ?? []).length === 0 ? 'Set up' : 'Edit'}
          </button>
        </div>

        {/* Subject info template */}
        <div className="flex flex-wrap items-center gap-1.5">
          <span className="text-xs font-semibold text-gray-400 uppercase tracking-wide w-24 shrink-0">Subject info</span>
          {subjectTemplate.map((f) => (
            <span
              key={f.key}
              className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium border ${
                f.active ? 'bg-emerald-50 border-emerald-200 text-emerald-700' : 'bg-gray-100 border-gray-200 text-gray-400'
              }`}
            >
              {f.active ? null : <span title="hidden">◌</span>}
              {f.label}
            </span>
          ))}
          <button
            onClick={() => setShowSubjectTemplate(true)}
            className="inline-flex items-center gap-1 text-xs text-gray-400 hover:text-emerald-600 transition-colors"
          >
            <svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15.232 5.232l3.536 3.536M9 13l6.586-6.586a2 2 0 112.828 2.828L11.828 15.828A2 2 0 0110 16.414V19h2.586a2 2 0 001.414-.586l6.5-6.5" />
            </svg>
            {subjectTemplate.length === 0 ? 'Set up' : 'Edit'}
          </button>
        </div>
      </div>

      {animals.length === 0 ? (
        <div className="text-center py-16 border-2 border-dashed border-gray-200 rounded-xl">
          <p className="text-gray-400 mb-3">No animals enrolled in this experiment yet.</p>
          <Button onClick={() => setShowAddAnimal(true)}>+ Add First Animal</Button>
        </div>
      ) : (
        <>
          {/* Display controls */}
          <div className="flex items-center gap-3 mb-3 flex-wrap">
            {/* Mode toggle */}
            <div className="flex rounded border border-gray-200 overflow-hidden text-xs">
              {[['list', 'List'], ['group', 'Group']].map(([mode, label]) => (
                <button key={mode} type="button" onClick={() => updateDisplayMode(mode)}
                  className={`px-3 py-1 border-l border-gray-200 first:border-l-0 transition-colors
                    ${displayMode === mode ? 'bg-gray-700 text-white' : 'bg-white text-gray-500 hover:bg-gray-50'}`}>
                  {label}
                </button>
              ))}
            </div>

            {displayMode === 'list' && (
              <>
                <span className="text-xs text-gray-400">Sort by</span>
                <select value={sortField} onChange={(e) => updateSort(e.target.value, sortDir)}
                  className="border border-gray-200 rounded px-2 py-1 text-xs bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400">
                  <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>
                <button type="button" onClick={() => updateSort(sortField, sortDir === 'asc' ? 'desc' : 'asc')}
                  className="text-xs text-gray-500 hover:text-gray-800 border border-gray-200 rounded px-2 py-1 bg-white transition-colors">
                  {sortDir === 'asc' ? '↑ Asc' : '↓ Desc'}
                </button>
              </>
            )}

            {displayMode === 'group' && (
              <>
                <span className="text-xs text-gray-400">Group by</span>
                <select value={groupField} onChange={(e) => updateGroupField(e.target.value)}
                  className="border border-gray-200 rounded px-2 py-1 text-xs bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400">
                  <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>
                <span className="text-xs text-gray-400 ml-1">· sorted within by</span>
                <select value={sortField} onChange={(e) => updateSort(e.target.value, sortDir)}
                  className="border border-gray-200 rounded px-2 py-1 text-xs bg-white focus:outline-none focus:ring-1 focus:ring-indigo-400">
                  <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>
                <button type="button" onClick={() => updateSort(sortField, sortDir === 'asc' ? 'desc' : 'asc')}
                  className="text-xs text-gray-500 hover:text-gray-800 border border-gray-200 rounded px-2 py-1 bg-white transition-colors">
                  {sortDir === 'asc' ? '↑ Asc' : '↓ Desc'}
                </button>
              </>
            )}
          </div>

          {displayMode === 'list' && (
            <AnimalCardList
              animals={sortedAnimals}
              subjectTemplate={subjectTemplate}
              onNavigate={(animal) => navigate(`/animals/${animal.id}`, { state: { template: experiment.template } })}
              onEdit={setEditAnimal}
            />
          )}

          {displayMode === 'group' && groupedAnimals && groupedAnimals.map(([groupValue, groupAnimals]) => {
            const groupLabel = (() => {
              if (groupField === '__name__' || groupField === '__id__') return groupValue;
              return subjectTemplate.find((f) => f.fieldId === groupField)?.label
                ? `${subjectTemplate.find((f) => f.fieldId === groupField).label}: ${groupValue}`
                : groupValue;
            })();
            return (
              <div key={groupValue} className="mb-5">
                <div className="flex items-center gap-2 mb-2">
                  <span className="text-xs font-semibold text-gray-500 uppercase tracking-wide">{groupLabel}</span>
                  <span className="text-xs text-gray-400">({groupAnimals.length})</span>
                  <div className="flex-1 border-t border-gray-100" />
                </div>
                <AnimalCardList
                  animals={groupAnimals}
                  subjectTemplate={subjectTemplate}
                  onNavigate={(animal) => navigate(`/animals/${animal.id}`, { state: { template: experiment.template } })}
                  onEdit={setEditAnimal}
                />
              </div>
            );
          })}

        </>
      )}

      <ExperimentAnalysisCharts
        animals={animals}
        experimentStatuses={experimentStatuses}
        subjectTemplate={subjectTemplate}
        dailyTemplate={dailyTemplate}
        plotConfig={experiment.plot_config}
        onPersistConfig={(cfg) => experimentsApi.savePlotConfig(id, cfg)}
      />

      {animals.length > 0 && (
        <ExperimentCalendar
          experimentId={id}
          template={dailyTemplate}
        />
      )}

      <AuditLogSection tableName="animals" limit={5} />

      {/* Template editor modal */}
      <Modal isOpen={showTemplate} onClose={() => setShowTemplate(false)} title="Daily Record Template" size="full">
        <TemplateEditor experimentId={id} onClose={handleTemplateSaved} />
      </Modal>

      <Modal isOpen={showSubjectTemplate} onClose={() => setShowSubjectTemplate(false)} title="Subject Info Template" size="full">
        <TemplateEditor
          experimentId={id}
          loadFn={() => experimentsApi.getSubjectTemplate(id)}
          saveFn={(fields) => experimentsApi.updateSubjectTemplate(id, fields)}
          onClose={(updated) => {
            setShowSubjectTemplate(false);
            if (updated) { setSubjectTemplate(updated); flash('Subject info template updated.'); }
          }}
        />
      </Modal>

      <Modal isOpen={showAddAnimal} onClose={() => setShowAddAnimal(false)} title="Add Animal">
        <AnimalForm experimentId={id} onSuccess={handleAnimalSaved} onCancel={() => setShowAddAnimal(false)} />
      </Modal>

      <Modal isOpen={!!editAnimal} onClose={() => setEditAnimal(null)} title="Edit Animal">
        <AnimalForm existing={editAnimal} experimentId={id} onSuccess={handleAnimalSaved} onCancel={() => setEditAnimal(null)} />
      </Modal>

      <Modal isOpen={showExport} onClose={() => setShowExport(false)} title="Export data" size="md">
        <ExportDataModal
          experimentId={id}
          experimentTitle={experiment.title}
          dailyTemplate={dailyTemplate}
          animals={animals}
          subjectTemplate={subjectTemplate}
          groupField={localStorage.getItem(`exp-subject-group-${id}`) ?? '__none__'}
          onClose={() => setShowExport(false)}
        />
      </Modal>

    </div>
  );
}
