import React, { useState, useEffect, useMemo } from 'react';
import {
  format, startOfMonth, endOfMonth, eachDayOfInterval,
  getDay, addMonths, subMonths,
} from 'date-fns';
import {
  ResponsiveContainer, BarChart, Bar, XAxis, YAxis,
  CartesianGrid, Tooltip, Legend,
} from 'recharts';
import { experimentsApi } from '../api/client';
import Modal from './ui/Modal';
import DailyStatusForm from './DailyStatusForm';

const BUILTIN_KEYS_SET = new Set(['experiment_description', 'vitals', 'treatment', 'notes']);

function SubjectReadOnly({ status, template }) {
  const activeFields = template.filter((f) => f.active);
  function getVal(s, f) {
    if (f.builtin) return s[f.key];
    return s.custom_fields?.[f.fieldId];
  }
  const nonEmpty = activeFields.filter((f) => {
    const v = getVal(status, f);
    return v !== null && v !== undefined && String(v).trim() !== '';
  });
  if (nonEmpty.length === 0) return <p className="text-xs text-gray-400">No field values recorded.</p>;
  return (
    <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-1">
      {nonEmpty.map((f) => (
        <div key={f.fieldId ?? f.key} className="text-sm">
          <span className="text-gray-500 font-medium">{f.label}:</span>{' '}
          <span className="text-gray-900 whitespace-pre-wrap">{String(getVal(status, f))}</span>
        </div>
      ))}
    </div>
  );
}

function DayPanel({ date, animals, allStatuses, template, experimentId, selectedField, fieldOptions, onStatusChange, onStatusCreate }) {
  const dateStr = format(date, 'yyyy-MM-dd');
  const [editingAnimalId, setEditingAnimalId] = useState(null);

  const statusByAnimal = useMemo(() => {
    const map = {};
    allStatuses.forEach((s) => {
      if (s.date.slice(0, 10) === dateStr) map[s.animal_id] = s;
    });
    return map;
  }, [allStatuses, dateStr]);

  // Only show animals that have a status record for this day WITH a non-empty selected field
  const animalsWithData = animals.filter((a) => {
    const s = statusByAnimal[a.id];
    if (!s) return false;
    if (!selectedField) return true;
    const isBuiltin = BUILTIN_KEYS_SET.has(selectedField);
    const val = isBuiltin ? s[selectedField] : s.custom_fields?.[selectedField];
    return val !== null && val !== undefined && String(val).trim() !== '';
  });

  const fieldLabel = fieldOptions.find((f) => f.value === selectedField)?.label;

  // Bar chart: animals with analysis_summary on this day → Success/Failure/Total from that summary
  const barData = useMemo(() => {
    return animalsWithData
      .map((animal) => {
        const status = statusByAnimal[animal.id];
        const summary = status?.analysis_summary;
        if (!summary || summary.total === 0) return null;
        return {
          name: animal.animal_name || animal.animal_id_string || animal.id.slice(0, 8),
          total: summary.total,
          success: summary.counts?.Success ?? 0,
          failure: summary.counts?.Failure ?? 0,
        };
      })
      .filter(Boolean);
  }, [animalsWithData, statusByAnimal]);

  return (
    <div className="space-y-3 max-h-[80vh] overflow-y-auto pr-1">
      {animalsWithData.length === 0 && (
        <p className="text-gray-400 text-sm py-2">No data recorded for this day.</p>
      )}
      {/* Per-animal data for this day */}
      {animalsWithData.map((animal) => {
        const existing = statusByAnimal[animal.id];
        const isEditing = editingAnimalId === animal.id;
        return (
          <div key={animal.id} className="bg-gray-50 rounded-xl p-4 border border-gray-100">
            <div className="flex items-center justify-between mb-2">
              <div className="font-semibold text-gray-900 text-sm">
                {animal.animal_name ?? 'Unknown subject'}
                {animal.animal_id_string && (
                  <span className="ml-2 text-gray-400 font-normal">· {animal.animal_id_string}</span>
                )}
              </div>
              {!isEditing && (
                <button
                  type="button"
                  onClick={() => setEditingAnimalId(animal.id)}
                  className="text-xs text-blue-600 hover:text-blue-800 border border-blue-200 rounded px-2 py-0.5 hover:bg-blue-50 transition-colors"
                >
                  Edit
                </button>
              )}
            </div>
            {isEditing ? (
              <DailyStatusForm
                animalId={animal.id}
                experimentId={experimentId}
                template={template}
                existing={{ ...existing, date: dateStr }}
                onSuccess={(saved) => { onStatusChange(saved); setEditingAnimalId(null); }}
                onCancel={() => setEditingAnimalId(null)}
              />
            ) : (
              <SubjectReadOnly status={existing} template={template} />
            )}
          </div>
        );
      })}

      {/* Bar chart: overall per-subject completeness */}
      {barData.length > 0 && (
        <div className="mt-4 pt-4 border-t border-gray-100">
          <h4 className="text-sm font-semibold text-gray-700 mb-3">Session metrics</h4>
          <ResponsiveContainer width="100%" height={200}>
            <BarChart data={barData} margin={{ top: 4, right: 16, left: 0, bottom: 4 }}>
              <CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
              <XAxis dataKey="name" tick={{ fontSize: 11 }} />
              <YAxis tick={{ fontSize: 11 }} />
              <Tooltip />
              <Legend wrapperStyle={{ fontSize: 11 }} />
              <Bar dataKey="total" name="Total" fill="#94a3b8" radius={[3, 3, 0, 0]} />
              <Bar dataKey="success" name="Success" fill="#22c55e" radius={[3, 3, 0, 0]} />
              <Bar dataKey="failure" name="Failure" fill="#f87171" radius={[3, 3, 0, 0]} minPointSize={2} />
            </BarChart>
          </ResponsiveContainer>
        </div>
      )}
    </div>
  );
}

