"use client";

import {
  ChangeEvent,
  FormEvent,
  useState,
} from "react";

import Link from "next/link";
import { useRouter } from "next/navigation";

import { createClient } from "../../../../lib/supabase/client";


type Category = {
  id: string;
  name: string;
};


type Media = {
  id: string;
  media_type: string;
  media_url: string;
  sort_order: number;
} | null;


type Product = {
  id: string;
  name: string;
  slug: string;
  description: string | null;
  price: number | string;
  category_id: string | null;
  is_available: boolean;
  is_featured: boolean;
  featured_image_url: string | null;
};


type Props = {
  product: Product;
  categories: Category[];
  existingImage: Media;
  existingVideo: Media;
};


export default function EditProductForm({
  product,
  categories,
  existingImage,
  existingVideo,
}: Props) {

  const router = useRouter();
  const supabase = createClient();


  // =====================================================
  // FORM STATE
  // =====================================================

  const [name, setName] =
    useState(product.name);

  const [categoryId, setCategoryId] =
    useState(product.category_id ?? "");

  const [price, setPrice] =
    useState(String(product.price));

  const [description, setDescription] =
    useState(product.description ?? "");

  const [isAvailable, setIsAvailable] =
    useState(product.is_available);

  const [isFeatured, setIsFeatured] =
    useState(product.is_featured);

  const [imageFile, setImageFile] =
    useState<File | null>(null);

  const [videoFile, setVideoFile] =
    useState<File | null>(null);

  const [saving, setSaving] =
    useState(false);

  const [errorMessage, setErrorMessage] =
    useState("");

  const [successMessage, setSuccessMessage] =
    useState("");


  // =====================================================
  // CREATE PRODUCT SLUG
  // =====================================================

  function createSlug(value: string) {
    return value
      .toLowerCase()
      .trim()
      .replace(/[^a-z0-9]+/g, "-")
      .replace(/^-+|-+$/g, "");
  }


  // =====================================================
  // GET STORAGE PATH FROM SUPABASE PUBLIC URL
  // =====================================================

  function getStoragePath(publicUrl: string) {

    const marker =
      "/storage/v1/object/public/product-media/";

    const index =
      publicUrl.indexOf(marker);

    if (index === -1) {
      return null;
    }

    return decodeURIComponent(
      publicUrl.substring(
        index + marker.length
      )
    );
  }


  // =====================================================
  // IMAGE SELECTION
  // =====================================================

  function handleImage(
    event: ChangeEvent<HTMLInputElement>
  ) {

    const file =
      event.target.files?.[0] ?? null;

    if (!file) {
      setImageFile(null);
      return;
    }

    if (!file.type.startsWith("image/")) {

      setErrorMessage(
        "Please choose a valid image file."
      );

      event.target.value = "";

      return;
    }

    if (file.size > 5 * 1024 * 1024) {

      setErrorMessage(
        "The image must be 5 MB or smaller."
      );

      event.target.value = "";

      return;
    }

    setErrorMessage("");
    setImageFile(file);
  }


  // =====================================================
  // VIDEO SELECTION
  // =====================================================

  function handleVideo(
    event: ChangeEvent<HTMLInputElement>
  ) {

    const file =
      event.target.files?.[0] ?? null;

    if (!file) {
      setVideoFile(null);
      return;
    }

    if (!file.type.startsWith("video/")) {

      setErrorMessage(
        "Please choose a valid video file."
      );

      event.target.value = "";

      return;
    }

    if (file.size > 6 * 1024 * 1024) {

      setErrorMessage(
        "For now, product videos must be 6 MB or smaller."
      );

      event.target.value = "";

      return;
    }

    setErrorMessage("");
    setVideoFile(file);
  }


  // =====================================================
  // SAVE PRODUCT
  // =====================================================

  async function handleSubmit(
    event: FormEvent<HTMLFormElement>
  ) {

    event.preventDefault();

    setSaving(true);
    setErrorMessage("");
    setSuccessMessage("");


    const newlyUploadedPaths: string[] = [];
    const newlyCreatedMediaIds: string[] = [];


    try {

      // -------------------------------------------------
      // VALIDATION
      // -------------------------------------------------

      const cleanName = name.trim();

      if (!cleanName) {
        throw new Error(
          "Product name is required."
        );
      }


      if (!categoryId) {
        throw new Error(
          "Please select a category."
        );
      }


      const numericPrice =
        Number(price);


      if (
        Number.isNaN(numericPrice) ||
        numericPrice < 0
      ) {

        throw new Error(
          "Please enter a valid product price."
        );
      }


      const slug =
        createSlug(cleanName);


      if (!slug) {
        throw new Error(
          "Please enter a valid product name."
        );
      }


      let finalImageUrl =
        product.featured_image_url;


      // =================================================
      // UPLOAD NEW COVER IMAGE
      // =================================================

      if (imageFile) {

        const extension =
          imageFile.name
            .split(".")
            .pop()
            ?.toLowerCase() || "jpg";


        const imagePath =
          `products/${product.id}/` +
          `cover-${crypto.randomUUID()}.${extension}`;


        const {
          error: imageUploadError,
        } = await supabase.storage
          .from("product-media")
          .upload(
            imagePath,
            imageFile,
            {
              contentType:
                imageFile.type,

              upsert: false,
            }
          );


        if (imageUploadError) {
          throw imageUploadError;
        }


        newlyUploadedPaths.push(
          imagePath
        );


        const {
          data: imagePublicData,
        } = supabase.storage
          .from("product-media")
          .getPublicUrl(imagePath);


        finalImageUrl =
          imagePublicData.publicUrl;


        const {
          data: imageMedia,
          error: imageMediaError,
        } = await supabase
          .from("product_media")
          .insert({
            product_id:
              product.id,

            media_type:
              "image",

            media_url:
              finalImageUrl,

            sort_order:
              0,
          })
          .select("id")
          .single();


        if (imageMediaError) {
          throw imageMediaError;
        }


        newlyCreatedMediaIds.push(
          imageMedia.id
        );
      }


      // =================================================
      // UPLOAD NEW PRODUCT VIDEO
      // =================================================

      if (videoFile) {

        const extension =
          videoFile.name
            .split(".")
            .pop()
            ?.toLowerCase() || "mp4";


        const videoPath =
          `products/${product.id}/` +
          `video-${crypto.randomUUID()}.${extension}`;


        const {
          error: videoUploadError,
        } = await supabase.storage
          .from("product-media")
          .upload(
            videoPath,
            videoFile,
            {
              contentType:
                videoFile.type,

              upsert: false,
            }
          );


        if (videoUploadError) {
          throw videoUploadError;
        }


        newlyUploadedPaths.push(
          videoPath
        );


        const {
          data: videoPublicData,
        } = supabase.storage
          .from("product-media")
          .getPublicUrl(videoPath);


        const {
          data: videoMedia,
          error: videoMediaError,
        } = await supabase
          .from("product_media")
          .insert({
            product_id:
              product.id,

            media_type:
              "video",

            media_url:
              videoPublicData.publicUrl,

            sort_order:
              1,
          })
          .select("id")
          .single();


        if (videoMediaError) {
          throw videoMediaError;
        }


        newlyCreatedMediaIds.push(
          videoMedia.id
        );
      }


      // =================================================
      // UPDATE PRODUCT DETAILS
      // =================================================

      const {
        error: productUpdateError,
      } = await supabase
        .from("products")
        .update({
          name:
            cleanName,

          slug:
            slug,

          category_id:
            categoryId,

          price:
            numericPrice,

          description:
            description.trim() || null,

          is_available:
            isAvailable,

          is_featured:
            isFeatured,

          featured_image_url:
            finalImageUrl,
        })
        .eq(
          "id",
          product.id
        );


      if (productUpdateError) {

        if (
          productUpdateError.message
            .toLowerCase()
            .includes("duplicate")
        ) {

          throw new Error(
            "Another product already uses this product name or slug."
          );
        }

        throw productUpdateError;
      }


      // =================================================
      // REMOVE OLD COVER IMAGE
      // =================================================

      if (imageFile) {

        if (existingImage) {

          const oldImagePath =
            getStoragePath(
              existingImage.media_url
            );


          const {
            error:
              oldImageRecordError,
          } = await supabase
            .from("product_media")
            .delete()
            .eq(
              "id",
              existingImage.id
            );


          if (oldImageRecordError) {
            console.error(
              "Could not delete old image record:",
              oldImageRecordError
            );
          }


          if (oldImagePath) {

            const {
              error:
                oldImageStorageError,
            } = await supabase.storage
              .from("product-media")
              .remove([
                oldImagePath,
              ]);


            if (
              oldImageStorageError
            ) {

              console.error(
                "Could not remove old image:",
                oldImageStorageError
              );
            }
          }

        } else if (
          product.featured_image_url
        ) {

          const oldFeaturedPath =
            getStoragePath(
              product.featured_image_url
            );


          if (oldFeaturedPath) {

            const {
              error:
                oldFeaturedStorageError,
            } = await supabase.storage
              .from("product-media")
              .remove([
                oldFeaturedPath,
              ]);


            if (
              oldFeaturedStorageError
            ) {

              console.error(
                "Could not remove old featured image:",
                oldFeaturedStorageError
              );
            }
          }
        }
      }


      // =================================================
      // REMOVE OLD PRODUCT VIDEO
      // =================================================

      if (
        videoFile &&
        existingVideo
      ) {

        const oldVideoPath =
          getStoragePath(
            existingVideo.media_url
          );


        const {
          error:
            oldVideoRecordError,
        } = await supabase
          .from("product_media")
          .delete()
          .eq(
            "id",
            existingVideo.id
          );


        if (oldVideoRecordError) {

          console.error(
            "Could not delete old video record:",
            oldVideoRecordError
          );
        }


        if (oldVideoPath) {

          const {
            error:
              oldVideoStorageError,
          } = await supabase.storage
            .from("product-media")
            .remove([
              oldVideoPath,
            ]);


          if (
            oldVideoStorageError
          ) {

            console.error(
              "Could not remove old video:",
              oldVideoStorageError
            );
          }
        }
      }


      // =================================================
      // SUCCESS
      // =================================================

      setSuccessMessage(
        "Product updated successfully."
      );


      router.push(
        "/admin/products"
      );

      router.refresh();

    } catch (error) {

      console.error(
        "Product update error:",
        error
      );


      // -------------------------------------------------
      // CLEAN NEW DATABASE MEDIA RECORDS
      // -------------------------------------------------

      if (
        newlyCreatedMediaIds.length > 0
      ) {

        await supabase
          .from("product_media")
          .delete()
          .in(
            "id",
            newlyCreatedMediaIds
          );
      }


      // -------------------------------------------------
      // CLEAN NEW STORAGE FILES
      // -------------------------------------------------

      if (
        newlyUploadedPaths.length > 0
      ) {

        await supabase.storage
          .from("product-media")
          .remove(
            newlyUploadedPaths
          );
      }


      setErrorMessage(
        error instanceof Error
          ? error.message
          : "Unable to update product."
      );

    } finally {

      setSaving(false);
    }
  }


  // =====================================================
  // PAGE
  // =====================================================

  return (

    <form
      onSubmit={handleSubmit}
      className="mt-10 space-y-7 rounded-[32px] bg-white p-6 shadow-sm md:p-10"
    >


      {/* =================================================
          PRODUCT NAME
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Product Name
        </label>

        <input
          type="text"
          value={name}
          onChange={(event) =>
            setName(
              event.target.value
            )
          }
          required
          placeholder="Product name"
          className="mt-2 w-full rounded-2xl border border-black/10 px-4 py-4 outline-none focus:border-black"
        />

      </div>


      {/* =================================================
          CATEGORY
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Category
        </label>

        <select
          value={categoryId}
          onChange={(event) =>
            setCategoryId(
              event.target.value
            )
          }
          required
          className="mt-2 w-full rounded-2xl border border-black/10 bg-white px-4 py-4 outline-none focus:border-black"
        >

          <option value="">
            Select category
          </option>

          {categories.map(
            (category) => (

              <option
                key={category.id}
                value={category.id}
              >
                {category.name}
              </option>

            )
          )}

        </select>

      </div>


      {/* =================================================
          PRICE
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Base Price (₦)
        </label>

        <input
          type="number"
          min="0"
          step="0.01"
          value={price}
          onChange={(event) =>
            setPrice(
              event.target.value
            )
          }
          required
          placeholder="6000"
          className="mt-2 w-full rounded-2xl border border-black/10 px-4 py-4 outline-none focus:border-black"
        />

        <p className="mt-2 text-xs text-black/40">
          This is the default product price.
          Sizes can have their own prices.
        </p>

      </div>


      {/* =================================================
          DESCRIPTION
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Description
        </label>

        <textarea
          value={description}
          onChange={(event) =>
            setDescription(
              event.target.value
            )
          }
          rows={5}
          placeholder="Describe the product..."
          className="mt-2 w-full resize-none rounded-2xl border border-black/10 px-4 py-4 outline-none focus:border-black"
        />

      </div>


      {/* =================================================
          AVAILABILITY / FEATURED
      ================================================= */}

      <div className="grid gap-5 sm:grid-cols-2">


        <label className="flex cursor-pointer items-center gap-3 rounded-2xl bg-[#f7f3ee] p-4">

          <input
            type="checkbox"
            checked={isAvailable}
            onChange={(event) =>
              setIsAvailable(
                event.target.checked
              )
            }
          />

          <div>

            <p className="font-bold">
              Available
            </p>

            <p className="text-xs text-black/50">
              Customers can order this product.
            </p>

          </div>

        </label>


        <label className="flex cursor-pointer items-center gap-3 rounded-2xl bg-[#f7f3ee] p-4">

          <input
            type="checkbox"
            checked={isFeatured}
            onChange={(event) =>
              setIsFeatured(
                event.target.checked
              )
            }
          />

          <div>

            <p className="font-bold">
              Featured Product
            </p>

            <p className="text-xs text-black/50">
              Highlight this product in PELCY.
            </p>

          </div>

        </label>


      </div>


      {/* =================================================
          CURRENT COVER IMAGE
      ================================================= */}

      {product.featured_image_url && (

        <div>

          <p className="text-sm font-bold">
            Current Cover Image
          </p>

          <img
            src={
              product.featured_image_url
            }
            alt={
              product.name
            }
            className="mt-3 h-44 w-44 rounded-3xl object-cover"
          />

        </div>

      )}


      {/* =================================================
          REPLACE COVER IMAGE
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Replace Cover Image
        </label>

        <input
          type="file"
          accept="image/*"
          onChange={handleImage}
          className="mt-3 block w-full rounded-2xl border border-dashed border-black/20 p-4"
        />

        <p className="mt-2 text-xs text-black/40">
          Leave empty to keep the current image.
        </p>

        {imageFile && (

          <p className="mt-2 text-sm font-medium text-green-700">
            New image selected:{" "}
            {imageFile.name}
          </p>

        )}

      </div>


      {/* =================================================
          CURRENT PRODUCT VIDEO
      ================================================= */}

      {existingVideo && (

        <div>

          <p className="text-sm font-bold">
            Current Product Video
          </p>

          <video
            src={
              existingVideo.media_url
            }
            controls
            playsInline
            preload="metadata"
            className="mt-3 aspect-square w-full max-w-[300px] rounded-3xl bg-black object-cover"
          >
            Your browser does not support
            video playback.
          </video>

        </div>

      )}


      {/* =================================================
          REPLACE PRODUCT VIDEO
      ================================================= */}

      <div>

        <label className="text-sm font-bold">
          Replace Product Video
        </label>

        <input
          type="file"
          accept="video/*"
          onChange={handleVideo}
          className="mt-3 block w-full rounded-2xl border border-dashed border-black/20 p-4"
        />

        <p className="mt-2 text-xs text-black/40">
          Leave empty to keep the current video.
          For now use videos 6 MB or smaller.
        </p>

        {videoFile && (

          <p className="mt-2 text-sm font-medium text-green-700">
            New video selected:{" "}
            {videoFile.name}
          </p>

        )}

      </div>


      {/* =================================================
          ERROR MESSAGE
      ================================================= */}

      {errorMessage && (

        <div className="rounded-2xl bg-red-100 p-4 text-sm font-medium text-red-700">
          {errorMessage}
        </div>

      )}


      {/* =================================================
          SUCCESS MESSAGE
      ================================================= */}

      {successMessage && (

        <div className="rounded-2xl bg-green-100 p-4 text-sm font-medium text-green-700">
          {successMessage}
        </div>

      )}


      {/* =================================================
          ACTION BUTTONS
      ================================================= */}

      <div className="flex flex-col gap-3 sm:flex-row sm:flex-wrap">


        {/* SAVE */}

        <button
          type="submit"
          disabled={saving}
          className="inline-flex items-center justify-center rounded-full bg-[#2b2118] px-7 py-4 font-bold text-white disabled:cursor-not-allowed disabled:opacity-50"
        >
          {saving
            ? "Saving Changes..."
            : "Save Changes"}
        </button>


        {/* MANAGE VARIANTS */}

        <Link
          href={`/admin/products/${product.id}/variants`}
          className="inline-flex items-center justify-center rounded-full bg-[#9b6a44] px-7 py-4 font-bold text-white transition hover:opacity-90"
        >
          Manage Sizes & Prices
        </Link>


        {/* CANCEL */}

        <button
          type="button"
          onClick={() =>
            router.push(
              "/admin/products"
            )
          }
          className="inline-flex items-center justify-center rounded-full border border-black/15 px-7 py-4 font-bold transition hover:bg-black hover:text-white"
        >
          Cancel
        </button>


      </div>


    </form>

  );
}