/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable import/no-named-as-default-member */
/* eslint-disable no-empty */
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
import Papa from 'papaparse';
import * as XLSX from 'xlsx';

import { recomaze_ai_personalization_env } from '../env';
import { useAppStateContext } from '../context/user.data.context';
import {
  getActiveContentGenJob,
  submitContentGenJob,
  getContentGenStatus,
  getContentGenUsage,
  improvePrompt,
  detectContentGenColumns,
  listPromptTemplates,
} from '../service/content-generator/content-generator.service';
import {
  clearCachedJobId,
  clearCachedJobSnapshot,
  loadCachedJobId,
  loadCachedJobSnapshot,
  saveCachedJobId,
  saveCachedJobSnapshot,
} from '../service/content-generator/job-cache';
import type {
  ContentGeneratorProduct,
  ContentGenerateFields,
  FieldPrompts,
  ContentGeneratorStatusResponse,
  ContentGeneratorUsage,
  DetectColumnsResponse,
  PromptTemplate,
} from '../service/content-generator/content-generator.interface';
import { LANGUAGE_OPTIONS as LANGUAGES } from '../data/locales';
import Button from '../components/widgets/Button';
import SearchableSelect from '../components/widgets/SearchableSelect';
import ErrorWrapper from '../components/alert/ErrorWrapper';
import PromptTemplates from '../components/content-generator/PromptTemplates';

const TONES = [
  { value: 'professional', label: 'Professional' },
  { value: 'friendly', label: 'Friendly' },
  { value: 'luxury', label: 'Luxury' },
  { value: 'technical', label: 'Technical' },
  { value: 'custom', label: 'Custom' },
];

const FIELD_LABELS: Record<keyof ContentGenerateFields, string> = {
  titles: 'Titles',
  descriptions: 'Descriptions',
  tags: 'Tags',
  faq: 'FAQ (Frequently Asked Questions)',
};

const FIELD_HELP: Record<keyof ContentGenerateFields, string> = {
  titles: 'Optimize product names for click-through rate.',
  descriptions: 'Generate rich, benefit-focused product copy.',
  tags: 'Generate relevant keywords for searchability.',
  faq: 'Generate Q&A pairs based on product information.',
};

const FIELD_PLACEHOLDERS: Record<keyof FieldPrompts, string> = {
  titles:
    'e.g., Always start with the brand name, max 70 characters, include main keyword...',
  descriptions:
    'e.g., Include a benefits section, mention free shipping, use bullet points, max 200 words...',
  tags: 'e.g., Include seasonal tags, max 8 tags, comma-separated...',
  faq: 'e.g., Focus on shipping and returns questions, 3-5 Q&A pairs...',
};

const POLL_INTERVAL = 3000;

const parseCSV = (text: string): string[][] => {
  const cleaned = text.replace(/^\ufeff/, '');
  const result = Papa.parse<string[]>(cleaned, {
    skipEmptyLines: true,
    delimitersToGuess: [',', ';', '\t', '|'],
  });
  return (result.data || []).map(row =>
    row.map(cell => (cell ?? '').toString().trim())
  );
};

const parseXLSX = (buffer: ArrayBuffer): string[][] => {
  const workbook = XLSX.read(buffer, { type: 'array' });
  const firstSheetName = workbook.SheetNames[0];
  if (!firstSheetName) return [];
  const sheet = workbook.Sheets[firstSheetName];
  const matrix = XLSX.utils.sheet_to_json<unknown[]>(sheet, {
    header: 1,
    defval: '',
    blankrows: false,
  });
  return matrix.map(row => row.map(cell => (cell ?? '').toString().trim()));
};

type ColumnMapping = {
  product_id: number;
  sku: number;
  title: number;
  description: number;
  tags: number;
  product_url: number;
  category: number;
};

const autoDetectColumns = (header: string[]): ColumnMapping | null => {
  const lower = header.map(h => h.toLowerCase().replace(/[^a-z0-9_]/g, '_'));

  const find = (needles: string[]): number =>
    lower.findIndex(h => needles.some(n => h.includes(n)));

  const productIdIdx = find(['product_id', 'product_id', 'product id']);
  const skuIdx = find(['sku', 'variant_sku', 'variant sku']);
  const titleIdx = find([
    'title',
    'name',
    'product_title',
    'product title',
    'product_name',
  ]);
  const descIdx = find(['description', 'body_html', 'body html', 'desc']);
  const tagsIdx = find(['tag', 'keyword']);
  const urlIdx = find([
    'url',
    'handle',
    'slug',
    'link',
    'custom_url',
    'product_url',
  ]);
  const categoryIdx = find(['categor', 'collection']);

  if (titleIdx === -1) return null;

  return {
    product_id: productIdIdx,
    sku: skuIdx,
    title: titleIdx,
    description: descIdx,
    tags: tagsIdx,
    product_url: urlIdx,
    category: categoryIdx,
  };
};

