"use client";

import { useState, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import * as XLSX from "xlsx";

import {
  createBlog,
  updateBlog,
  getBlog,
} from "@/services/blogs";

import BlogSectionEditor, {
  type BlogSection,
} from "./BlogSectionEditor";

import GalleryUploader from "./GalleryUploader";
import FaqEditor from "./FaqEditor";

interface Props {
  blogId?: string;
}

interface ImportedFaq {
  question: string;
  answer: string;
}

interface ImportedPoint {
  title: string;
  description: string;
}

interface ImportedCard {
  title: string;
  description: string;
  points: ImportedPoint[];
}

/* =====================================================
   EXCEL PARSING HELPERS
===================================================== */

const parsePlainTextBlocks = (
  value: unknown
): string[] => {
  const text = String(value ?? "").trim();

  if (!text) {
    return [];
  }

  return text
    .split(/\n\s*\n/)
    .map((block) => block.trim())
    .filter(Boolean);
};

const parseTitleDescription = (
  value: string
): {
  title: string;
  description: string;
} => {
  const lines = value
    .split("\n")
    .map((line) => line.trim())
    .filter(Boolean);

  if (!lines.length) {
    return {
      title: "",
      description: "",
    };
  }

  const firstLine = lines[0];

  const separatorIndex =
    firstLine.indexOf(":");

  if (separatorIndex > 0) {
    return {
      title: firstLine
        .slice(0, separatorIndex)
        .trim(),

      description: [
        firstLine
          .slice(separatorIndex + 1)
          .trim(),

        ...lines.slice(1),
      ]
        .filter(Boolean)
        .join("\n\n"),
    };
  }

  return {
    title: firstLine,
    description: lines
      .slice(1)
      .join("\n\n"),
  };
};

const parseNumberedPoints = (
  value: unknown
): ImportedPoint[] => {
  const text = String(value ?? "").trim();

  if (!text) {
    return [];
  }

  /*
   * Each numbered point starts with:
   *
   * [TITLE]
   * ...
   *
   * OR
   *
   * [POINT]
   * ...
   *
   * OR
   *
   * A normal line containing Title: Description
   *
   * Blocks are separated by blank lines.
   */

  const blocks = text
    .split(/\n\s*\n/)
    .map((block) => block.trim())
    .filter(Boolean);

  /*
   * If the user has used [TITLE] blocks,
   * parse those first.
   */

  if (text.includes("[TITLE]")) {
    const points: ImportedPoint[] = [];

    const matches = text.match(
      /\[TITLE\][\s\S]*?(?=(?:\n\s*\[TITLE\])|$)/g
    );

    if (matches) {
      matches.forEach((block) => {
        const withoutTitle =
          block.replace(
            /^\s*\[TITLE\]\s*/i,
            ""
          );

        const descriptionMatch =
          withoutTitle.match(
            /\[DESCRIPTION\]([\s\S]*?)(?=\[POINTS\]|$)/i
          );

        const pointsMatch =
          withoutTitle.match(
            /\[POINTS\]([\s\S]*)$/i
          );

        const title =
          descriptionMatch
            ? withoutTitle
                .split(/\[DESCRIPTION\]/i)[0]
                .trim()
            : withoutTitle
                .split(/\[POINTS\]/i)[0]
                .trim();

        const description =
          descriptionMatch?.[1]?.trim() ||
          "";

        const pointText =
          pointsMatch?.[1]?.trim() ||
          "";

        let finalDescription =
          description;

        if (pointText) {
          finalDescription = [
            description,
            pointText,
          ]
            .filter(Boolean)
            .join("\n\n");
        }

        if (title || finalDescription) {
          points.push({
            title,
            description:
              finalDescription,
          });
        }
      });

      if (points.length) {
        return points;
      }
    }
  }

  /*
   * Simple format:
   *
   * Title: Description
   *
   * separated by blank lines.
   */

  return blocks.map((block) => {
    return parseTitleDescription(
      block
    );
  });
};

const parseTwoColumnCards = (
  value: unknown
): ImportedCard[] => {
  const text = String(value ?? "").trim();

  if (!text) {
    return [];
  }

  /*
   * Preferred format:
   *
   * [CARD]
   * Card Title
   *
   * [DESCRIPTION]
   * Paragraph 1
   *
   * Paragraph 2
   *
   * [POINTS]
   * Point 1
   * Point 2
   */

  if (text.includes("[CARD]")) {
    const cards: ImportedCard[] = [];

    const matches = text.match(
      /\[CARD\][\s\S]*?(?=(?:\n\s*\[CARD\])|$)/g
    );

    if (matches) {
      matches.forEach((block) => {
        const withoutCard =
          block.replace(
            /^\s*\[CARD\]\s*/i,
            ""
          );

        const descriptionMatch =
          withoutCard.match(
            /\[DESCRIPTION\]([\s\S]*?)(?=\[POINTS\]|$)/i
          );

        const pointsMatch =
          withoutCard.match(
            /\[POINTS\]([\s\S]*)$/i
          );

        const title =
          descriptionMatch
            ? withoutCard
                .split(/\[DESCRIPTION\]/i)[0]
                .trim()
            : withoutCard
                .split(/\[POINTS\]/i)[0]
                .trim();

        const description =
          descriptionMatch?.[1]?.trim() ||
          "";

        const pointsText =
          pointsMatch?.[1]?.trim() ||
          "";

        const points: ImportedPoint[] =
          pointsText
            ? pointsText
                .split("\n")
                .map((line) =>
                  line
                    .replace(
                      /^[-•*]\s*/,
                      ""
                    )
                    .trim()
                )
                .filter(Boolean)
                .map((line) =>
                  parseTitleDescription(
                    line
                  )
                )
            : [];

        if (
          title ||
          description ||
          points.length
        ) {
          cards.push({
            title,
            description,
            points,
          });
        }
      });

      if (cards.length) {
        return cards;
      }
    }
  }

  /*
   * Simple format:
   *
   * Card Title: Description
   *
   * separated by blank lines.
   */

  const blocks = text
    .split(/\n\s*\n/)
    .map((block) => block.trim())
    .filter(Boolean);

  return blocks.map((block) => {
    const parsed =
      parseTitleDescription(block);

    return {
      title: parsed.title,
      description:
        parsed.description,
      points: [],
    };
  });
};

const parseStandardSections = (
  value: unknown
): BlogSection[] => {
  const text = String(value ?? "").trim();

  if (!text) {
    return [];
  }

  /*
   * Preferred format:
   *
   * [SECTION]
   * Conclusion
   *
   * [DESCRIPTION]
   * Paragraph 1
   *
   * Paragraph 2
   */

  if (text.includes("[SECTION]")) {
    const sections: BlogSection[] = [];

    const matches = text.match(
      /\[SECTION\][\s\S]*?(?=(?:\n\s*\[SECTION\])|$)/g
    );

    if (matches) {
      matches.forEach((block) => {
        const withoutSection =
          block.replace(
            /^\s*\[SECTION\]\s*/i,
            ""
          );

        const descriptionMatch =
          withoutSection.match(
            /\[DESCRIPTION\]([\s\S]*)$/i
          );

        const title =
          descriptionMatch
            ? withoutSection
                .split(/\[DESCRIPTION\]/i)[0]
                .trim()
            : withoutSection.trim();

        const content =
          descriptionMatch?.[1]?.trim() ||
          "";

        if (title || content) {
          sections.push({
            id: crypto.randomUUID(),
            type: "standard",
            title,
            content,
            points: [],
            cards: [],
          });
        }
      });

      if (sections.length) {
        return sections;
      }
    }
  }

  /*
   * Simple format:
   *
   * Section Title: Section content
   *
   * separated by blank lines.
   */

  const blocks = text
    .split(/\n\s*\n/)
    .map((block) => block.trim())
    .filter(Boolean);

  return blocks.map((block) => {
    const parsed =
      parseTitleDescription(block);

    return {
      id: crypto.randomUUID(),
      type: "standard",
      title: parsed.title,
      content: parsed.description,
      points: [],
      cards: [],
    };
  });
};

const parsePlainTextFaqs = (
  value: unknown
): ImportedFaq[] => {
  const text = String(value ?? "").trim();

  if (!text) {
    return [];
  }

  /*
   * Preferred/simple format:
   *
   * Question: Answer
   *
   * separated by blank lines.
   *
   * The first ":" is used as the
   * question/answer separator.
   */

  const blocks = text
    .split(/\n\s*\n/)
    .map((block) => block.trim())
    .filter(Boolean);

  return blocks
    .map((block) => {
      const separatorIndex =
        block.indexOf(":");

      if (separatorIndex <= 0) {
        return {
          question: block.trim(),
          answer: "",
        };
      }

      return {
        question: block
          .slice(0, separatorIndex)
          .trim(),

        answer: block
          .slice(separatorIndex + 1)
          .trim(),
      };
    })
    .filter(
      (faq) =>
        faq.question ||
        faq.answer
    );
};

export default function BlogForm({
  blogId,
}: Props) {
  const router = useRouter();

  const queryClient =
    useQueryClient();

  const [loading, setLoading] =
    useState(false);

  /* =====================================================
     EXCEL IMPORT
  ===================================================== */

  const excelInputRef =
    useRef<HTMLInputElement | null>(
      null
    );

  const [importingExcel, setImportingExcel] =
    useState(false);

  /* =====================================================
     COVER IMAGE
     Hero image
  ===================================================== */

  const [coverImage, setCoverImage] =
    useState<File | null>(null);

  const [removeCoverImage, setRemoveCoverImage] =
    useState(false);

  /* =====================================================
     INTRO IMAGE
     Separate image for Introduction / Overview
  ===================================================== */

  const [introImage, setIntroImage] =
    useState<File | null>(null);

  const [removeIntroImage, setRemoveIntroImage] =
    useState(false);

  /* =====================================================
     OG IMAGE
     Separate image for Open Graph / Social Sharing
  ===================================================== */

  const [ogImage, setOgImage] =
    useState<File | null>(null);

  const [removeOgImage, setRemoveOgImage] =
    useState(false);

  /* =====================================================
     GALLERY
  ===================================================== */

  const [gallery, setGallery] =
    useState<File[]>([]);

  const [existingGallery, setExistingGallery] =
    useState<string[]>([]);

  /* =====================================================
     FAQ
  ===================================================== */

  const [faqs, setFaqs] = useState<
    {
      question: string;
      answer: string;
    }[]
  >([]);

  /* =====================================================
     BLOG SECTIONS
  ===================================================== */

  const [sections, setSections] =
    useState<BlogSection[]>([]);

  /* =====================================================
     FORM
  ===================================================== */

  const [form, setForm] = useState({
    title: "",
    slug: "",
    excerpt: "",
    category: "Wedding",
    tags: "",

    /* SEO */
    seoTitle: "",
    metaDescription: "",
    metaKeywords: "",

    /* CANONICAL */
    canonicalUrl: "",

    /* OPEN GRAPH */
    ogTitle: "",
    ogDescription: "",
    ogImageAlt: "",
    ogImageTitle: "",

    status: "Draft",
  });

  /* =====================================================
     GET BLOG
  ===================================================== */

  const {
    data,
    isLoading,
  } = useQuery({
    queryKey: ["blog", blogId],
    queryFn: () => getBlog(blogId!),
    enabled: !!blogId,
  });

  /* =====================================================
     LOAD EXISTING BLOG
  ===================================================== */

  useEffect(() => {
    if (!data) return;

    const blog = data.data;

    setExistingGallery(
      blog.gallery || []
    );

    setForm({
      title: blog.title || "",

      slug: blog.slug || "",

      excerpt: blog.excerpt || "",

      category:
        blog.category || "Wedding",

      tags:
        blog.tags?.join(", ") || "",

      /* SEO */

      seoTitle:
        blog.seoTitle || "",

      metaDescription:
        blog.metaDescription || "",

      metaKeywords:
        blog.metaKeywords?.join(", ") || "",

      /* CANONICAL */

      canonicalUrl:
        blog.canonicalUrl || "",

      /* OPEN GRAPH */

      ogTitle:
        blog.ogTitle || "",

      ogDescription:
        blog.ogDescription || "",

      ogImageAlt:
        blog.ogImageAlt || "",

      ogImageTitle:
        blog.ogImageTitle || "",

      status:
        blog.status || "Draft",
    });

    setSections(
      blog.sections || []
    );

    setFaqs(
      blog.faqs || []
    );

    setCoverImage(null);
    setIntroImage(null);
    setOgImage(null);

    setRemoveCoverImage(false);
    setRemoveIntroImage(false);
    setRemoveOgImage(false);
  }, [data]);

  /* =====================================================
     EXCEL HELPERS
  ===================================================== */

  const normalizeExcelValue = (
    value: unknown
  ): string => {
    if (
      value === null ||
      value === undefined
    ) {
      return "";
    }

    return String(value).trim();
  };

  const parseJsonCell = <T,>(
    value: unknown,
    fieldName: string
  ): T | null => {
    const text =
      normalizeExcelValue(value);

    if (!text) {
      return null;
    }

    try {
      return JSON.parse(text) as T;
    } catch {
      throw new Error(
        `${fieldName} contains invalid JSON.`
      );
    }
  };

  /* =====================================================
     IMPORT EXCEL
  ===================================================== */

  const handleExcelImport = async (
    e: React.ChangeEvent<HTMLInputElement>
  ) => {
    const file =
      e.target.files?.[0];

    if (!file) {
      return;
    }

    try {
      setImportingExcel(true);

      const arrayBuffer =
        await file.arrayBuffer();

      const workbook =
        XLSX.read(arrayBuffer, {
          type: "array",
        });

      const firstSheetName =
        workbook.SheetNames[0];

      if (!firstSheetName) {
        throw new Error(
          "Excel file does not contain any worksheet."
        );
      }

      const worksheet =
        workbook.Sheets[
          firstSheetName
        ];

      const rows =
        XLSX.utils.sheet_to_json<
          Record<string, unknown>
        >(worksheet, {
          defval: "",
        });

      if (!rows.length) {
        throw new Error(
          "Excel file does not contain any data."
        );
      }

      /*
       * This BlogForm imports the first
       * data row from the Excel sheet.
       */

      const row = rows[0];

      /*
       * Normalize column names so that
       * Title / TITLE / title all work.
       */

      const normalizedRow: Record<
        string,
        unknown
      > = {};

      Object.entries(row).forEach(
        ([key, value]) => {
          normalizedRow[
            key.trim().toLowerCase()
          ] = value;
        }
      );

      /* -----------------------------------------------
         BASIC REQUIRED FIELDS
      ----------------------------------------------- */

      const title =
        normalizeExcelValue(
          normalizedRow.title
        );

      const slug =
        normalizeExcelValue(
          normalizedRow.slug
        );

      const excerpt =
        normalizeExcelValue(
          normalizedRow.excerpt
        );

      if (!title) {
        throw new Error(
          "Title is missing in the Excel file."
        );
      }

      /*
       * IMPORTANT:
       * Slug MUST come from Excel.
       *
       * We do NOT generate it from title.
       */

      if (!slug) {
        throw new Error(
          "Slug is missing in the Excel file. Slug must be manually provided."
        );
      }

      if (!excerpt) {
        throw new Error(
          "Excerpt is missing in the Excel file."
        );
      }

      /* -----------------------------------------------
         CATEGORY
      ----------------------------------------------- */

      const allowedCategories = [
        "Wedding",
        "Corporate",
        "Stay",
        "Photoshoot",
        "Events",
        "Awards",
      ];

      const importedCategory =
        normalizeExcelValue(
          normalizedRow.category
        );

      const category =
        importedCategory ||
        "Wedding";

      if (
        !allowedCategories.includes(
          category
        )
      ) {
        throw new Error(
          `Invalid category "${category}". Allowed values: ${allowedCategories.join(
            ", "
          )}`
        );
      }

      /* -----------------------------------------------
         STATUS
      ----------------------------------------------- */

      const allowedStatuses = [
        "Draft",
        "Published",
        "Archived",
      ];

      const importedStatus =
        normalizeExcelValue(
          normalizedRow.status
        );

      const status =
        importedStatus ||
        "Draft";

      if (
        !allowedStatuses.includes(
          status
        )
      ) {
        throw new Error(
          `Invalid status "${status}". Allowed values: ${allowedStatuses.join(
            ", "
          )}`
        );
      }

      /* -----------------------------------------------
         SECTIONS
      ----------------------------------------------- */

      let importedSections: BlogSection[] =
        [];

      /*
       * OLD FORMAT SUPPORT
       *
       * If the Excel file contains the
       * old "sections" JSON column,
       * continue supporting it.
       */

      const oldSections =
        parseJsonCell<BlogSection[]>(
          normalizedRow.sections,
          "Sections"
        );

      if (oldSections !== null) {
        if (!Array.isArray(oldSections)) {
          throw new Error(
            "Sections must be a JSON array."
          );
        }

        importedSections =
          oldSections;
      } else {
        /*
         * NEW EASY EXCEL FORMAT
         */

        /* -------------------------------------------
           INTRODUCTION
        ------------------------------------------- */

        const introTitle =
          normalizeExcelValue(
            normalizedRow.introtitle
          );

        const introContent =
          normalizeExcelValue(
            normalizedRow.introcontent
          );

        if (
          introTitle ||
          introContent
        ) {
          importedSections.push({
            id: crypto.randomUUID(),
            type: "introduction",
            title: introTitle,
            content: introContent,
            points: [],
            cards: [],
          });
        }

        /* -------------------------------------------
           NUMBERED SECTION
        ------------------------------------------- */

        const numberedTitle =
          normalizeExcelValue(
            normalizedRow.numberedsectiontitle
          );

        const numberedPointsText =
          normalizeExcelValue(
            normalizedRow.numberedpoints
          );

        const numberedPoints =
          parseNumberedPoints(
            numberedPointsText
          );

        if (
          numberedTitle ||
          numberedPoints.length
        ) {
          importedSections.push({
            id: crypto.randomUUID(),
            type: "numbered",
            title: numberedTitle,
            content: "",
            points:
              numberedPoints.map(
                (point) => ({
                  title:
                    point.title,
                  description:
                    point.description,
                })
              ),
            cards: [],
          });
        }

        /* -------------------------------------------
           TWO COLUMN SECTION
        ------------------------------------------- */

        const twoColumnTitle =
          normalizeExcelValue(
            normalizedRow.twocolumnsectiontitle
          );

        const twoColumnCardsText =
          normalizeExcelValue(
            normalizedRow.twocolumncards
          );

        const twoColumnCards =
          parseTwoColumnCards(
            twoColumnCardsText
          );

        if (
          twoColumnTitle ||
          twoColumnCards.length
        ) {
          importedSections.push({
            id: crypto.randomUUID(),
            type: "two-column",
            title: twoColumnTitle,
            content: "",
            points: [],
            cards:
              twoColumnCards.map(
                (card) => ({
                  title: card.title,
                  description:
                    card.description,
                  points:
                    card.points.map(
                      (point) => ({
                        title:
                          point.title,
                        description:
                          point.description,
                      })
                    ),
                })
              ),
          });
        }

        /* -------------------------------------------
           STANDARD SECTIONS
        ------------------------------------------- */

        const standardSectionsText =
          normalizeExcelValue(
            normalizedRow.standardsections
          );

        const standardSections =
          parseStandardSections(
            standardSectionsText
          );

        if (
          standardSections.length
        ) {
          importedSections.push(
            ...standardSections
          );
        }
      }

      /* -----------------------------------------------
         FAQS
      ----------------------------------------------- */

      let importedFaqs: ImportedFaq[] =
        [];

      /*
       * OLD JSON FAQ SUPPORT
       */

      const oldFaqs =
        parseJsonCell<ImportedFaq[]>(
          normalizedRow.faqs,
          "FAQs"
        );

      if (oldFaqs !== null) {
        if (!Array.isArray(oldFaqs)) {
          throw new Error(
            "FAQs must be a JSON array."
          );
        }

        importedFaqs = oldFaqs;
      } else {
        /*
         * NEW EASY FAQ FORMAT
         */

        importedFaqs =
          parsePlainTextFaqs(
            normalizedRow.faqs
          );
      }

      /* -----------------------------------------------
         SET BASIC FORM DATA
      ----------------------------------------------- */

      setForm({
        title,

        /*
         * IMPORTANT:
         * Use Excel slug exactly as provided.
         * No slug generation here.
         */

        slug,

        excerpt,

        category,

        tags:
          normalizeExcelValue(
            normalizedRow.tags
          ),

        /* SEO */

        seoTitle:
          normalizeExcelValue(
            normalizedRow.seotitle
          ),

        metaDescription:
          normalizeExcelValue(
            normalizedRow.metadescription
          ),

        metaKeywords:
          normalizeExcelValue(
            normalizedRow.metakeywords
          ),

        /* CANONICAL */

        canonicalUrl:
          normalizeExcelValue(
            normalizedRow.canonicalurl
          ),

        /* OPEN GRAPH */

        ogTitle:
          normalizeExcelValue(
            normalizedRow.ogtitle
          ),

        ogDescription:
          normalizeExcelValue(
            normalizedRow.ogdescription
          ),

        /*
         * OG IMAGE IS INTENTIONALLY NOT
         * IMPORTED FROM EXCEL.
         *
         * It must be uploaded manually
         * through the BlogForm.
         */

        ogImageAlt:
          normalizeExcelValue(
            normalizedRow.ogimagealt
          ),

        ogImageTitle:
          normalizeExcelValue(
            normalizedRow.ogimagetitle
          ),

        status,
      });

      /* -----------------------------------------------
         SET SECTIONS
      ----------------------------------------------- */

      setSections(
        importedSections
      );

      /* -----------------------------------------------
         SET FAQS
      ----------------------------------------------- */

      setFaqs(
        importedFaqs
      );

      /*
       * Excel import does NOT change:
       *
       * - cover image
       * - intro image
       * - OG image
       * - gallery
       * - existing gallery
       */

      toast.success(
        "Blog data imported from Excel successfully."
      );
    } catch (error) {
      console.error(
        "Excel import error:",
        error
      );

      toast.error(
        error instanceof Error
          ? error.message
          : "Failed to import Excel file."
      );
    } finally {
      setImportingExcel(false);

      /*
       * Allows importing the same file again.
       */

      if (excelInputRef.current) {
        excelInputRef.current.value = "";
      }
    }
  };

  /* =====================================================
     SUBMIT
  ===================================================== */

  const handleSubmit = async (
    e: React.FormEvent
  ) => {
    e.preventDefault();

    /* -----------------------------------------------
       Validation
    ----------------------------------------------- */

    if (!form.title.trim()) {
      toast.error(
        "Blog title is required."
      );
      return;
    }

    if (!form.slug.trim()) {
      toast.error(
        "URL slug is required."
      );
      return;
    }

    if (!form.excerpt.trim()) {
      toast.error(
        "Short description is required."
      );
      return;
    }

    /*
     * New blogs must have a cover image.
     */

    if (
      !blogId &&
      !coverImage
    ) {
      toast.error(
        "Cover image is required."
      );
      return;
    }

    /*
     * New blogs should have at least
     * one content section.
     */

    if (
      !sections ||
      sections.length === 0
    ) {
      toast.error(
        "Please add at least one content section."
      );
      return;
    }

    try {
      setLoading(true);

      const formData =
        new FormData();

      /* -----------------------------------------------
         BASIC BLOG DATA
      ----------------------------------------------- */

      formData.append(
        "title",
        form.title
      );

      formData.append(
        "slug",
        form.slug
      );

      formData.append(
        "excerpt",
        form.excerpt
      );

      formData.append(
        "sections",
        JSON.stringify(sections)
      );

      formData.append(
        "category",
        form.category
      );

      formData.append(
        "tags",
        form.tags
      );

      /* -----------------------------------------------
         SEO
      ----------------------------------------------- */

      formData.append(
        "seoTitle",
        form.seoTitle
      );

      formData.append(
        "metaDescription",
        form.metaDescription
      );

      formData.append(
        "metaKeywords",
        form.metaKeywords
      );

      /* -----------------------------------------------
         CANONICAL
      ----------------------------------------------- */

      formData.append(
        "canonicalUrl",
        form.canonicalUrl
      );

      /* -----------------------------------------------
         OPEN GRAPH
      ----------------------------------------------- */

      formData.append(
        "ogTitle",
        form.ogTitle
      );

      formData.append(
        "ogDescription",
        form.ogDescription
      );

      formData.append(
        "ogImageAlt",
        form.ogImageAlt
      );

      formData.append(
        "ogImageTitle",
        form.ogImageTitle
      );

      /*
       * OG IMAGE REMOVAL FLAG
       */

      formData.append(
        "removeOgImage",
        String(removeOgImage)
      );

      /*
       * OG IMAGE FILE
       *
       * Only append when the user has
       * selected a new OG image.
       */

      if (ogImage) {
        formData.append(
          "ogImage",
          ogImage
        );
      }

      /* -----------------------------------------------
         STATUS
      ----------------------------------------------- */

      formData.append(
        "status",
        form.status
      );

      /* -----------------------------------------------
         COVER IMAGE
         Hero image
      ----------------------------------------------- */

      formData.append(
        "removeCoverImage",
        String(removeCoverImage)
      );

      if (coverImage) {
        formData.append(
          "coverImage",
          coverImage
        );
      }

      /* -----------------------------------------------
         INTRO IMAGE
         Introduction / Overview image
      ----------------------------------------------- */

      formData.append(
        "removeIntroImage",
        String(removeIntroImage)
      );

      if (introImage) {
        formData.append(
          "introImage",
          introImage
        );
      }

      /* -----------------------------------------------
         GALLERY
      ----------------------------------------------- */

      formData.append(
        "existingGallery",
        JSON.stringify(
          existingGallery
        )
      );

      gallery.forEach(
        (image) => {
          formData.append(
            "gallery",
            image
          );
        }
      );

      /* -----------------------------------------------
         FAQ
      ----------------------------------------------- */

      formData.append(
        "faqs",
        JSON.stringify(faqs)
      );

      /* -----------------------------------------------
         CREATE / UPDATE
      ----------------------------------------------- */

      if (blogId) {
        await updateBlog(
          blogId,
          formData
        );

        await queryClient.invalidateQueries({
          queryKey: ["blogs"],
        });

        await queryClient.invalidateQueries({
          queryKey: [
            "blog",
            blogId,
          ],
        });

        toast.success(
          "Blog updated successfully."
        );
      } else {
        await createBlog(
          formData
        );

        toast.success(
          "Blog created successfully."
        );
      }

      router.push("/blogs");
    } catch (error) {
      console.error(error);

      toast.error(
        blogId
          ? "Failed to update blog."
          : "Failed to create blog."
      );
    } finally {
      setLoading(false);
    }
  };

  /* =====================================================
     LOADING
  ===================================================== */

  if (
    blogId &&
    isLoading
  ) {
    return (
      <div className="rounded-2xl border bg-white p-12 text-center animate-pulse">
        Loading Blog...
      </div>
    );
  }

  /* =====================================================
     UI
  ===================================================== */

  return (
    <form
      onSubmit={handleSubmit}
      className="space-y-8 rounded-2xl border bg-white p-8"
    >
      {/* =================================================
          HEADER
      ================================================= */}

      <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
        <h2 className="text-2xl font-bold">
          {blogId
            ? "Edit Blog"
            : "Create Blog"}
        </h2>

        {/* =================================================
            EXCEL IMPORT
        ================================================= */}

        <div className="flex flex-col items-start gap-2 sm:items-end">
          <input
            ref={excelInputRef}
            type="file"
            accept=".xlsx,.xls"
            onChange={
              handleExcelImport
            }
            className="hidden"
          />

          <button
            type="button"
            disabled={
              importingExcel ||
              loading
            }
            onClick={() =>
              excelInputRef.current?.click()
            }
            className="rounded-xl border border-[#C9A227] px-5 py-3 font-semibold text-[#9c7a12] transition hover:bg-[#C9A227] hover:text-white disabled:cursor-not-allowed disabled:opacity-50"
          >
            {importingExcel
              ? "Importing..."
              : "Import from Excel"}
          </button>

          <p className="text-xs text-gray-500">
            Imports the first blog row
            from the Excel file.
          </p>
        </div>
      </div>

      {/* =================================================
          TITLE
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Blog Title
        </label>

        <input
          value={form.title}
          onChange={(e) => {
            setForm((prev) => ({
              ...prev,
              title: e.target.value,
            }));
          }}
          className="w-full rounded-xl border p-3"
          placeholder="Enter blog title"
        />
      </div>

      {/* =================================================
          SLUG
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          URL Slug
        </label>

        <input
          value={form.slug}
          onChange={(e) => {
            setForm((prev) => ({
              ...prev,
              slug: e.target.value
                .toLowerCase()
                .trim()
                .replace(/\s+/g, "-")
                .replace(/[^a-z0-9-]/g, ""),
            }));
          }}
          className="w-full rounded-xl border p-3"
          placeholder="example-luxury-wedding-venues-pune"
        />

        <p className="mt-2 text-xs text-gray-500">
          For Excel import, the slug must
          be manually provided in the
          Excel file. It is not generated
          from the title.
        </p>
      </div>

      {/* =================================================
          EXCERPT
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Short Description
        </label>

        <textarea
          rows={4}
          value={form.excerpt}
          onChange={(e) =>
            setForm({
              ...form,
              excerpt:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="Short summary..."
        />
      </div>

      {/* =================================================
          COVER IMAGE
          HERO IMAGE
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Cover Image
        </label>

        <p className="mb-3 text-sm text-gray-500">
          This image will be displayed as the main hero image of the blog.
        </p>

        {/* Existing */}

        {blogId &&
          data?.data?.coverImage &&
          !coverImage &&
          !removeCoverImage && (
            <div className="relative mb-4">
              <img
                src={
                  data.data.coverImage
                }
                alt="Current Cover"
                className="h-56 w-full rounded-xl border object-cover"
              />

              <button
                type="button"
                onClick={() =>
                  setRemoveCoverImage(
                    true
                  )
                }
                className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
              >
                Replace Cover Image
              </button>
            </div>
          )}

        {/* New preview */}

        {coverImage && (
          <div className="relative mb-4">
            <img
              src={URL.createObjectURL(
                coverImage
              )}
              alt="New Cover"
              className="h-56 w-full rounded-xl border object-cover"
            />

            <button
              type="button"
              onClick={() =>
                setCoverImage(null)
              }
              className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
            >
              Remove New Image
            </button>
          </div>
        )}

        <input
          type="file"
          accept="image/*"
          onChange={(e) => {
            if (
              e.target.files?.length
            ) {
              setCoverImage(
                e.target.files[0]
              );

              setRemoveCoverImage(
                false
              );
            }
          }}
          className="block w-full rounded-xl border p-3"
        />

        {blogId && (
          <p className="mt-2 text-sm text-gray-500">
            Leave empty to keep the existing cover image.
          </p>
        )}
      </div>

      {/* =================================================
          INTRODUCTION IMAGE
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Introduction Image
        </label>

        <p className="mb-3 text-sm text-gray-500">
          This is separate from the cover image. It will appear beside the Introduction section.
        </p>

        {/* Existing intro image */}

        {blogId &&
          data?.data?.introImage &&
          !introImage &&
          !removeIntroImage && (
            <div className="relative mb-4">
              <img
                src={
                  data.data.introImage
                }
                alt="Current Introduction"
                className="h-56 w-full rounded-xl border object-cover"
              />

              <button
                type="button"
                onClick={() =>
                  setRemoveIntroImage(
                    true
                  )
                }
                className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
              >
                Remove
              </button>
            </div>
          )}

        {/* New intro preview */}

        {introImage && (
          <div className="relative mb-4">
            <img
              src={URL.createObjectURL(
                introImage
              )}
              alt="New Introduction"
              className="h-56 w-full rounded-xl border object-cover"
            />

            <button
              type="button"
              onClick={() =>
                setIntroImage(null)
              }
              className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
            >
              Remove New Image
            </button>
          </div>
        )}

        <input
          type="file"
          accept="image/*"
          onChange={(e) => {
            if (
              e.target.files?.length
            ) {
              setIntroImage(
                e.target.files[0]
              );

              setRemoveIntroImage(
                false
              );
            }
          }}
          className="block w-full rounded-xl border p-3"
        />

        {blogId && (
          <p className="mt-2 text-sm text-gray-500">
            Leave empty to keep the existing introduction image.
          </p>
        )}
      </div>

      {/* =================================================
          BLOG CONTENT SECTIONS
      ================================================= */}

      <div>
        <BlogSectionEditor
          sections={sections}
          setSections={setSections}
        />
      </div>

      {/* =================================================
          CATEGORY
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Category
        </label>

        <select
          value={form.category}
          onChange={(e) =>
            setForm({
              ...form,
              category:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
        >
          <option value="Wedding">
            Wedding
          </option>

          <option value="Corporate">
            Corporate
          </option>

          <option value="Stay">
            Stay
          </option>

          <option value="Photoshoot">
            Photoshoot
          </option>

          <option value="Events">
            Events
          </option>

          <option value="Awards">
            Awards
          </option>
        </select>
      </div>

      {/* =================================================
          TAGS
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Tags
        </label>

        <input
          value={form.tags}
          onChange={(e) =>
            setForm({
              ...form,
              tags:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="Luxury, Wedding, Pune"
        />
      </div>

      {/* =================================================
          GALLERY
      ================================================= */}

      <GalleryUploader
        existingGallery={
          existingGallery
        }
        setExistingGallery={
          setExistingGallery
        }
        gallery={gallery}
        setGallery={setGallery}
      />

      {/* =================================================
          FAQ
      ================================================= */}

      <FaqEditor
        faqs={faqs}
        setFaqs={setFaqs}
      />

      <hr />

      {/* =================================================
          SEO
      ================================================= */}

      <div>
        <h2 className="text-xl font-bold">
          SEO Settings
        </h2>
      </div>

      {/* SEO TITLE */}

      <div>
        <label className="mb-2 block font-semibold">
          SEO Title
        </label>

        <input
          value={form.seoTitle}
          onChange={(e) =>
            setForm({
              ...form,
              seoTitle:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="SEO title for search engines"
        />
      </div>

      {/* META DESCRIPTION */}

      <div>
        <label className="mb-2 block font-semibold">
          Meta Description
        </label>

        <textarea
          rows={4}
          value={
            form.metaDescription
          }
          onChange={(e) =>
            setForm({
              ...form,
              metaDescription:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="Meta description for search engines"
        />
      </div>

      {/* META KEYWORDS */}

      <div>
        <label className="mb-2 block font-semibold">
          Meta Keywords
        </label>

        <input
          value={
            form.metaKeywords
          }
          onChange={(e) =>
            setForm({
              ...form,
              metaKeywords:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="wedding,pune,resort,luxury"
        />
      </div>

      {/* =================================================
          CANONICAL URL
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Canonical URL
        </label>

        <input
          type="url"
          value={
            form.canonicalUrl
          }
          onChange={(e) =>
            setForm({
              ...form,
              canonicalUrl:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
          placeholder="https://www.example.com/blogs/example-blog"
        />

        <p className="mt-2 text-xs text-gray-500">
          The preferred URL for this blog page.
        </p>
      </div>

      {/* =================================================
          OPEN GRAPH
      ================================================= */}

      <div className="space-y-6">
        <div>
          <h2 className="text-xl font-bold">
            Open Graph Settings
          </h2>
        </div>

        {/* OG TITLE */}

        <div>
          <label className="mb-2 block font-semibold">
            OG Title
          </label>

          <input
            value={form.ogTitle}
            onChange={(e) =>
              setForm({
                ...form,
                ogTitle:
                  e.target.value,
              })
            }
            className="w-full rounded-xl border p-3"
            placeholder="Title shown when the blog is shared"
          />
        </div>

        {/* OG DESCRIPTION */}

        <div>
          <label className="mb-2 block font-semibold">
            OG Description
          </label>

          <textarea
            rows={4}
            value={
              form.ogDescription
            }
            onChange={(e) =>
              setForm({
                ...form,
                ogDescription:
                  e.target.value,
              })
            }
            className="w-full rounded-xl border p-3"
            placeholder="Description shown when the blog is shared"
          />
        </div>

        {/* =================================================
            OG IMAGE UPLOAD
        ================================================= */}

        <div>
          <label className="mb-2 block font-semibold">
            OG Image
          </label>

          <p className="mb-3 text-sm text-gray-500">
            Upload the image that should appear when this blog is shared on social platforms.
          </p>

          {/* Existing OG Image */}

          {blogId &&
            data?.data?.ogImage &&
            !ogImage &&
            !removeOgImage && (
              <div className="relative mb-4">
                <img
                  src={
                    data.data.ogImage
                  }
                  alt={
                    data.data.ogImageAlt ||
                    "Current OG Image"
                  }
                  className="h-56 w-full rounded-xl border object-cover"
                />

                <button
                  type="button"
                  onClick={() =>
                    setRemoveOgImage(
                      true
                    )
                  }
                  className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
                >
                  Replace OG Image
                </button>
              </div>
            )}

          {/* New OG Image Preview */}

          {ogImage && (
            <div className="relative mb-4">
              <img
                src={URL.createObjectURL(
                  ogImage
                )}
                alt="New OG Image"
                className="h-56 w-full rounded-xl border object-cover"
              />

              <button
                type="button"
                onClick={() =>
                  setOgImage(null)
                }
                className="absolute right-3 top-3 rounded-lg bg-red-500 px-4 py-2 text-white"
              >
                Remove New Image
              </button>
            </div>
          )}

          {/* OG Image File Input */}

          <input
            type="file"
            accept="image/*"
            onChange={(e) => {
              if (
                e.target.files?.length
              ) {
                setOgImage(
                  e.target.files[0]
                );

                setRemoveOgImage(
                  false
                );
              }
            }}
            className="block w-full rounded-xl border p-3"
          />

          {blogId && (
            <p className="mt-2 text-sm text-gray-500">
              Leave empty to keep the existing OG image.
            </p>
          )}
        </div>

        {/* OG IMAGE ALT */}

        <div>
          <label className="mb-2 block font-semibold">
            OG Image Alt
          </label>

          <input
            value={
              form.ogImageAlt
            }
            onChange={(e) =>
              setForm({
                ...form,
                ogImageAlt:
                  e.target.value,
              })
            }
            className="w-full rounded-xl border p-3"
            placeholder="Luxury wedding venue in Pune"
          />
        </div>

        {/* OG IMAGE TITLE */}

        <div>
          <label className="mb-2 block font-semibold">
            OG Image Title
          </label>

          <input
            value={
              form.ogImageTitle
            }
            onChange={(e) =>
              setForm({
                ...form,
                ogImageTitle:
                  e.target.value,
              })
            }
            className="w-full rounded-xl border p-3"
            placeholder="Luxury Wedding Venue in Pune"
          />
        </div>
      </div>

      {/* =================================================
          STATUS
      ================================================= */}

      <div>
        <label className="mb-2 block font-semibold">
          Status
        </label>

        <select
          value={form.status}
          onChange={(e) =>
            setForm({
              ...form,
              status:
                e.target.value,
            })
          }
          className="w-full rounded-xl border p-3"
        >
          <option value="Draft">
            Draft
          </option>

          <option value="Published">
            Published
          </option>

          <option value="Archived">
            Archived
          </option>
        </select>
      </div>

      {/* =================================================
          BUTTONS
      ================================================= */}

      <div className="flex justify-end gap-4">
        {/* SAVE DRAFT */}

        <button
          type="button"
          disabled={loading}
          onClick={() => {
            setForm((prev) => ({
              ...prev,
              status: "Draft",
            }));

            setTimeout(() => {
              (
                document.querySelector(
                  "form"
                ) as HTMLFormElement
              )?.requestSubmit();
            }, 0);
          }}
          className="rounded-xl border px-6 py-3 hover:bg-gray-100 disabled:opacity-50"
        >
          Save Draft
        </button>

        {/* PUBLISH / UPDATE */}

        <button
          type="submit"
          disabled={loading}
          className="rounded-xl bg-[#C9A227] px-6 py-3 text-white transition hover:bg-[#b08d1d] disabled:cursor-not-allowed disabled:opacity-50"
        >
          {loading
            ? blogId
              ? "Updating..."
              : "Publishing..."
            : blogId
            ? "Update Blog"
            : "Publish Blog"}
        </button>
      </div>
    </form>
  );
}