import { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { createRecipe, importRecipeFromUrl } from '../services/api';
import type { RecipeDraft, UrlImportResult } from '../types/recipe';
import { UiButton, UiCard, UiChip, UiPage, UiSection } from '../components/ui/primitives';

type ImportErrorType = 'invalid-url' | 'parse-failure' | 'timeout' | 'generic';
type ImportStage = 'idle' | 'fetching' | 'parsing' | 'review' | 'saving' | 'done' | 'error';

function toTextBlock(items: string[]): string {
  return items.join('\n');
}

function toList(text: string): string[] {
  return text
    .split('\n')
    .map((line) => line.trim())
    .filter((line) => line.length > 0);
}

function getImportErrorDetails(message: string): { type: ImportErrorType; message: string } {
  const normalized = message.toLowerCase();
  if (normalized.includes('valid url')) {
    return {
      type: 'invalid-url',
      message: 'Please enter a valid URL (including https://).',
    };
  }
  if (normalized.includes('timed out')) {
    return {
      type: 'timeout',
      message: 'The import request timed out. Please try again in a moment.',
    };
  }
  if (normalized.includes('network error') || normalized.includes('could not fetch the page')) {
    return {
      type: 'generic',
      message: 'We could not reach that recipe page right now. Please try again in a moment.',
    };
  }
  if (normalized.includes('did not return an html page')) {
    return {
      type: 'generic',
      message: 'That link did not point to an HTML recipe page. Try the direct recipe URL.',
    };
  }
  return {
    type: 'generic',
    message,
  };
}

function draftIngredientsToStringArray(ingredients: RecipeDraft['ingredients']): string[] {
  if (!Array.isArray(ingredients)) return [];
  return ingredients.map((x) =>
    x && typeof x === 'object' && typeof x.item === 'string' ? x.item : String(x),
  );
}

function ingredientStringsToDraftArray(strings: string[]): RecipeDraft['ingredients'] {
  return strings.map((s) => ({ item: s, quantity: null, unit: null, notes: null }));
}

function stageProgress(stage: ImportStage): number {
  switch (stage) {
    case 'fetching':
      return 25;
    case 'parsing':
      return 60;
    case 'review':
      return 80;
    case 'saving':
      return 95;
    case 'done':
      return 100;
    default:
      return 0;
  }
}

export function ImportUrlPage() {
  const navigate = useNavigate();
  const [url, setUrl] = useState<string>('');
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);
  const [errorType, setErrorType] = useState<ImportErrorType | null>(null);
  const [result, setResult] = useState<UrlImportResult | null>(null);
  const [ingredientLines, setIngredientLines] = useState<string[]>([]);
  const [instructionLines, setInstructionLines] = useState<string[]>([]);
  const [draft, setDraft] = useState<RecipeDraft | null>(null);
  const [draftError, setDraftError] = useState<string | null>(null);
  const [isSaving, setIsSaving] = useState<boolean>(false);
  const [stage, setStage] = useState<ImportStage>('idle');

  useEffect(() => {
    if (draft) {
      setIngredientLines(draftIngredientsToStringArray(draft.ingredients));
      setInstructionLines(Array.isArray(draft.instructions) ? draft.instructions.filter(Boolean) : []);
    } else {
      setIngredientLines([]);
      setInstructionLines([]);
    }
  }, [draft]);

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setLoading(true);
    setError(null);
    setErrorType(null);
    setResult(null);
    setDraft(null);
    setDraftError(null);
    setStage('fetching');

    try {
      setTimeout(() => setStage((current) => (current === 'fetching' ? 'parsing' : current)), 450);
      const imported: UrlImportResult = await importRecipeFromUrl(url);
      setResult(imported);
      const importedDraft = imported.draft_recipe ?? null;
      setDraft(importedDraft);
      setStage('review');
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Failed to import recipe URL';
      const details = getImportErrorDetails(message);
      setErrorType(details.type);
      setError(details.message);
      setStage('error');
    } finally {
      setLoading(false);
    }
  };

  const handleSave = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!draft) {
      setDraftError('No draft recipe to save.');
      return;
    }

    const title = draft.title.trim();
    const ingredients = ingredientStringsToDraftArray(ingredientLines.filter(Boolean));
    const instructions = instructionLines.filter(Boolean);

    if (!title) {
      setDraftError('Title is required.');
      return;
    }
    if (ingredients.length === 0) {
      setDraftError('At least one ingredient is required.');
      return;
    }
    if (instructions.length === 0) {
      setDraftError('At least one instruction step is required.');
      return;
    }

    setIsSaving(true);
    setDraftError(null);
    setStage('saving');
    try {
      const created = await createRecipe({ ...draft, title, ingredients, instructions });
      setStage('done');
      navigate(`/recipe/${created.id}`);
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Failed to save recipe';
      setDraftError(message);
      setStage('error');
      setIsSaving(false);
    }
  };

  const progress = stageProgress(stage);
  const stageOrder: ImportStage[] = ['idle', 'fetching', 'parsing', 'review', 'saving', 'done', 'error'];
  const activeIndex = stageOrder.indexOf(stage);

  return (
    <UiPage className="mx-auto max-w-3xl py-8">
      <UiSection className="relative mb-8 overflow-hidden" padding="lg">
        <div className="absolute inset-x-0 top-0 h-24 bg-gradient-to-r from-[var(--color-primary-soft)] via-[var(--surface-muted)] to-[var(--surface-elevated)]" />
        <div className="relative">
          <div className="mb-5 flex items-start justify-between gap-4">
            <div>
              <p className="text-xs font-semibold uppercase tracking-wider text-[var(--color-primary)]">Smart Import</p>
              <h2 className="text-3xl font-bold text-[var(--text-h)]">Import from URL</h2>
              <p className="mt-1 text-[var(--text-dim)]">
                Paste a recipe URL and we'll fetch, parse, and prep it for your cookbook.
              </p>
            </div>
            <div className="hidden rounded-xl border border-[var(--border)] bg-white/70 p-4 text-3xl md:block">🔎</div>
          </div>

          <UiCard tone="muted" className="mb-5 p-3">
            <div className="mb-2 flex items-center justify-between text-sm">
              <span className="font-semibold text-[var(--text)]">Import Progress</span>
              <span className="text-[var(--text-dim)]">{progress}%</span>
            </div>
            <div className="h-2 overflow-hidden rounded-full bg-[var(--border)]">
              <div
                className="h-full rounded-full bg-gradient-to-r from-[var(--color-primary)] to-[var(--color-primary-dark)] transition-all duration-500"
                style={{ width: `${progress}%` }}
              />
            </div>
            <div className="mt-3 grid grid-cols-2 gap-2 text-xs sm:grid-cols-4">
              {[
                { key: 'fetching', label: 'Fetch page' },
                { key: 'parsing', label: 'Parse data' },
                { key: 'review', label: 'Review draft' },
                { key: 'saving', label: 'Save recipe' },
              ].map((step, index) => {
                const stepIndex = index + 1;
                const done = stage === 'done' || activeIndex > stepIndex;
                const active = activeIndex === stepIndex;

                return (
                  <div
                    key={step.key}
                    className={`rounded-md border px-2 py-1.5 ${
                      done
                        ? 'border-[var(--success-border)] bg-[var(--success-bg)] text-[var(--success-text)]'
                        : active
                          ? 'border-[var(--border-focus)] bg-[var(--color-primary-soft)] text-[var(--color-primary)]'
                          : 'border-[var(--border)] bg-white text-[var(--text-muted)]'
                    }`}
                  >
                    {done ? '✓ ' : active ? '● ' : '○ '} {step.label}
                  </div>
                );
              })}
            </div>
          </UiCard>

          <form onSubmit={handleSubmit} className="space-y-4">
            <div>
              <label htmlFor="import-url" className="mb-2 block text-sm font-medium text-[var(--text)]">
                Recipe URL
              </label>
              <input
                id="import-url"
                type="url"
                required
                value={url}
                onChange={(event) => setUrl(event.target.value)}
                placeholder="https://example.com/my-recipe"
                className="ui-input"
              />
            </div>
            <UiButton type="submit" variant="primary" disabled={loading} className="disabled:cursor-not-allowed disabled:opacity-50">
              {loading ? 'Importing…' : '🔗 Import URL'}
            </UiButton>
          </form>

          {error && (
            <div
              className={`mt-6 rounded-lg border p-4 ${
                errorType === 'parse-failure'
                  ? 'border-[var(--warning-border)] bg-[var(--warning-bg)]'
                  : 'border-[var(--danger-border)] bg-[var(--danger-bg)]'
              }`}
            >
              <p className={errorType === 'parse-failure' ? 'text-[var(--warning-text)]' : 'text-[var(--danger-text)]'}>
                <strong>
                  {errorType === 'invalid-url' && 'Invalid URL:'}
                  {errorType === 'timeout' && 'Import timed out:'}
                  {errorType === 'parse-failure' && 'Parse failed:'}
                  {errorType === 'generic' && 'Error:'}
                </strong>{' '}
                {error}
              </p>
            </div>
          )}
        </div>
      </UiSection>

      {result && (
        <UiSection className="mb-7 mt-1 space-y-5" padding="lg">
          <UiCard className="bg-[var(--surface-muted)] p-4">
            <h3 className="font-semibold text-[var(--text-h)]">Parsed Preview</h3>
            <p className="text-sm text-[var(--text-dim)]">Source: {result.source_url}</p>
            <p className="text-sm text-[var(--text-dim)]">
              JSON-LD blocks found: {Array.isArray(result.json_ld_blocks) ? result.json_ld_blocks.length : 0}
            </p>
          </UiCard>

          {draft ? (
            <form onSubmit={handleSave} className="space-y-5">
              <p className="text-sm text-[var(--text-dim)]">Review and edit before saving.</p>
              {draftError && (
                <div className="mb-2 rounded-lg border border-[var(--danger-border)] bg-[var(--danger-bg)] p-3 text-sm text-[var(--danger-text)]">
                  {draftError}
                </div>
              )}

              <div>
                <label htmlFor="draft-title" className="mb-1 block text-sm font-medium text-[var(--text)]">Title</label>
                <input
                  id="draft-title"
                  type="text"
                  required
                  value={draft.title}
                  onChange={(event) => setDraft({ ...draft, title: event.target.value })}
                  className="ui-input"
                />
              </div>

              <div>
                <label htmlFor="draft-ingredients" className="mb-1 block text-sm font-medium text-[var(--text)]">
                  Ingredients (one per line)
                </label>
                <textarea
                  id="draft-ingredients"
                  rows={8}
                  value={toTextBlock(ingredientLines)}
                  onChange={(e) => setIngredientLines(toList(e.target.value))}
                  className="ui-textarea"
                />
              </div>

              <div>
                <label htmlFor="draft-instructions" className="mb-1 block text-sm font-medium text-[var(--text)]">
                  Steps (one per line)
                </label>
                <textarea
                  id="draft-instructions"
                  rows={10}
                  value={toTextBlock(instructionLines)}
                  onChange={(e) => setInstructionLines(toList(e.target.value))}
                  className="ui-textarea"
                />
              </div>

              <div>
                <label htmlFor="draft-source-url" className="mb-1 block text-sm font-medium text-[var(--text)]">
                  Source URL
                </label>
                <input
                  id="draft-source-url"
                  type="url"
                  value={draft.source_url ?? ''}
                  onChange={(event) =>
                    setDraft({
                      ...draft,
                      source_url: event.target.value.trim() ? event.target.value : undefined,
                    })
                  }
                  className="ui-input"
                />
              </div>

              <div className="mt-2 flex flex-wrap gap-3">
                <UiButton type="submit" variant="primary" disabled={isSaving} className="disabled:cursor-not-allowed disabled:opacity-50">
                  {isSaving ? 'Saving…' : '💾 Save Recipe'}
                </UiButton>
                <Link to="/recipe/new" className="ui-btn ui-btn-secondary">📝 Open full editor</Link>
              </div>
            </form>
          ) : (
            <UiChip className="border-[var(--warning-border)] bg-[var(--warning-bg)] text-[var(--warning-text)]">
              Could not parse a recipe preview from this URL.
            </UiChip>
          )}
        </UiSection>
      )}
    </UiPage>
  );
}
