'use client';

import { useState, useEffect, useCallback, useMemo } from 'react';
import useSWR, { mutate } from 'swr';
import {
  listRegimens,
  createRegimen,
  updateRegimen,
  deleteRegimen,
  getBurnRates,
} from '@/services/regimens';
import { listMedicines } from '@/services/medicines';
import {
  DosageFrequency,
  TimeOfDay,
  DosageUnit,
  type MedicineForm,
  allowedUnitsForForm,
  defaultUnitForForm,
} from '@meshitrack/shared';
import type { CreateRegimenInput } from '@meshitrack/shared';
import type { z } from 'zod/v4';
import type {
  RegimenResponseSchema,
  RegimenMedicationInputSchema,
  BurnRateItemSchema,
} from '@meshitrack/shared';

type Regimen = z.infer<typeof RegimenResponseSchema>;
type MedicationInput = z.infer<typeof RegimenMedicationInputSchema>;
type BurnRateItem = z.infer<typeof BurnRateItemSchema>;

type MedicineOption = {
  _id: string;
  name: string;
  strength: number;
  strengthUnit: string;
  form: MedicineForm;
};

const FREQUENCY_LABELS: Record<string, string> = {
  daily: 'Once daily',
  twice_daily: 'Twice daily',
  three_times_daily: 'Three times daily',
  weekly: 'Weekly',
  every_other_day: 'Every other day',
  as_needed: 'As needed',
  custom: 'Custom',
};

const TIME_LABELS: Record<string, string> = {
  morning: 'Morning',
  afternoon: 'Afternoon',
  evening: 'Evening',
  bedtime: 'Bedtime',
};

const FORM_LABELS: Record<string, string> = {
  tablet: 'Tablet',
  capsule: 'Capsule',
  liquid: 'Liquid',
  injection: 'Injection',
  other: 'Other',
};

function formatDate(dateStr: string): string {
  return new Date(dateStr).toLocaleDateString();
}

// --- Medication sub-form row ---

