'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { createRecipe, updateRecipe } from '@/services/recipes';
import { NutritionWarning } from '@meshitrack/shared';
import type { z } from 'zod/v4';
import type { RecipeResponseSchema, CreateRecipeInput } from '@meshitrack/shared';

type Recipe = z.infer<typeof RecipeResponseSchema>;
type IngredientUnit = CreateRecipeInput['ingredients'][number]['unit'];

type IngredientInput = {
  productId: string;
  productName: string;
  quantity: number;
  unit: IngredientUnit;
  preparation: string;
  isOptional: boolean;
};

type StepInput = {
  order: number;
  instruction: string;
  duration: string;
  tip: string;
};

const WARNING_LABELS: Partial<Record<string, string>> = {
  [NutritionWarning.HIGH_CALORIES]: 'High calories',
  [NutritionWarning.HIGH_SODIUM]: 'High sodium',
  [NutritionWarning.HIGH_SUGAR]: 'High sugar',
  [NutritionWarning.HIGH_SATURATED_FAT]: 'High sat fat',
  [NutritionWarning.LOW_PROTEIN]: 'Low protein',
  [NutritionWarning.LOW_FIBER]: 'Low fiber',
  [NutritionWarning.HIGH_CHOLESTEROL]: 'High cholesterol',
};

const UNIT_OPTIONS = ['g', 'ml', 'piece', 'slice', 'oz', 'lb', 'cup', 'tbsp', 'tsp', 'fl_oz'];

function emptyIngredient(): IngredientInput {
  return {
    productId: '',
    productName: '',
    quantity: 100,
    unit: 'g',
    preparation: '',
    isOptional: false,
  };
}

function emptyStep(order: number): StepInput {
  return { order, instruction: '', duration: '', tip: '' };
}

function ingredientFromRecipe(ing: Recipe['ingredients'][0]): IngredientInput {
  return {
    productId: ing.productId,
    productName: ing.productName,
    quantity: ing.originalQuantity ?? ing.quantity,
    unit: ing.originalUnit ?? ing.unit,
    preparation: ing.preparation ?? '',
    isOptional: ing.isOptional,
  };
}

function stepFromRecipe(step: Recipe['steps'][0]): StepInput {
  return {
    order: step.order,
    instruction: step.instruction,
    duration: step.duration ? String(step.duration) : '',
    tip: step.tip ?? '',
  };
}