const ContentGeneratorPage = (): JSX.Element => {
  const { clientId, user } = useAppStateContext();
  const fileInputRef = useRef<HTMLInputElement>(null);

  const [activeTab, setActiveTab] = useState<'generator' | 'templates'>(
    'generator'
  );
  const [step, setStep] = useState(0);

  const [backupLoading, setBackupLoading] = useState(false);
  const [backupError, setBackupError] = useState<string | null>(null);
  const [backupDone, setBackupDone] = useState(false);
  const [categories, setCategories] = useState<
    { id: number; name: string; count: number }[]
  >([]);
  const [selectedCategory, setSelectedCategory] = useState('all');

  const [fileName, setFileName] = useState('');
  const [products, setProducts] = useState<ContentGeneratorProduct[]>([]);
  const [uploadError, setUploadError] = useState<string | null>(null);

  const [tone, setTone] = useState('professional');
  const [language, setLanguage] = useState('en');
  // Additional languages (max 2) for multi-language fan-out. Total stays at 3
  // on the agent side.
  const [additionalLanguages, setAdditionalLanguages] = useState<string[]>([]);
  // Output shape for multi-language jobs (single merged CSV vs one per
  // language). Irrelevant when only one language is picked.
  const [bundleOutput, setBundleOutput] = useState<'single' | 'per_language'>(
    'single'
  );
  const [temperature, setTemperature] = useState(0.7);
  const [fields, setFields] = useState<ContentGenerateFields>({
    titles: true,
    descriptions: true,
    tags: true,
    faq: false,
  });
  const [fieldPrompts, setFieldPrompts] = useState<FieldPrompts>({
    titles: '',
    descriptions: '',
    tags: '',
    faq: '',
  });
  const [faqInDescription, setFaqInDescription] = useState(true);
  const [email, setEmail] = useState(user?.email ?? '');
  const [improvingField, setImprovingField] = useState<string | null>(null);

  const [jobStatus, setJobStatus] =
    useState<ContentGeneratorStatusResponse | null>(null);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const pollRef = useRef<NodeJS.Timeout | null>(null);

  /**
   * Poll the agent's job status every 3s until the job leaves the
   * ``pending`` / ``processing`` window. Idempotent: clears any previous
   * interval before scheduling a new one. Mirrors the Shopify plugin's
   * pattern - on 404 / network error the agent has already deleted the
   * status snapshot (terminal cleanup releases the per-merchant lock), so
   * we synthesise a ``completed`` frame from the last known status
   * instead of freezing on PENDING.
   *
   * @param {string} jobId
   * @return {void}
   */
  const startPolling = useCallback(
    (jobId: string): void => {
      if (!clientId) return;
      if (pollRef.current) {
        clearInterval(pollRef.current);
        pollRef.current = null;
      }
      const refreshUsage = (): void => {
        const plan: string = user?.plan_snapshot || user?.plan || 'FREE';
        getContentGenUsage(plan, clientId)
          .then(res => {
            if (res?.data) setUsage(res.data);
          })
          .catch(() => {});
      };
      const finishPolling = (): void => {
        if (pollRef.current) {
          clearInterval(pollRef.current);
          pollRef.current = null;
        }
        clearCachedJobId(clientId);
      };
      const tick = async (): Promise<void> => {
        const res = await getContentGenStatus(jobId, clientId).catch(
          () => null
        );
        const status: ContentGeneratorStatusResponse | undefined = res?.data;
        const errored: boolean = !res || !!(res as { error?: string })?.error;
        if (errored || !status) {
          // /status returns 404 once terminal cleanup wipes the Redis
          // blob. Synthesise the completed frame from the last known
          // status so the UI flips out of PENDING.
          finishPolling();
          setJobStatus(previous => {
            if (
              !previous ||
              (previous.state !== 'pending' && previous.state !== 'processing')
            ) {
              return previous;
            }
            const synthesised: ContentGeneratorStatusResponse = {
              ...previous,
              state: 'completed',
              progress: 100,
              processed_count: previous.total_count || previous.processed_count,
            };
            saveCachedJobSnapshot(clientId, synthesised);
            return synthesised;
          });
          refreshUsage();
          return;
        }
        setJobStatus(status);
        if (status.state === 'completed' || status.state === 'failed') {
          finishPolling();
          saveCachedJobSnapshot(clientId, status);
          if (status.state === 'completed') refreshUsage();
        }
      };
      tick();
      pollRef.current = setInterval(tick, 3000);
    },
    [clientId, user?.plan_snapshot, user?.plan]
  );

  useEffect(
    () => () => {
      if (pollRef.current) {
        clearInterval(pollRef.current);
        pollRef.current = null;
      }
    },
    []
  );

  // Resume polling for an in-flight job after a refresh - getActiveContentGenJob
  // wakes the page back into step 3, but the previous mount's setInterval is
  // gone, so we need to schedule a fresh one keyed on the surfaced job_id.
  useEffect(() => {
    if (!clientId) return;
    if (!jobStatus?.job_id) return;
    if (pollRef.current) return;
    if (jobStatus.state !== 'pending' && jobStatus.state !== 'processing')
      return;
    startPolling(jobStatus.job_id);
  }, [clientId, jobStatus?.job_id, jobStatus?.state, startPolling]);

  const [usage, setUsage] = useState<ContentGeneratorUsage | null>(null);

  const [dataRowsForDetect, setDataRowsForDetect] = useState<string[][]>([]);
  const [headersForDetect, setHeadersForDetect] = useState<string[]>([]);

  const [promptTemplates, setPromptTemplates] = useState<PromptTemplate[]>([]);
  const [templatesLoaded, setTemplatesLoaded] = useState(false);
  const [selectedTemplateId, setSelectedTemplateId] = useState<string>('');

  const apiBase = recomaze_ai_personalization_env?.wp_api_url;
  const nonce = recomaze_ai_personalization_env?.nonce;

  useEffect(() => {
    if (!clientId) return;
    const plan = user?.plan_snapshot || user?.plan || 'free';
    getContentGenUsage(plan, clientId).then(res => {
      if (res?.data) setUsage(res.data);
    });
  }, [clientId, user?.plan_snapshot, user?.plan]);

  // On mount, ask the agent whether there's an in-flight job for this
  // merchant. If yes, surface it on step 3 so the page resumes the
  // progress bar; the polling-resume effect below picks up from there.
  // If /active is inactive (job already completed and Redis lock released),
  // fall back to the cached terminal snapshot so the merchant still lands
  // on the "Job Complete" card after a refresh or tab change instead of
  // being dumped back to step 0.
  useEffect(() => {
    if (!clientId) return;
    let cancelled: boolean = false;
    (async () => {
      try {
        const res = await getActiveContentGenJob(clientId);
        if (cancelled) return;
        const activePayload = res?.data;
        if (activePayload?.active && activePayload.status) {
          setJobStatus(activePayload.status);
          saveCachedJobId(clientId, activePayload.status.job_id);
          setStep(3);
          return;
        }
        if (loadCachedJobId(clientId)) clearCachedJobId(clientId);
        const snapshot = loadCachedJobSnapshot(clientId);
        if (snapshot) {
          setJobStatus(snapshot);
          setStep(3);
        }
      } catch {
        /* network / auth error - leave the cache alone, retry next mount */
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [clientId]);

  useEffect(() => {
    if (!apiBase || !nonce) return;
    fetch(`${apiBase}recomaze/v1/product-categories`, {
      headers: { 'X-WP-Nonce': nonce },
    })
      .then(r => r.json())
      .then(data => {
        if (data?.categories) setCategories(data.categories);
      })
      .catch(() => {});
  }, [apiBase, nonce]);

  useEffect(() => {
    return () => {
      if (pollRef.current) clearInterval(pollRef.current);
    };
  }, []);

  useEffect(() => {
    if (step !== 2 || templatesLoaded || !clientId) return;
    setTemplatesLoaded(true);
    listPromptTemplates(clientId).then(res => {
      if (res?.data?.templates) setPromptTemplates(res.data.templates);
    });
  }, [step, templatesLoaded, clientId]);

  const downloadBackup = async () => {
    if (!apiBase || !nonce) {
      setBackupError('Missing WordPress API configuration.');
      return;
    }
    try {
      setBackupLoading(true);
      setBackupError(null);
      const backupUrl =
        selectedCategory === 'all'
          ? `${apiBase}recomaze/v1/product-improvements/backup`
          : `${apiBase}recomaze/v1/product-improvements/backup?category=${selectedCategory}`;
      const resp = await fetch(backupUrl, {
        headers: { 'X-WP-Nonce': nonce },
      });
      if (!resp.ok) {
        const data = await resp.json().catch(() => ({}));
        throw new Error(data?.error || 'Failed to download backup.');
      }
      const raw = await resp.text();
      let csv: string;
      try {
        const parsed = JSON.parse(raw);
        csv = typeof parsed === 'string' ? parsed : raw;
      } catch {
        csv = raw;
      }
      const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      const catLabel =
        selectedCategory !== 'all'
          ? categories.find(c => String(c.id) === selectedCategory)?.name
          : '';
      a.download = catLabel
        ? `product_backup_${catLabel.replace(/[^a-zA-Z0-9_-]/g, '_')}.csv`
        : 'product_backup.csv';
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
      setBackupDone(true);
    } catch (err: any) {
      setBackupError(err?.message || 'Failed to download backup.');
    } finally {
      setBackupLoading(false);
    }
  };

  const applyAIColumnMapping = useCallback(
    (
      ai: DetectColumnsResponse,
      currentMapping: ColumnMapping,
      headers: string[]
    ): ColumnMapping => {
      const lower = headers.map(h => h.toLowerCase().trim());
      const findHeader = (aiValue: string | null): number => {
        if (!aiValue) return -1;
        const exact = lower.indexOf(aiValue.toLowerCase().trim());
        if (exact !== -1) return exact;
        return lower.findIndex(h => h.includes(aiValue.toLowerCase().trim()));
      };
      return {
        product_id: currentMapping.product_id,
        sku: ai.sku ? findHeader(ai.sku) : currentMapping.sku,
        title: ai.title ? findHeader(ai.title) : currentMapping.title,
        description: ai.description
          ? findHeader(ai.description)
          : currentMapping.description,
        tags: ai.tags ? findHeader(ai.tags) : currentMapping.tags,
        product_url: ai.handle
          ? findHeader(ai.handle)
          : currentMapping.product_url,
        category: ai.collection
          ? findHeader(ai.collection)
          : currentMapping.category,
      };
    },
    []
  );

  const requestAIColumnDetection = useCallback(
    (headers: string[], dataRows: string[][], staticMapping: ColumnMapping) => {
      if (!clientId) return;
      const sampleRows = dataRows.slice(0, 5).map(row => {
        const obj: Record<string, string> = {};
        headers.forEach((h, i) => {
          obj[h] = row[i] ?? '';
        });
        return obj;
      });
      detectContentGenColumns({ headers, sample_rows: sampleRows }, clientId)
        .then(res => {
          const ai = res?.data;
          if (!ai) return;
          const aiMapping = applyAIColumnMapping(ai, staticMapping, headers);
          setProducts(prev => {
            const parsed: ContentGeneratorProduct[] = [];
            setDataRowsForDetect(currentRows => {
              for (let i = 0; i < currentRows.length; i++) {
                const r = currentRows[i];
                const title =
                  aiMapping.title >= 0 ? r[aiMapping.title] || '' : '';
                if (!title) continue;
                parsed.push({
                  row_index: i + 1,
                  product_id:
                    aiMapping.product_id >= 0
                      ? r[aiMapping.product_id] || ''
                      : '',
                  sku: aiMapping.sku >= 0 ? r[aiMapping.sku] || '' : '',
                  title,
                  description:
                    aiMapping.description >= 0
                      ? r[aiMapping.description] || ''
                      : '',
                  tags: aiMapping.tags >= 0 ? r[aiMapping.tags] || '' : '',
                  product_url:
                    aiMapping.product_url >= 0
                      ? r[aiMapping.product_url] || ''
                      : '',
                  category:
                    aiMapping.category >= 0 ? r[aiMapping.category] || '' : '',
                });
              }
              return currentRows;
            });
            return parsed.length > 0 ? parsed : prev;
          });
        })
        .catch(() => {});
    },
    [clientId, applyAIColumnMapping]
  );

  const handleParsedRows = useCallback(
    (rows: string[][], uploadedFileName: string) => {
      if (rows.length < 2) {
        setUploadError(
          'File must have a header row and at least one data row.'
        );
        return;
      }

      const mapping = autoDetectColumns(rows[0]);
      if (!mapping) {
        setUploadError(
          'Could not detect columns. Ensure your file has at least a "Title" column.'
        );
        return;
      }

      const dataRows = rows.slice(1);
      const parsed: ContentGeneratorProduct[] = [];
      for (let i = 0; i < dataRows.length; i++) {
        const r = dataRows[i];
        const title = mapping.title >= 0 ? r[mapping.title] || '' : '';
        if (!title) continue;
        parsed.push({
          row_index: i + 1,
          product_id:
            mapping.product_id >= 0 ? r[mapping.product_id] || '' : '',
          sku: mapping.sku >= 0 ? r[mapping.sku] || '' : '',
          title,
          description:
            mapping.description >= 0 ? r[mapping.description] || '' : '',
          tags: mapping.tags >= 0 ? r[mapping.tags] || '' : '',
          product_url:
            mapping.product_url >= 0 ? r[mapping.product_url] || '' : '',
          category: mapping.category >= 0 ? r[mapping.category] || '' : '',
        });
      }

      if (!parsed.length) {
        setUploadError('No valid product rows found.');
        return;
      }

      setDataRowsForDetect(dataRows);
      setHeadersForDetect(rows[0]);
      setProducts(parsed);
      setFileName(uploadedFileName);
      setStep(1);

      requestAIColumnDetection(rows[0], dataRows, mapping);
    },
    [requestAIColumnDetection]
  );

  const handleFileUpload = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file) return;

      setUploadError(null);
      const ext = file.name.split('.').pop()?.toLowerCase();

      if (ext === 'xlsx' || ext === 'xls') {
        const buffer = await file.arrayBuffer();
        const rows = parseXLSX(buffer);
        handleParsedRows(rows, file.name);
        return;
      }

      let text = await file.text();
      try {
        const parsedJson = JSON.parse(text);
        if (typeof parsedJson === 'string') text = parsedJson;
      } catch {}
      const rows = parseCSV(text);
      handleParsedRows(rows, file.name);
    },
    [handleParsedRows]
  );

  const handleApplyTemplate = useCallback(
    (templateId: string) => {
      const template = promptTemplates.find(t => t.template_id === templateId);
      if (!template) return;
      setSelectedTemplateId(templateId);
      setFieldPrompts({
        titles: template.titles_prompt ?? '',
        descriptions: template.descriptions_prompt ?? '',
        tags: template.tags_prompt ?? '',
        faq: template.faq_prompt ?? '',
      });
      setLanguage(template.language ?? 'en');
      setTone(template.tone ?? 'professional');
      setTemperature(template.temperature ?? 0.7);
    },
    [promptTemplates]
  );

  const handleImprovePrompt = async (field: keyof FieldPrompts) => {
    if (!clientId) return;
    const current = fieldPrompts[field];
    if (!current.trim()) return;

    setImprovingField(field);
    try {
      const res = await improvePrompt(current, field, language, clientId);
      const improved = res?.data?.improved_prompt;
      if (improved) {
        setFieldPrompts(prev => ({
          ...prev,
          [field]: improved,
        }));
      }
    } catch {
    } finally {
      setImprovingField(null);
    }
  };

  const handleSubmit = async () => {
    if (!clientId || !products.length) return;

    setSubmitting(true);
    setSubmitError(null);
    setJobStatus(null);

    try {
      const plan = user?.plan_snapshot || user?.plan || 'FREE';
      // When the merchant picked extra languages, send the full list (primary +
      // extras) on `languages` so the agent fans out per language. Single-
      // language jobs leave `languages` undefined and keep the legacy single-CSV
      // pipeline untouched.
      const dedupedLanguages: string[] = [];
      const seenLanguageCodes = new Set<string>();
      for (const code of [language, ...additionalLanguages]) {
        const normalized = (code || '').trim().toLowerCase();
        if (normalized && !seenLanguageCodes.has(normalized)) {
          seenLanguageCodes.add(normalized);
          dedupedLanguages.push(normalized);
        }
      }
      const languagesPayload =
        dedupedLanguages.length > 1 ? dedupedLanguages : undefined;

      const res = await submitContentGenJob(
        {
          products,
          config: {
            platform: 'woocommerce',
            tone,
            language,
            languages: languagesPayload,
            // Only send bundle_output when multi-language fan-out is on.
            bundle_output: languagesPayload ? bundleOutput : undefined,
            temperature,
            generate_fields: fields,
            field_prompts: fieldPrompts,
            faq_in_description: fields.faq ? faqInDescription : undefined,
          },
          email,
          plan,
        },
        clientId
      );

      if (res?.error || res?.errors) {
        // Submit rejected — could be 409 (a job is already running). Re-check
        // via /active and hydrate the UI to that job instead of erroring out.
        const activeRes = await getActiveContentGenJob(clientId);
        const activePayload = activeRes?.data;
        if (activePayload?.active && activePayload.status) {
          setJobStatus(activePayload.status);
          saveCachedJobId(clientId, activePayload.status.job_id);
          setStep(3);
          startPolling(activePayload.status.job_id);
          return;
        }
        throw new Error(
          (res.error || String(res.errors) || 'Failed to submit job') as string
        );
      }

      const jobId = res?.data?.job_id;
      if (!jobId) throw new Error('No job ID returned.');

      setJobStatus({
        job_id: jobId,
        state: 'pending',
        progress: 0,
        total_count: products.length,
        processed_count: 0,
      });
      saveCachedJobId(clientId, jobId);
      setStep(3);
      startPolling(jobId);
    } catch (err: any) {
      setSubmitError(err?.message || 'Failed to submit generation job.');
    } finally {
      setSubmitting(false);
    }
  };

  const progressPct = jobStatus?.progress ?? 0;

  const resetWizard = () => {
    setStep(0);
    setProducts([]);
    setFileName('');
    setJobStatus(null);
    setBackupDone(false);
    setSubmitError(null);
    setUploadError(null);
    setDataRowsForDetect([]);
    setHeadersForDetect([]);
    setSelectedTemplateId('');
    if (clientId) clearCachedJobSnapshot(clientId);
  };

  const planName = user?.plan_snapshot || user?.plan || 'Free';
  const WIZARD_STEPS = ['Backup', 'Upload', 'Configure', 'Generate'];

  return (
    <div className="mx-auto w-full max-w-5xl space-y-8 bg-white p-6 md:p-10">
      <header>
        <h1 className="text-xl font-medium tracking-tight text-gray-900 md:text-2xl">
          AI Content Generator
        </h1>
        <p className="mt-2 text-sm text-gray-500">
          Generate optimized titles, descriptions, tags, and FAQs for your
          products.
        </p>
      </header>

      <div className="border-b border-gray-200">
        <div className="flex gap-4">
          {[
            { key: 'generator', label: 'Content Generator' },
            { key: 'templates', label: 'Prompt Templates' },
          ].map(tab => (
            <button
              key={tab.key}
              type="button"
              onClick={() => setActiveTab(tab.key as 'generator' | 'templates')}
              className={`px-3 py-2.5 text-sm font-medium border-b-2 -mb-px ${
                activeTab === tab.key
                  ? 'border-gray-900 text-gray-900'
                  : 'border-transparent text-gray-500 hover:text-gray-700'
              }`}
            >
              {tab.label}
            </button>
          ))}
        </div>
      </div>

      {activeTab === 'templates' && <PromptTemplates />}

      {activeTab === 'generator' && (
        <>
          {usage && (
            <div className="flex flex-col gap-4 rounded-lg border border-gray-200 bg-gray-50 p-5 md:flex-row md:items-center md:justify-between">
              <div>
                <h3 className="text-sm font-medium text-gray-900">
                  Monthly Usage limit
                </h3>
                <p className="mt-1 text-xs text-gray-500">
                  {usage.remaining > 0
                    ? `You can generate content for ${usage.remaining} more product(s) this month on your ${planName} plan.`
                    : `You've reached your monthly limit on the ${planName} plan. Upgrade to generate more content.`}
                </p>
              </div>
              <div className="flex shrink-0 items-center gap-4">
                <div className="h-2 w-32 overflow-hidden rounded-full bg-gray-200">
                  <div
                    className="h-full bg-gray-900"
                    style={{
                      width: `${Math.min((usage.used / usage.limit) * 100, 100)}%`,
                    }}
                  />
                </div>
                <span className="text-xs font-medium text-gray-900">
                  {usage.used} / {usage.limit}
                </span>
              </div>
            </div>
          )}

          <div className="relative">
            <div className="absolute left-0 top-1/2 h-0.5 w-full -translate-y-1/2 bg-gray-100" />
            <div className="relative flex justify-between">
              {WIZARD_STEPS.map((label, idx) => {
                const isActive = step === idx;
                const isCompleted = step > idx;

                return (
                  <div key={label} className="flex flex-col items-center gap-2">
                    <div
                      className={`flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold ring-4 ring-white ${
                        isActive
                          ? 'bg-gray-900 text-white'
                          : isCompleted
                            ? 'bg-gray-200 text-gray-900'
                            : 'bg-gray-50 text-gray-400 border border-gray-200'
                      }`}
                    >
                      {isCompleted ? (
                        <svg
                          className="h-4 w-4"
                          fill="none"
                          viewBox="0 0 24 24"
                          stroke="currentColor"
                          strokeWidth={2.5}
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M5 13l4 4L19 7"
                          />
                        </svg>
                      ) : (
                        idx + 1
                      )}
                    </div>
                    <span
                      className={`text-[11px] font-medium uppercase tracking-wider ${isActive ? 'text-gray-900' : 'text-gray-400'}`}
                    >
                      {label}
                    </span>
                  </div>
                );
              })}
            </div>
          </div>

          <div className="rounded-lg border border-gray-200 bg-white">
            {step === 0 && (
              <section>
                <header className="border-b border-gray-100 bg-gray-50/50 px-6 py-5">
                  <h2 className="text-sm font-medium text-gray-900">
                    Download Product Backup
                  </h2>
                  <p className="mt-0.5 text-xs text-gray-500">
                    Highly recommended before generating new content so you can
                    revert changes if needed.
                  </p>
                </header>

                <div className="p-6">
                  <div className="mb-6 rounded-md bg-gray-50 p-4 ring-1 ring-inset ring-gray-200">
                    <p className="text-sm font-medium text-gray-900">
                      How it works
                    </p>
                    <p className="mt-1 text-xs text-gray-600">
                      The AI generates optimized content based on your settings.
                      The result is emailed as a CSV file. Having a backup means
                      you can always restore your original catalog.
                    </p>
                  </div>

                  {categories.length > 0 && (
                    <div className="mb-6 max-w-sm space-y-2">
                      <label className="block text-sm font-medium text-gray-900">
                        Target Category
                      </label>
                      <select
                        value={selectedCategory}
                        onChange={e => setSelectedCategory(e.target.value)}
                        className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                      >
                        <option value="all">All Products</option>
                        {categories.map(c => (
                          <option key={c.id} value={String(c.id)}>
                            {c.name} ({c.count})
                          </option>
                        ))}
                      </select>
                    </div>
                  )}

                  {backupError && (
                    <div className="mb-6">
                      <ErrorWrapper error={backupError} />
                    </div>
                  )}

                  {backupDone && (
                    <div className="mb-6 rounded-md bg-emerald-50 p-4 ring-1 ring-inset ring-emerald-600/20">
                      <p className="text-sm font-medium text-emerald-900">
                        Backup Successfully Downloaded
                      </p>
                      <p className="mt-1 text-xs text-emerald-800">
                        Your backup CSV is ready. You can now safely proceed
                        with generating new content.
                      </p>
                    </div>
                  )}

                  <div className="flex flex-col-reverse gap-3 sm:flex-row sm:items-center sm:justify-end">
                    <Button
                      variant="secondary"
                      onClick={() => setStep(1)}
                      className="rounded-md border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50"
                    >
                      Skip Backup
                    </Button>
                    <Button
                      onClick={downloadBackup}
                      disabled={backupLoading}
                      isLoading={backupLoading}
                      className="rounded-md bg-gray-900 px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-gray-800"
                    >
                      Download CSV
                    </Button>
                  </div>
                </div>
              </section>
            )}

            {step === 1 && (
              <section>
                <header className="border-b border-gray-100 bg-gray-50/50 px-6 py-5">
                  <h2 className="text-sm font-medium text-gray-900">
                    Upload Product CSV
                  </h2>
                  <p className="mt-0.5 text-xs text-gray-500">
                    Upload the backup you just downloaded or any standard
                    WooCommerce export.
                  </p>
                </header>

                <div className="p-6">
                  <div className="mb-6">
                    <input
                      ref={fileInputRef}
                      type="file"
                      accept=".csv,.xlsx"
                      className="hidden"
                      onChange={handleFileUpload}
                    />
                    <Button
                      variant="secondary"
                      onClick={() => fileInputRef.current?.click()}
                      className="w-full justify-center rounded-md border border-dashed border-gray-300 bg-gray-50 py-8 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-100"
                    >
                      {fileName ? 'Replace File' : 'Click to Browse CSV / XLSX'}
                    </Button>
                  </div>

                  {usage && usage.remaining <= 0 && (
                    <div className="mb-6 rounded-md bg-amber-50 p-4 ring-1 ring-inset ring-amber-600/20">
                      <p className="text-sm font-medium text-amber-900">
                        Monthly limit reached
                      </p>
                      <p className="mt-1 text-xs text-amber-800">
                        You&apos;ve used all {usage.limit} product generations
                        on your {planName} plan. Upgrade to continue.
                      </p>
                    </div>
                  )}

                  <div className="mb-6 rounded-md border border-gray-200 bg-gray-50 p-4">
                    <p className="mb-2 text-xs font-medium text-gray-700">
                      Expected CSV format (first row = headers):
                    </p>
                    <pre className="overflow-x-auto rounded bg-white p-3 text-[11px] text-gray-600 ring-1 ring-gray-200">
                      {`Title,Description,SKU,Tags,URL,Category
"Blue Widget","A great widget",SKU-001,"blue,widget",/products/blue-widget,Widgets`}
                    </pre>
                    <p className="mt-2 text-[11px] text-gray-500">
                      Only &quot;Title&quot; is required. Delimiters (comma,
                      semicolon, tab, pipe) are detected automatically. XLSX
                      files are also supported.
                    </p>
                  </div>

                  {uploadError && (
                    <div className="mb-6">
                      <ErrorWrapper error={uploadError} />
                    </div>
                  )}

                  {products.length > 0 && (
                    <div className="mb-6 rounded-md border border-gray-200 bg-gray-50 p-4">
                      <p className="text-sm font-medium text-gray-900">
                        {products.length} products detected
                      </p>
                      <p className="mt-1 text-xs text-gray-500">
                        File: {fileName}
                      </p>
                    </div>
                  )}

                  <div className="flex flex-col-reverse gap-3 sm:flex-row sm:items-center sm:justify-end">
                    <Button
                      variant="secondary"
                      onClick={() => setStep(0)}
                      className="rounded-md border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50"
                    >
                      Back
                    </Button>
                    <Button
                      onClick={() => setStep(2)}
                      disabled={products.length === 0}
                      className="rounded-md bg-gray-900 px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
                    >
                      Continue to Configuration
                    </Button>
                  </div>
                </div>
              </section>
            )}

            {step === 2 && (
              <section>
                <header className="border-b border-gray-100 bg-gray-50/50 px-6 py-5">
                  <h2 className="text-sm font-medium text-gray-900">
                    Configure AI Output
                  </h2>
                  <p className="mt-0.5 text-xs text-gray-500">
                    Setup the generation rules for your {products.length}{' '}
                    products.
                  </p>
                </header>

                <div className="p-6">
                  {promptTemplates.length > 0 && (
                    <div className="mb-6 rounded-lg border border-gray-200 bg-gray-50 p-4">
                      <label className="block text-sm font-medium text-gray-900 mb-2">
                        Apply a Prompt Template (optional)
                      </label>
                      <div className="flex gap-3">
                        <select
                          value={selectedTemplateId}
                          onChange={e => setSelectedTemplateId(e.target.value)}
                          className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                        >
                          <option value="">— Select a template —</option>
                          {promptTemplates.map(t => (
                            <option key={t.template_id} value={t.template_id}>
                              {t.name}
                            </option>
                          ))}
                        </select>
                        <button
                          type="button"
                          disabled={!selectedTemplateId}
                          onClick={() =>
                            handleApplyTemplate(selectedTemplateId)
                          }
                          className="shrink-0 rounded-md bg-gray-900 px-4 py-2 text-sm font-medium text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-40"
                        >
                          Apply
                        </button>
                      </div>
                      <p className="mt-2 text-xs text-gray-500">
                        Applying a template overwrites the current tone,
                        language, creativity, and field instructions below.
                      </p>
                    </div>
                  )}

                  <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
                    <div className="space-y-2">
                      <label className="block text-sm font-medium text-gray-900">
                        Brand Tone
                      </label>
                      <select
                        value={tone}
                        onChange={e => setTone(e.target.value)}
                        className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                      >
                        {TONES.map(t => (
                          <option key={t.value} value={t.value}>
                            {t.label}
                          </option>
                        ))}
                      </select>
                    </div>

                    <div className="space-y-2">
                      <label className="block text-sm font-medium text-gray-900">
                        Language
                      </label>
                      <select
                        value={language}
                        onChange={e => {
                          const nextLanguage = e.target.value;
                          setLanguage(nextLanguage);
                          setAdditionalLanguages(current =>
                            current.filter(code => code !== nextLanguage)
                          );
                        }}
                        className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                      >
                        {LANGUAGES.map(l => (
                          <option key={l.value} value={l.value}>
                            {l.label}
                          </option>
                        ))}
                      </select>
                      {additionalLanguages.length > 0 && (
                        <div className="flex flex-wrap gap-1">
                          {additionalLanguages.map(code => {
                            const matched = LANGUAGES.find(
                              option => option.value === code
                            );
                            const labelForCode =
                              matched?.label ?? code.toUpperCase();
                            return (
                              <span
                                key={code}
                                className="inline-flex items-center gap-1 rounded-full bg-gray-200 px-2 py-0.5 text-xs text-gray-700"
                              >
                                {labelForCode}
                                <button
                                  type="button"
                                  aria-label={`Remove ${labelForCode}`}
                                  className="text-gray-500 hover:text-gray-900"
                                  onClick={() =>
                                    setAdditionalLanguages(current =>
                                      current.filter(
                                        existing => existing !== code
                                      )
                                    )
                                  }
                                >
                                  x
                                </button>
                              </span>
                            );
                          })}
                        </div>
                      )}
                      <select
                        value=""
                        onChange={e => {
                          const nextLanguage = e.target.value;
                          if (!nextLanguage || nextLanguage === language)
                            return;
                          setAdditionalLanguages(current => {
                            if (current.includes(nextLanguage)) return current;
                            if (current.length >= 2) return current;
                            return [...current, nextLanguage];
                          });
                        }}
                        disabled={additionalLanguages.length >= 2}
                        className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                      >
                        <option value="">
                          {additionalLanguages.length >= 2
                            ? 'Max 2 extra languages'
                            : 'Also generate in (optional)...'}
                        </option>
                        {LANGUAGES.filter(
                          option =>
                            option.value !== language &&
                            !additionalLanguages.includes(option.value)
                        ).map(option => (
                          <option key={option.value} value={option.value}>
                            {option.label}
                          </option>
                        ))}
                      </select>
                      <p className="text-xs text-gray-500">
                        Up to 2 extras (3 languages total).
                      </p>
                      {additionalLanguages.length > 0 && (
                        <div className="space-y-2 pt-2">
                          <label className="block text-sm font-medium text-gray-900">
                            Output format
                          </label>
                          <div className="flex flex-col gap-1.5">
                            <label className="flex items-start gap-2 cursor-pointer text-sm">
                              <input
                                type="radio"
                                name="bundle-output"
                                value="single"
                                checked={bundleOutput === 'single'}
                                onChange={() => setBundleOutput('single')}
                                className="mt-1"
                              />
                              <span>
                                <span className="font-medium">
                                  One merged CSV
                                </span>
                                <span className="block text-xs text-gray-500">
                                  All languages in one file, identified by a
                                  Language column.
                                </span>
                              </span>
                            </label>
                            <label className="flex items-start gap-2 cursor-pointer text-sm">
                              <input
                                type="radio"
                                name="bundle-output"
                                value="per_language"
                                checked={bundleOutput === 'per_language'}
                                onChange={() => setBundleOutput('per_language')}
                                className="mt-1"
                              />
                              <span>
                                <span className="font-medium">
                                  Separate CSV per language
                                </span>
                                <span className="block text-xs text-gray-500">
                                  One CSV per language, attached to the same
                                  email.
                                </span>
                              </span>
                            </label>
                          </div>
                        </div>
                      )}
                    </div>

                    <div className="space-y-2">
                      <label className="block text-sm font-medium text-gray-900">
                        Creativity
                      </label>
                      <select
                        value={String(temperature)}
                        onChange={e =>
                          setTemperature(parseFloat(e.target.value))
                        }
                        className="block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                      >
                        <option value="0.3">Conservative (0.3)</option>
                        <option value="0.5">Balanced (0.5)</option>
                        <option value="0.7">Default (0.7)</option>
                        <option value="0.9">Creative (0.9)</option>
                      </select>
                    </div>
                  </div>

                  <hr className="my-8 border-gray-100" />

                  <h3 className="mb-4 text-sm font-medium text-gray-900">
                    Target Fields
                  </h3>
                  <div className="grid grid-cols-1 gap-6">
                    {(
                      Object.keys(FIELD_LABELS) as Array<
                        keyof ContentGenerateFields
                      >
                    ).map(key => (
                      <div
                        key={key}
                        className={`rounded-lg border transition-colors ${fields[key] ? 'border-gray-900 ring-1 ring-inset ring-gray-900' : 'border-gray-200 hover:border-gray-300'}`}
                      >
                        <div className="flex items-center gap-3 p-4">
                          <input
                            type="checkbox"
                            checked={fields[key]}
                            onChange={e =>
                              setFields(prev => ({
                                ...prev,
                                [key]: e.target.checked,
                              }))
                            }
                            className="h-4 w-4 rounded border-gray-300 text-gray-900 focus:ring-gray-900"
                          />
                          <div className="flex flex-col">
                            <span className="text-sm font-medium text-gray-900">
                              {FIELD_LABELS[key]}
                            </span>
                            <span className="text-xs text-gray-500">
                              {FIELD_HELP[key]}
                            </span>
                          </div>
                        </div>

                        {fields[key] && (
                          <div className="border-t border-gray-100 bg-gray-50/50 p-4">
                            {key === 'faq' && (
                              <div className="mb-4 space-y-2">
                                <label className="block text-xs font-medium text-gray-700">
                                  FAQ Placement
                                </label>
                                <select
                                  value={
                                    faqInDescription
                                      ? 'in_description'
                                      : 'separate'
                                  }
                                  onChange={e =>
                                    setFaqInDescription(
                                      e.target.value === 'in_description'
                                    )
                                  }
                                  className="block w-full max-w-sm rounded-md border-gray-300 py-1.5 pl-3 pr-10 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                                >
                                  <option value="in_description">
                                    Append to Description (Recommended)
                                  </option>
                                  <option value="separate">
                                    Generate in Separate Column
                                  </option>
                                </select>
                              </div>
                            )}

                            <div className="space-y-2">
                              <div className="flex items-center justify-between">
                                <label className="block text-xs font-medium text-gray-700">
                                  Custom Instructions (Optional)
                                </label>
                                <button
                                  type="button"
                                  onClick={() => handleImprovePrompt(key)}
                                  disabled={
                                    improvingField === key ||
                                    !fieldPrompts[key].trim()
                                  }
                                  className="text-[10px] font-semibold text-gray-600 hover:text-gray-900 disabled:cursor-not-allowed disabled:opacity-50"
                                >
                                  {improvingField === key
                                    ? 'Enhancing...'
                                    : '✨ Enhance with AI'}
                                </button>
                              </div>
                              <textarea
                                rows={2}
                                value={fieldPrompts[key]}
                                onChange={e =>
                                  setFieldPrompts(prev => ({
                                    ...prev,
                                    [key]: e.target.value,
                                  }))
                                }
                                placeholder={FIELD_PLACEHOLDERS[key]}
                                className="block w-full rounded-md border-gray-300 px-3 py-2 text-sm placeholder:text-gray-400 focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                              />
                            </div>
                          </div>
                        )}
                      </div>
                    ))}
                  </div>

                  {!Object.values(fields).some(Boolean) && (
                    <div className="mt-4">
                      <ErrorWrapper error="You must select at least one field to generate." />
                    </div>
                  )}

                  <hr className="my-8 border-gray-100" />

                  <div className="max-w-md space-y-2">
                    <label className="block text-sm font-medium text-gray-900">
                      Delivery Email
                    </label>
                    <input
                      type="email"
                      value={email}
                      onChange={e => setEmail(e.target.value)}
                      placeholder={user?.email || 'your@email.com'}
                      className="block w-full rounded-md border-gray-300 px-3 py-2 text-sm focus:border-gray-900 focus:outline-none focus:ring-1 focus:ring-gray-900"
                    />
                    <p className="text-xs text-gray-500">
                      The final CSV will be sent here when processing completes.
                    </p>
                  </div>

                  {submitError && (
                    <div className="mt-6">
                      <ErrorWrapper error={submitError} />
                    </div>
                  )}

                  <div className="mt-8 flex flex-col-reverse gap-3 border-t border-gray-100 pt-6 sm:flex-row sm:items-center sm:justify-end">
                    <Button
                      variant="secondary"
                      onClick={() => setStep(1)}
                      className="rounded-md border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50"
                    >
                      Back
                    </Button>
                    <Button
                      onClick={handleSubmit}
                      disabled={
                        submitting ||
                        !Object.values(fields).some(Boolean) ||
                        !email.trim()
                      }
                      isLoading={submitting}
                      className="rounded-md bg-gray-900 px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50"
                    >
                      Start Generation
                    </Button>
                  </div>
                </div>
              </section>
            )}

            {step === 3 && jobStatus && (
              <section>
                <header className="border-b border-gray-100 bg-gray-50/50 px-6 py-5">
                  <h2 className="text-sm font-medium text-gray-900">
                    Job Processing
                  </h2>
                  <p className="mt-0.5 text-xs text-gray-500">
                    You can safely leave this page. We will email you the final
                    CSV when generation completes.
                  </p>
                </header>

                <div className="p-6">
                  <div className="rounded-md border border-gray-200 bg-gray-50 p-6">
                    <div className="flex items-center justify-between">
                      <p className="text-sm font-medium text-gray-900">
                        {jobStatus.current_step || 'Initializing...'}
                      </p>
                      <span
                        className={`inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset ${
                          jobStatus.state === 'processing' ||
                          jobStatus.state === 'pending'
                            ? 'bg-blue-50 text-blue-700 ring-blue-600/20'
                            : jobStatus.state === 'completed'
                              ? 'bg-emerald-50 text-emerald-700 ring-emerald-600/20'
                              : 'bg-red-50 text-red-700 ring-red-600/20'
                        }`}
                      >
                        {jobStatus.state.toUpperCase()}
                      </span>
                    </div>

                    <div className="mt-4 flex items-center justify-between text-xs text-gray-500">
                      <span>
                        Processed {jobStatus.processed_count} of{' '}
                        {jobStatus.total_count}
                      </span>
                      <span>{progressPct}%</span>
                    </div>

                    <div className="mt-2 h-2 w-full overflow-hidden rounded-full bg-gray-200">
                      <div
                        className={`h-full transition-all duration-300 ${jobStatus.state === 'failed' ? 'bg-red-600' : 'bg-gray-900'}`}
                        style={{ width: `${progressPct}%` }}
                      />
                    </div>

                    {jobStatus.state === 'completed' && (
                      <div className="mt-6 rounded-md bg-emerald-50 p-4 ring-1 ring-inset ring-emerald-600/20">
                        <p className="text-sm font-medium text-emerald-900">
                          Job Complete
                        </p>
                        <p className="mt-1 text-xs text-emerald-800">
                          Your CSV is ready and has been emailed to you. You can
                          now use the Bulk Upload tool to import your new
                          content.
                        </p>
                      </div>
                    )}

                    {jobStatus.state === 'failed' && (
                      <div className="mt-6 rounded-md bg-red-50 p-4 ring-1 ring-inset ring-red-600/20">
                        <p className="text-sm font-medium text-red-900">
                          Job Failed
                        </p>
                        <p className="mt-1 text-xs text-red-800">
                          {jobStatus.error || 'An unknown error occurred.'}
                        </p>
                      </div>
                    )}
                  </div>

                  <div className="mt-6 flex flex-col gap-3 border-t border-gray-100 pt-6 sm:flex-row sm:items-center sm:justify-end">
                    {jobStatus.state === 'failed' && (
                      <Button
                        variant="secondary"
                        onClick={() => {
                          setStep(2);
                          setJobStatus(null);
                          if (clientId) clearCachedJobSnapshot(clientId);
                        }}
                        className="w-full justify-center rounded-md border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-50 sm:w-auto"
                      >
                        Go Back & Retry
                      </Button>
                    )}

                    {jobStatus.state === 'completed' && (
                      <>
                        <Button
                          variant="secondary"
                          onClick={resetWizard}
                          className="w-full justify-center rounded-md border border-gray-200 bg-white px-5 py-2.5 text-sm font-medium text-gray-900 hover:bg-gray-50 sm:w-auto"
                        >
                          Start New Job
                        </Button>
                        <Link
                          to="/product-improvements"
                          className="inline-flex w-full items-center justify-center rounded-md bg-gray-900 px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-gray-800 sm:w-auto"
                        >
                          Go to Bulk Upload
                        </Link>
                      </>
                    )}
                  </div>
                </div>
              </section>
            )}
          </div>
        </>
      )}
    </div>
  );
};

export default ContentGeneratorPage;