function MedicationRow({
  medication,
  index,
  medicines,
  onChange,
  onRemove,
}: {
  medication: MedicationInput;
  index: number;
  medicines: MedicineOption[];
  onChange: (index: number, updated: MedicationInput) => void;
  onRemove: (index: number) => void;
}) {
  const selectedMed = medicines.find((m) => m._id === medication.medicineId);
  const allowedUnits = selectedMed
    ? allowedUnitsForForm(selectedMed.form)
    : Object.values(DosageUnit);

  function handleMedicineChange(medicineId: string) {
    const med = medicines.find((m) => m._id === medicineId);
    const newUnit = med ? defaultUnitForForm(med.form) : DosageUnit.TABLET;
    onChange(index, { ...medication, medicineId, dosageUnit: newUnit });
  }

  return (
    <div className="rounded-lg border bg-gray-50 p-4 space-y-3">
      <div className="flex items-start justify-between gap-2">
        <span className="text-sm font-medium text-gray-600">Medication {index + 1}</span>
        <button
          type="button"
          onClick={() => onRemove(index)}
          className="mt-btn mt-btn--danger-icon"
          title="Remove medication"
        >
          <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M6 18L18 6M6 6l12 12"
            />
          </svg>
        </button>
      </div>

      <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
        <div>
          <label className="mt-field-label">Medicine</label>
          <select
            required
            value={medication.medicineId}
            onChange={(e) => handleMedicineChange(e.target.value)}
            className="mt-field"
          >
            <option value="">Select medicine...</option>
            {medicines.map((m) => (
              <option key={m._id} value={m._id}>
                {m.name} {m.strength} {m.strengthUnit} ({FORM_LABELS[m.form] ?? m.form})
              </option>
            ))}
          </select>
        </div>

        <div className="flex gap-2">
          <div className="flex-1">
            <label className="mt-field-label">Dosage</label>
            <input
              type="number"
              required
              min={0.01}
              step="any"
              value={medication.dosage || ''}
              onChange={(e) => onChange(index, { ...medication, dosage: Number(e.target.value) })}
              className="mt-field"
            />
          </div>
          <div className="flex-1">
            <label className="mt-field-label">Unit</label>
            <select
              value={medication.dosageUnit}
              onChange={(e) =>
                onChange(index, { ...medication, dosageUnit: e.target.value as DosageUnit })
              }
              className="mt-field"
            >
              {allowedUnits.map((u) => (
                <option key={u} value={u}>
                  {u}
                </option>
              ))}
            </select>
          </div>
        </div>

        <div>
          <label className="mt-field-label">Frequency</label>
          <select
            value={medication.frequency}
            onChange={(e) =>
              onChange(index, {
                ...medication,
                frequency: e.target.value as DosageFrequency,
                customFrequencyPerDay:
                  e.target.value === DosageFrequency.CUSTOM
                    ? (medication.customFrequencyPerDay ?? 1)
                    : undefined,
              })
            }
            className="mt-field"
          >
            {Object.values(DosageFrequency).map((f) => (
              <option key={f} value={f}>
                {FREQUENCY_LABELS[f] ?? f}
              </option>
            ))}
          </select>
        </div>

        {medication.frequency === DosageFrequency.CUSTOM && (
          <div>
            <label className="mt-field-label">Times per day</label>
            <input
              type="number"
              required
              min={1}
              step={1}
              value={medication.customFrequencyPerDay ?? ''}
              onChange={(e) =>
                onChange(index, { ...medication, customFrequencyPerDay: Number(e.target.value) })
              }
              className="mt-field"
            />
          </div>
        )}

        <div>
          <label className="mt-field-label">Time of day (optional)</label>
          <select
            value={medication.timeOfDay ?? ''}
            onChange={(e) =>
              onChange(index, {
                ...medication,
                timeOfDay: e.target.value ? (e.target.value as TimeOfDay) : undefined,
              })
            }
            className="mt-field"
          >
            <option value="">Any time</option>
            {Object.values(TimeOfDay).map((t) => (
              <option key={t} value={t}>
                {TIME_LABELS[t] ?? t}
              </option>
            ))}
          </select>
        </div>

        <div>
          <label className="mt-field-label">Instructions (optional)</label>
          <input
            type="text"
            maxLength={500}
            value={medication.instructions ?? ''}
            onChange={(e) =>
              onChange(index, { ...medication, instructions: e.target.value || undefined })
            }
            placeholder="e.g. Take with food"
            className="mt-field"
          />
        </div>
      </div>
    </div>
  );
}

// --- Regimen create / edit form ---

function emptyMedication(): MedicationInput {
  return {
    medicineId: '',
    dosage: 1,
    dosageUnit: DosageUnit.TABLET,
    frequency: DosageFrequency.DAILY,
  };
}