export default function ExperimentCalendar({ experimentId, template, allStatuses, animals, onStatusChange, onStatusCreate }) {
  const [currentMonth, setCurrentMonth] = useState(() => new Date());
  const [selectedField, setSelectedField] = useState(null);
  const [calendarDays, setCalendarDays] = useState({});
  const [loading, setLoading] = useState(false);
  const [selectedDate, setSelectedDate] = useState(null);

  const fieldOptions = useMemo(
    () => template.filter((f) => f.active).map((f) => ({ value: f.builtin ? f.key : f.fieldId, label: f.label })),
    [template],
  );

  useEffect(() => {
    if (fieldOptions.length === 0 || selectedField) return;
    const weightField = fieldOptions.find((f) => f.label.toLowerCase().includes('weight'));
    setSelectedField(weightField ? weightField.value : fieldOptions[0]?.value ?? null);
  }, [fieldOptions]); // eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    if (!selectedField) return;
    const isBuiltin = BUILTIN_KEYS_SET.has(selectedField);
    const days = {};
    allStatuses.forEach((s) => {
      const val = isBuiltin ? s[selectedField] : s.custom_fields?.[selectedField];
      if (val !== null && val !== undefined && String(val).trim() !== '') {
        const key = s.date.slice(0, 10);
        days[key] = (days[key] || 0) + 1;
      }
    });
    setCalendarDays(days);
  }, [allStatuses, selectedField]);

  const monthStart = startOfMonth(currentMonth);
  const monthEnd   = endOfMonth(currentMonth);
  const days       = eachDayOfInterval({ start: monthStart, end: monthEnd });
  const leadingPad = getDay(monthStart);

  return (
    <div className="bg-white rounded-xl border border-gray-200 p-5 shadow-sm mt-6">
      <h3 className="text-base font-semibold text-gray-900 mb-4">Daily Record Calendar</h3>

      <div className="flex flex-wrap items-center gap-3 mb-5">
        <span className="text-sm text-gray-600 font-medium">Count by field:</span>
        <select
          data-testid="field-select"
          className="text-sm border border-gray-300 rounded-lg px-3 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-500 bg-white"
          value={selectedField ?? ''}
          onChange={(e) => setSelectedField(e.target.value)}
          disabled={fieldOptions.length === 0}
        >
          {fieldOptions.map((f) => <option key={f.value} value={f.value}>{f.label}</option>)}
          {fieldOptions.length === 0 && <option value="">No fields configured</option>}
        </select>
        {loading && <span className="text-xs text-gray-400" aria-live="polite">Loading...</span>}
      </div>

      <div className="flex items-center justify-between mb-4">
        <button aria-label="Previous month" onClick={() => setCurrentMonth((m) => subMonths(m, 1))}
          className="p-2 rounded-lg hover:bg-gray-100 text-gray-500 text-lg leading-none">&#8249;</button>
        <span className="font-semibold text-gray-900 text-base">{format(currentMonth, 'MMMM yyyy')}</span>
        <button aria-label="Next month" onClick={() => setCurrentMonth((m) => addMonths(m, 1))}
          className="p-2 rounded-lg hover:bg-gray-100 text-gray-500 text-lg leading-none">&#8250;</button>
      </div>

      <div className="grid grid-cols-7 mb-1">
        {['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'].map((d) => (
          <div key={d} className="text-center text-xs font-medium text-gray-400 py-1 select-none">{d}</div>
        ))}
      </div>

      <div className="grid grid-cols-7 gap-1">
        {Array.from({ length: leadingPad }).map((_, i) => <div key={`pad-${i}`} />)}
        {days.map((day) => {
          const dateStr = format(day, 'yyyy-MM-dd');
          const count   = calendarDays[dateStr] ?? 0;
          const hasData = count > 0;
          return (
            <button
              key={dateStr}
              data-testid={`day-${dateStr}`}
              disabled={!hasData}
              onClick={() => setSelectedDate(day)}
              className={[
                'relative flex flex-col items-center justify-center rounded-lg py-1.5 min-h-[2.75rem] text-sm select-none transition-all',
                hasData ? 'bg-blue-50 border border-blue-200 hover:bg-blue-100 cursor-pointer' : 'text-gray-300 cursor-default',
              ].join(' ')}
            >
              <span className={hasData ? 'font-semibold text-blue-900 text-xs' : 'text-xs'}>{day.getDate()}</span>
              {hasData && (
                <span data-testid={`count-${dateStr}`} className="text-[10px] leading-none font-bold text-blue-600 mt-0.5">{count}</span>
              )}
            </button>
          );
        })}
      </div>

      {selectedDate && (
        <Modal isOpen={!!selectedDate} onClose={() => setSelectedDate(null)} title={format(selectedDate, 'MMMM d, yyyy')} size="lg">
          <DayPanel
            date={selectedDate}
            animals={animals}
            allStatuses={allStatuses}
            template={template}
            experimentId={experimentId}
            selectedField={selectedField}
            fieldOptions={fieldOptions}
            onStatusChange={(updated) => { onStatusChange?.(updated); setSelectedDate(null); }}
            onStatusCreate={(created) => { onStatusCreate?.(created); setSelectedDate(null); }}
          />
        </Modal>
      )}
    </div>
  );
}