function NutritionDisplay({
  nutrition,
  warnings,
}: {
  nutrition: Recipe['perServingNutrition'] | null;
  warnings: string[];
}) {
  if (!nutrition) return null;
  return (
    <div
      style={{
        background: 'var(--bg-elev)',
        border: '1px solid var(--border)',
        borderRadius: 'var(--r-md)',
        padding: 16,
      }}
    >
      <h3
        style={{
          fontSize: 13,
          fontWeight: 600,
          marginBottom: 10,
          textTransform: 'uppercase',
          letterSpacing: '0.05em',
          color: 'var(--ink-muted)',
        }}
      >
        Per serving (estimated)
      </h3>
      <div
        style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '4px 12px', fontSize: 13 }}
      >
        <span style={{ color: 'var(--ink-muted)' }}>Calories</span>
        <span style={{ fontWeight: 600 }}>{Math.round(nutrition.calories)} kcal</span>
        <span style={{ color: 'var(--ink-muted)' }}>Protein</span>
        <span>{nutrition.protein.toFixed(1)}g</span>
        <span style={{ color: 'var(--ink-muted)' }}>Carbs</span>
        <span>{nutrition.carbs.toFixed(1)}g</span>
        <span style={{ color: 'var(--ink-muted)' }}>Fat</span>
        <span>{nutrition.fat.toFixed(1)}g</span>
      </div>
      {warnings.length > 0 && (
        <div style={{ marginTop: 12 }}>
          {warnings.map((w) => (
            <div
              key={w}
              style={{
                fontSize: 11,
                color: 'var(--danger)',
                padding: '2px 0',
              }}
            >
              {WARNING_LABELS[w] ?? w}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

interface RecipeEditorProps {
  householdId: string;
  existing?: Recipe;
}

export function RecipeEditor({ householdId, existing }: RecipeEditorProps) {
  const router = useRouter();

  const [name, setName] = useState(existing?.name ?? '');
  const [description, setDescription] = useState(existing?.description ?? '');
  const [servings, setServings] = useState(existing?.servings ?? 4);
  const [prepTime, setPrepTime] = useState(existing?.prepTime ? String(existing.prepTime) : '');
  const [cookTime, setCookTime] = useState(existing?.cookTime ? String(existing.cookTime) : '');
  const [cuisine, setCuisine] = useState(existing?.cuisine ?? '');
  const [tags, setTags] = useState(existing?.tags.join(', ') ?? '');
  const [isFavorite, setIsFavorite] = useState(existing?.isFavorite ?? false);
  const [ingredients, setIngredients] = useState<IngredientInput[]>(
    existing ? existing.ingredients.map(ingredientFromRecipe) : [emptyIngredient()],
  );
  const [steps, setSteps] = useState<StepInput[]>(
    existing ? existing.steps.map(stepFromRecipe) : [emptyStep(1)],
  );
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState('');

  function updateIngredient(
    i: number,
    field: keyof IngredientInput,
    value: IngredientInput[keyof IngredientInput],
  ) {
    setIngredients((prev) =>
      prev.map((ing, idx) => (idx === i ? { ...ing, [field]: value } : ing)),
    );
  }

  function removeIngredient(i: number) {
    setIngredients((prev) => prev.filter((_, idx) => idx !== i));
  }

  function addIngredient() {
    setIngredients((prev) => [...prev, emptyIngredient()]);
  }

  function updateStep(i: number, field: keyof StepInput, value: string) {
    setSteps((prev) => prev.map((s, idx) => (idx === i ? { ...s, [field]: value } : s)));
  }

  function addStep() {
    setSteps((prev) => [...prev, emptyStep(prev.length + 1)]);
  }

  function removeStep(i: number) {
    setSteps((prev) =>
      prev.filter((_, idx) => idx !== i).map((s, idx) => ({ ...s, order: idx + 1 })),
    );
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError('');
    setSaving(true);

    const tagList = tags
      .split(',')
      .map((t) => t.trim())
      .filter(Boolean);

    const payload = {
      name: name.trim(),
      description: description.trim() || undefined,
      servings,
      prepTime: prepTime ? Number(prepTime) : undefined,
      cookTime: cookTime ? Number(cookTime) : undefined,
      cuisine: cuisine.trim() || undefined,
      tags: tagList,
      isFavorite,
      ingredients: ingredients.map((ing) => ({
        productId: ing.productId.trim(),
        productName: ing.productName.trim(),
        quantity: Number(ing.quantity),
        unit: ing.unit,
        preparation: ing.preparation.trim() || undefined,
        isOptional: ing.isOptional,
      })),
      steps: steps
        .filter((s) => s.instruction.trim())
        .map((s, i) => ({
          order: i + 1,
          instruction: s.instruction.trim(),
          duration: s.duration ? Number(s.duration) : undefined,
          tip: s.tip.trim() || undefined,
        })),
    };

    try {
      if (existing) {
        await updateRecipe(householdId, existing._id, payload);
        router.push(`/recipes/${existing._id}`);
      } else {
        const created = await createRecipe(householdId, payload);
        router.push(`/recipes/${created._id}`);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to save recipe');
      setSaving(false);
    }
  }

  const inputStyle: React.CSSProperties = {
    width: '100%',
    padding: '8px 12px',
    borderRadius: 'var(--r-sm)',
    border: '1px solid var(--border)',
    background: 'var(--bg)',
    color: 'var(--ink)',
    fontSize: 14,
    boxSizing: 'border-box',
  };

  const labelStyle: React.CSSProperties = {
    display: 'block',
    fontSize: 12,
    fontWeight: 600,
    color: 'var(--ink-muted)',
    marginBottom: 4,
    textTransform: 'uppercase',
    letterSpacing: '0.05em',
  };

  return (
    <form
      onSubmit={handleSubmit}
      style={{ display: 'grid', gridTemplateColumns: '1fr 300px', gap: 32, maxWidth: 1100 }}
    >
      {/* Main form */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 20 }}>
        {error && <p style={{ color: 'var(--danger)', fontSize: 14, margin: 0 }}>{error}</p>}

        {/* Basics */}
        <div>
          <label style={labelStyle}>Name *</label>
          <input
            required
            value={name}
            onChange={(e) => setName(e.target.value)}
            style={inputStyle}
            placeholder="Recipe name"
          />
        </div>

        <div>
          <label style={labelStyle}>Description</label>
          <textarea
            value={description}
            onChange={(e) => setDescription(e.target.value)}
            rows={3}
            style={{ ...inputStyle, resize: 'vertical' }}
            placeholder="Brief description..."
          />
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
          <div>
            <label style={labelStyle}>Servings *</label>
            <input
              type="number"
              required
              min={1}
              value={servings}
              onChange={(e) => setServings(Number(e.target.value))}
              style={inputStyle}
            />
          </div>
          <div>
            <label style={labelStyle}>Prep time (min)</label>
            <input
              type="number"
              min={0}
              value={prepTime}
              onChange={(e) => setPrepTime(e.target.value)}
              style={inputStyle}
              placeholder="0"
            />
          </div>
          <div>
            <label style={labelStyle}>Cook time (min)</label>
            <input
              type="number"
              min={0}
              value={cookTime}
              onChange={(e) => setCookTime(e.target.value)}
              style={inputStyle}
              placeholder="0"
            />
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
          <div>
            <label style={labelStyle}>Cuisine</label>
            <input
              value={cuisine}
              onChange={(e) => setCuisine(e.target.value)}
              style={inputStyle}
              placeholder="Italian, Japanese..."
            />
          </div>
          <div>
            <label style={labelStyle}>Tags (comma-separated)</label>
            <input
              value={tags}
              onChange={(e) => setTags(e.target.value)}
              style={inputStyle}
              placeholder="vegetarian, quick..."
            />
          </div>
        </div>

        <label
          style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14, cursor: 'pointer' }}
        >
          <input
            type="checkbox"
            checked={isFavorite}
            onChange={(e) => setIsFavorite(e.target.checked)}
          />
          Mark as favorite
        </label>

        {/* Ingredients */}
        <div>
          <h2 style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>Ingredients</h2>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {ingredients.map((ing, i) => (
              <div
                key={i}
                style={{
                  display: 'grid',
                  gridTemplateColumns: '2fr 80px 90px 1fr auto',
                  gap: 8,
                  alignItems: 'center',
                }}
              >
                <input
                  placeholder="Product name"
                  value={ing.productName}
                  onChange={(e) => {
                    updateIngredient(i, 'productName', e.target.value);
                    updateIngredient(
                      i,
                      'productId',
                      e.target.value.toLowerCase().replace(/\s+/g, '-'),
                    );
                  }}
                  style={{ ...inputStyle, fontSize: 13 }}
                  required
                />
                <input
                  type="number"
                  placeholder="Qty"
                  value={ing.quantity}
                  min={0}
                  onChange={(e) => updateIngredient(i, 'quantity', e.target.value)}
                  style={{ ...inputStyle, fontSize: 13 }}
                  required
                />
                <select
                  value={ing.unit}
                  onChange={(e) => updateIngredient(i, 'unit', e.target.value as IngredientUnit)}
                  style={{ ...inputStyle, fontSize: 13 }}
                >
                  {UNIT_OPTIONS.map((u) => (
                    <option key={u} value={u}>
                      {u}
                    </option>
                  ))}
                </select>
                <input
                  placeholder="Preparation (optional)"
                  value={ing.preparation}
                  onChange={(e) => updateIngredient(i, 'preparation', e.target.value)}
                  style={{ ...inputStyle, fontSize: 13 }}
                />
                <button
                  type="button"
                  onClick={() => removeIngredient(i)}
                  disabled={ingredients.length === 1}
                  style={{
                    background: 'none',
                    border: 'none',
                    color: 'var(--ink-muted)',
                    cursor: 'pointer',
                    fontSize: 18,
                    padding: '0 4px',
                    lineHeight: 1,
                  }}
                >
                  &times;
                </button>
              </div>
            ))}
          </div>
          <button
            type="button"
            onClick={addIngredient}
            style={{
              marginTop: 10,
              fontSize: 13,
              color: 'var(--brand)',
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              padding: 0,
            }}
          >
            + Add ingredient
          </button>
          <p style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 6 }}>
            Volume/imperial units (cup, tbsp, etc.) are automatically converted to metric before
            saving. A product must be linked for nutrition to calculate.
          </p>
        </div>

        {/* Steps */}
        <div>
          <h2 style={{ fontSize: 15, fontWeight: 600, marginBottom: 12 }}>Instructions</h2>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {steps.map((step, i) => (
              <div key={i} style={{ display: 'flex', gap: 10, alignItems: 'flex-start' }}>
                <span
                  style={{
                    fontSize: 13,
                    fontWeight: 600,
                    color: 'var(--ink-muted)',
                    minWidth: 20,
                    paddingTop: 10,
                  }}
                >
                  {i + 1}.
                </span>
                <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
                  <textarea
                    value={step.instruction}
                    onChange={(e) => updateStep(i, 'instruction', e.target.value)}
                    rows={2}
                    style={{ ...inputStyle, resize: 'vertical', fontSize: 13 }}
                    placeholder="Instruction..."
                  />
                  <div style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 8 }}>
                    <input
                      type="number"
                      placeholder="Duration (min)"
                      value={step.duration}
                      min={0}
                      onChange={(e) => updateStep(i, 'duration', e.target.value)}
                      style={{ ...inputStyle, fontSize: 12 }}
                    />
                    <input
                      placeholder="Tip (optional)"
                      value={step.tip}
                      onChange={(e) => updateStep(i, 'tip', e.target.value)}
                      style={{ ...inputStyle, fontSize: 12 }}
                    />
                  </div>
                </div>
                <button
                  type="button"
                  onClick={() => removeStep(i)}
                  disabled={steps.length === 1}
                  style={{
                    background: 'none',
                    border: 'none',
                    color: 'var(--ink-muted)',
                    cursor: 'pointer',
                    fontSize: 18,
                    padding: '0 4px',
                    lineHeight: 1,
                    paddingTop: 8,
                  }}
                >
                  &times;
                </button>
              </div>
            ))}
          </div>
          <button
            type="button"
            onClick={addStep}
            style={{
              marginTop: 10,
              fontSize: 13,
              color: 'var(--brand)',
              background: 'none',
              border: 'none',
              cursor: 'pointer',
              padding: 0,
            }}
          >
            + Add step
          </button>
        </div>

        {/* Submit */}
        <div style={{ display: 'flex', gap: 12, paddingTop: 8 }}>
          <button
            type="submit"
            disabled={saving}
            style={{
              padding: '10px 24px',
              background: 'var(--brand)',
              color: '#fff',
              border: 'none',
              borderRadius: 'var(--r-md)',
              fontSize: 14,
              fontWeight: 600,
              cursor: 'pointer',
              opacity: saving ? 0.7 : 1,
            }}
          >
            {saving ? 'Saving...' : existing ? 'Save changes' : 'Create recipe'}
          </button>
          <button
            type="button"
            onClick={() => router.back()}
            style={{
              padding: '10px 16px',
              background: 'none',
              color: 'var(--ink-muted)',
              border: '1px solid var(--border)',
              borderRadius: 'var(--r-md)',
              fontSize: 14,
              cursor: 'pointer',
            }}
          >
            Cancel
          </button>
        </div>
      </div>

      {/* Nutrition sidebar */}
      <div style={{ paddingTop: 8 }}>
        <NutritionDisplay
          nutrition={existing?.perServingNutrition ?? null}
          warnings={existing?.warnings ?? []}
        />
        <p style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 10, lineHeight: 1.5 }}>
          Nutrition is calculated server-side when you save. Link ingredients to products in the
          product library for accurate data.
        </p>
      </div>
    </form>
  );
}