function RegimenForm({
  householdId,
  medicines,
  initial,
  onSaved,
  onCancel,
}: {
  householdId: string;
  medicines: MedicineOption[];
  initial?: Regimen;
  onSaved: () => void;
  onCancel: () => void;
}) {
  const [name, setName] = useState(initial?.name ?? '');
  const [isActive, setIsActive] = useState(initial?.isActive ?? true);
  const [medications, setMedications] = useState<MedicationInput[]>(
    initial?.medications.map((m) => ({
      medicineId: m.medicineId,
      dosage: m.dosage,
      dosageUnit: m.dosageUnit as DosageUnit,
      frequency: m.frequency as DosageFrequency,
      customFrequencyPerDay: m.customFrequencyPerDay,
      timeOfDay: m.timeOfDay as TimeOfDay | undefined,
      instructions: m.instructions,
    })) ?? [emptyMedication()],
  );
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState('');

  function updateMedication(index: number, updated: MedicationInput) {
    setMedications((prev) => prev.map((m, i) => (i === index ? updated : m)));
  }

  function removeMedication(index: number) {
    setMedications((prev) => prev.filter((_, i) => i !== index));
  }

  function addMedication() {
    setMedications((prev) => [...prev, emptyMedication()]);
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (medications.length === 0) {
      setError('At least one medication is required.');
      return;
    }
    setError('');
    setSubmitting(true);
    try {
      const payload: CreateRegimenInput = { name: name.trim(), isActive, medications };
      if (initial) {
        await updateRegimen(householdId, initial._id, payload);
      } else {
        await createRegimen(householdId, payload);
      }
      onSaved();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save regimen');
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="mt-card mb-6">
      <h2 className="text-lg font-semibold mb-4">{initial ? 'Edit Regimen' : 'New Regimen'}</h2>
      {error && <div className="mt-alert mt-alert--danger mb-4">{error}</div>}
      <form onSubmit={handleSubmit} className="space-y-5">
        <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
          <div>
            <label className="mt-field-label">Name</label>
            <input
              type="text"
              required
              maxLength={200}
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="e.g. Morning routine"
              className="mt-field"
            />
          </div>
          <div className="flex items-center gap-3 pt-6">
            <input
              type="checkbox"
              id="isActive"
              checked={isActive}
              onChange={(e) => setIsActive(e.target.checked)}
              className="h-4 w-4 rounded border-gray-300"
            />
            <label htmlFor="isActive" className="text-sm font-medium text-gray-700">
              Active
            </label>
          </div>
        </div>

        <div>
          <div className="flex items-center justify-between mb-3">
            <h3 className="text-sm font-semibold text-gray-800">Medications</h3>
            <button type="button" onClick={addMedication} className="mt-btn mt-btn--ghost">
              + Add medication
            </button>
          </div>
          {medications.length === 0 ? (
            <p className="text-sm text-gray-500 italic">No medications added yet.</p>
          ) : (
            <div className="space-y-3">
              {medications.map((med, i) => (
                <MedicationRow
                  key={i}
                  index={i}
                  medication={med}
                  medicines={medicines}
                  onChange={updateMedication}
                  onRemove={removeMedication}
                />
              ))}
            </div>
          )}
        </div>

        <div className="flex gap-3 pt-2">
          <button type="submit" disabled={submitting} className="mt-btn mt-btn--primary">
            {submitting ? 'Saving...' : initial ? 'Save changes' : 'Create regimen'}
          </button>
          <button type="button" onClick={onCancel} className="mt-btn mt-btn--ghost">
            Cancel
          </button>
        </div>
      </form>
    </div>
  );
}

// --- Burn rate table ---

function BurnRateTable({ burnRates }: { burnRates: BurnRateItem[] }) {
  if (burnRates.length === 0) {
    return (
      <p className="text-sm text-gray-500">
        No active regimens with cabinet stock to calculate burn rates.
      </p>
    );
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-sm">
        <thead>
          <tr className="border-b text-left text-gray-500">
            <th className="pb-2 font-medium">Medicine</th>
            <th className="pb-2 font-medium text-right">Daily use</th>
            <th className="pb-2 font-medium text-right">In cabinet</th>
            <th className="pb-2 font-medium text-right">Days left</th>
            <th className="pb-2 font-medium text-right">Monthly cost</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-100">
          {burnRates.map((item) => {
            const daysLeft = item.daysUntilEmpty;
            const daysColor =
              daysLeft === null
                ? 'text-gray-400'
                : daysLeft <= 7
                  ? 'text-red-600 font-semibold'
                  : daysLeft <= 30
                    ? 'text-yellow-600'
                    : 'text-green-600';

            return (
              <tr key={item.medicineId} className="py-2">
                <td className="py-2 font-medium text-gray-900">{item.medicineName}</td>
                <td className="py-2 text-right text-gray-600">
                  {item.dailyConsumption.toFixed(2)}
                </td>
                <td className="py-2 text-right text-gray-600">{item.totalInCabinet}</td>
                <td className={`py-2 text-right ${daysColor}`}>
                  {daysLeft !== null ? daysLeft : '-'}
                </td>
                <td className="py-2 text-right text-gray-600">
                  {item.projectedMonthlyCost !== null
                    ? `${item.currency ?? ''} ${item.projectedMonthlyCost.toFixed(2)}`.trim()
                    : '-'}
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

// --- Main component ---

export function RegimensTab({ householdId }: { householdId: string }) {
  const [error, setError] = useState('');
  const [medicines, setMedicines] = useState<MedicineOption[]>([]);
  const [showForm, setShowForm] = useState(false);
  const [editingRegimen, setEditingRegimen] = useState<Regimen | null>(null);
  const [filterActive, setFilterActive] = useState<'all' | 'active' | 'inactive'>('all');
  const [showBurnRate, setShowBurnRate] = useState(false);

  const query = useMemo(() => {
    const q: any = { limit: 50 };
    if (filterActive === 'active') q.isActive = true;
    if (filterActive === 'inactive') q.isActive = false;
    return q;
  }, [filterActive]);

  const swrKey = householdId ? `regimens-${householdId}-${JSON.stringify(query)}` : null;
  const { data: regimensResponse, mutate: mutateRegimens, isLoading: loading, error: swrError } = useSWR(
    swrKey,
    () => listRegimens(householdId, query)
  );

  const regimens = regimensResponse?.data ?? [];

  const { data: burnRateResponse, mutate: mutateBurnRates, isLoading: burnRateSWRLoading, error: burnRateError } = useSWR(
    householdId && showBurnRate ? `burn-rates-${householdId}` : null,
    () => getBurnRates(householdId)
  );

  const burnRates = burnRateResponse?.data ?? [];
  const burnRateLoading = showBurnRate && burnRateSWRLoading;

  useEffect(() => {
    const err = swrError || burnRateError;
    if (err) {
      setError(err instanceof Error ? err.message : 'Failed to load data');
    }
  }, [swrError, burnRateError]);

  // Medicines are needed for the form
  useEffect(() => {
    listMedicines(householdId, { limit: 100 })
      .then((r) => setMedicines(r.data as MedicineOption[]))
      .catch(() => {});
  }, [householdId]);

  async function handleDelete(id: string, name: string) {
    if (!window.confirm(`Delete regimen "${name}"?`)) return;
    
    // Optimistic delete
    mutateRegimens(async (current) => {
      if (!current) return current;
      return { ...current, data: current.data.filter((r: any) => r._id !== id) };
    }, { revalidate: false });

    try {
      await deleteRegimen(householdId, id);
      mutateRegimens();
      if (showBurnRate) mutateBurnRates();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to delete');
      mutateRegimens();
    }
  }

  async function handleToggleActive(regimen: Regimen) {
    const nextActive = !regimen.isActive;
    
    // Optimistic toggle
    mutateRegimens(async (current) => {
      if (!current) return current;
      return {
        ...current,
        data: current.data.map((r: any) => r._id === regimen._id ? { ...r, isActive: nextActive } : r)
      };
    }, { revalidate: false });

    try {
      await updateRegimen(householdId, regimen._id, {
        isActive: nextActive,
      });
      mutateRegimens();
      if (showBurnRate) mutateBurnRates();
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to update');
      mutateRegimens();
    }
  }

  async function handleShowBurnRate() {
    setShowBurnRate((prev) => !prev);
  }

  const isFormOpen = showForm || editingRegimen !== null;

  return (
    <div>
      <div className="flex items-center justify-between mb-4">
        <div className="flex items-center gap-3">
          <select
            value={filterActive}
            onChange={(e) => setFilterActive(e.target.value as 'all' | 'active' | 'inactive')}
            className="mt-field"
            style={{ width: 'auto' }}
          >
            <option value="all">All regimens</option>
            <option value="active">Active</option>
            <option value="inactive">Inactive</option>
          </select>
          <button onClick={handleShowBurnRate} className="mt-btn mt-btn--ghost">
            {showBurnRate ? 'Hide burn rate' : 'Burn rate'}
          </button>
        </div>
        <button
          onClick={() => {
            setEditingRegimen(null);
            setShowForm(!showForm);
          }}
          className="mt-btn mt-btn--primary"
        >
          {showForm ? 'Cancel' : 'New Regimen'}
        </button>
      </div>

      {error && (
        <div className="mt-alert mt-alert--danger mb-4">
          {error}
          <button onClick={() => setError('')} className="ml-2 underline">
            Dismiss
          </button>
        </div>
      )}

      {showBurnRate && (
        <div className="mb-6 mt-card">
          <h2 className="text-lg font-semibold mb-4">Burn Rate &amp; Spending Projections</h2>
          {burnRateLoading ? (
            <div className="animate-pulse space-y-2">
              <div className="h-6 w-full rounded bg-gray-200" />
              <div className="h-6 w-full rounded bg-gray-200" />
            </div>
          ) : (
            <BurnRateTable burnRates={burnRates} />
          )}
        </div>
      )}

      {showForm && !editingRegimen && (
        <RegimenForm
          householdId={householdId}
          medicines={medicines}
          onSaved={() => {
            setShowForm(false);
            mutateRegimens();
            if (showBurnRate) mutateBurnRates();
          }}
          onCancel={() => setShowForm(false)}
        />
      )}

      {editingRegimen && (
        <RegimenForm
          householdId={householdId}
          medicines={medicines}
          initial={editingRegimen}
          onSaved={() => {
            setEditingRegimen(null);
            mutateRegimens();
            if (showBurnRate) mutateBurnRates();
          }}
          onCancel={() => setEditingRegimen(null)}
        />
      )}

      {loading ? (
        <div className="space-y-3">
          {Array.from({ length: 3 }).map((_, i) => (
            <div key={i} className="animate-pulse rounded-xl border bg-white p-4 h-24" />
          ))}
        </div>
      ) : regimens.length === 0 ? (
        <div className="mt-card text-center" style={{ color: 'var(--ink-muted)' }}>
          {filterActive !== 'all'
            ? `No ${filterActive} regimens found.`
            : isFormOpen
              ? null
              : 'No regimens yet. Create your first medication schedule above.'}
        </div>
      ) : (
        <div className="space-y-3">
          {regimens.map((regimen) => (
            <div key={regimen._id} className="mt-card">
              <div className="flex items-start justify-between gap-4">
                <div className="flex-1 min-w-0">
                  <div className="flex items-center gap-2 mb-1">
                    <h3 className="font-semibold text-gray-900">{regimen.name}</h3>
                    <span
                      className={`mt-pill ${regimen.isActive ? 'mt-pill--ok' : 'mt-pill--ghost'}`}
                    >
                      {regimen.isActive ? 'Active' : 'Inactive'}
                    </span>
                  </div>
                  <p className="text-sm text-gray-500 mb-2">
                    {regimen.medications.length} medication
                    {regimen.medications.length !== 1 ? 's' : ''}
                  </p>
                  <div className="flex flex-wrap gap-1">
                    {regimen.medications.map((med, i) => (
                      <span key={i} className="mt-pill mt-pill--info">
                        {med.medicineName} — {med.dosage} {med.dosageUnit} (
                        {FREQUENCY_LABELS[med.frequency] ?? med.frequency})
                      </span>
                    ))}
                  </div>
                  <p className="mt-2 text-xs text-gray-400">
                    Created {formatDate(regimen.createdAt)}
                  </p>
                </div>
                <div className="flex items-center gap-2 shrink-0">
                  <button
                    onClick={() => handleToggleActive(regimen)}
                    className="mt-btn mt-btn--ghost"
                    title={regimen.isActive ? 'Deactivate' : 'Activate'}
                  >
                    {regimen.isActive ? 'Deactivate' : 'Activate'}
                  </button>
                  <button
                    onClick={() => {
                      setShowForm(false);
                      setEditingRegimen(regimen);
                    }}
                    className="mt-btn mt-btn--icon"
                    title="Edit"
                  >
                    <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
                      />
                    </svg>
                  </button>
                  <button
                    onClick={() => handleDelete(regimen._id, regimen.name)}
                    className="mt-btn mt-btn--danger-icon"
                    title="Delete"
                  >
                    <svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                      />
                    </svg>
                  </button>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}
