import React, { useState, useEffect, useRef } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { Item, Rental, Address } from "../types";
import { useAuth } from "../contexts/AuthContext";
import { itemAPI, rentalAPI, addressAPI, userAPI } from "../services/api";
import { uploadImagesWithVariants, getImageUrl } from "../services/uploadService";
import AvailabilitySettings from "../components/AvailabilitySettings";
import ImageUpload from "../components/ImageUpload";
import ItemInformation from "../components/ItemInformation";
import LocationForm from "../components/LocationForm";
import PricingForm from "../components/PricingForm";
import RulesForm from "../components/RulesForm";
import { IMAGE_LIMITS } from "../config/imageLimits";

interface ItemFormData {
  name: string;
  description: string;
  pricePerHour?: number | string;
  pricePerDay?: number | string;
  pricePerWeek?: number | string;
  pricePerMonth?: number | string;
  replacementCost: number | string;
  address1: string;
  address2: string;
  city: string;
  state: string;
  zipCode: string;
  country: string;
  latitude?: number;
  longitude?: number;
  rules?: string;
  generalAvailableAfter: string;
  generalAvailableBefore: string;
  specifyTimesPerDay: boolean;
  weeklyTimes: {
    sunday: { availableAfter: string; availableBefore: string };
    monday: { availableAfter: string; availableBefore: string };
    tuesday: { availableAfter: string; availableBefore: string };
    wednesday: { availableAfter: string; availableBefore: string };
    thursday: { availableAfter: string; availableBefore: string };
    friday: { availableAfter: string; availableBefore: string };
    saturday: { availableAfter: string; availableBefore: string };
  };
}

const EditItem: React.FC = () => {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const { user } = useAuth();
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState(false);
  const [imageFiles, setImageFiles] = useState<File[]>([]);
  const [imagePreviews, setImagePreviews] = useState<string[]>([]);
  const [existingImageKeys, setExistingImageKeys] = useState<string[]>([]); // S3 keys for existing images
  const [acceptedRentals, setAcceptedRentals] = useState<Rental[]>([]);
  const [userAddresses, setUserAddresses] = useState<Address[]>([]);
  const [selectedAddressId, setSelectedAddressId] = useState<string>("");
  const [addressesLoading, setAddressesLoading] = useState(true);
  const [selectedPricingUnit, setSelectedPricingUnit] = useState<string>("day");
  const [showAdvancedPricing, setShowAdvancedPricing] =
    useState<boolean>(false);
  const [enabledPricingTiers, setEnabledPricingTiers] = useState({
    hour: false,
    day: false,
    week: false,
    month: false,
  });

  // Reference to LocationForm geocoding function
  const geocodeLocationRef = useRef<
    (() => Promise<{ latitude: number; longitude: number } | null>) | null
  >(null);
  const [formData, setFormData] = useState<ItemFormData>({
    name: "",
    description: "",
    pricePerHour: "",
    pricePerDay: "",
    replacementCost: "",
    address1: "",
    address2: "",
    city: "",
    state: "",
    zipCode: "",
    country: "US",
    rules: "",
    generalAvailableAfter: "00:00",
    generalAvailableBefore: "23:00",
    specifyTimesPerDay: false,
    weeklyTimes: {
      sunday: { availableAfter: "00:00", availableBefore: "23:00" },
      monday: { availableAfter: "00:00", availableBefore: "23:00" },
      tuesday: { availableAfter: "00:00", availableBefore: "23:00" },
      wednesday: { availableAfter: "00:00", availableBefore: "23:00" },
      thursday: { availableAfter: "00:00", availableBefore: "23:00" },
      friday: { availableAfter: "00:00", availableBefore: "23:00" },
      saturday: { availableAfter: "00:00", availableBefore: "23:00" },
    },
  });

  useEffect(() => {
    fetchItem();
    fetchAcceptedRentals();
    fetchUserAddresses();
  }, [id]);

  const fetchUserAddresses = async () => {
    try {
      const response = await addressAPI.getAddresses();
      setUserAddresses(response.data || []);
    } catch (error) {
      console.error("Error fetching addresses:", error);
    } finally {
      setAddressesLoading(false);
    }
  };

  const fetchItem = async () => {
    try {
      const response = await itemAPI.getItem(id!);
      const item: Item = response.data;

      if (item.ownerId !== user?.id) {
        setError("You are not authorized to edit this item");
        return;
      }

      // Convert item data to form data format
      setFormData({
        name: item.name,
        description: item.description,
        pricePerHour: item.pricePerHour || "",
        pricePerDay: item.pricePerDay || "",
        pricePerWeek: item.pricePerWeek || "",
        pricePerMonth: item.pricePerMonth || "",
        replacementCost: item.replacementCost || "",
        address1: item.address1 || "",
        address2: item.address2 || "",
        city: item.city || "",
        state: item.state || "",
        zipCode: item.zipCode || "",
        country: item.country || "US",
        latitude: item.latitude,
        longitude: item.longitude,
        rules: item.rules || "",
        generalAvailableAfter: item.availableAfter || "00:00",
        generalAvailableBefore: item.availableBefore || "23:00",
        specifyTimesPerDay: item.specifyTimesPerDay || false,
        weeklyTimes: item.weeklyTimes || {
          sunday: { availableAfter: "00:00", availableBefore: "23:00" },
          monday: { availableAfter: "00:00", availableBefore: "23:00" },
          tuesday: { availableAfter: "00:00", availableBefore: "23:00" },
          wednesday: { availableAfter: "00:00", availableBefore: "23:00" },
          thursday: { availableAfter: "00:00", availableBefore: "23:00" },
          friday: { availableAfter: "00:00", availableBefore: "23:00" },
          saturday: { availableAfter: "00:00", availableBefore: "23:00" },
        },
      });

      // Set existing images - store S3 keys and generate preview URLs
      if (item.imageFilenames && item.imageFilenames.length > 0) {
        setExistingImageKeys(item.imageFilenames);
        // Generate preview URLs from S3 keys (use thumbnail for previews)
        setImagePreviews(item.imageFilenames.map((key: string) => getImageUrl(key, 'thumbnail')));
      }

      // Determine which pricing unit to select based on existing data
      // Priority: hour -> day -> week -> month (first one with a value)
      if (item.pricePerHour) {
        setSelectedPricingUnit("hour");
      } else if (item.pricePerDay) {
        setSelectedPricingUnit("day");
      } else if (item.pricePerWeek) {
        setSelectedPricingUnit("week");
      } else if (item.pricePerMonth) {
        setSelectedPricingUnit("month");
      } else {
        setSelectedPricingUnit("day"); // Default to day if no pricing is set
      }

      // Set enabled tiers based on which prices are populated
      setEnabledPricingTiers({
        hour: !!(item.pricePerHour && Number(item.pricePerHour) > 0),
        day: !!(item.pricePerDay && Number(item.pricePerDay) > 0),
        week: !!(item.pricePerWeek && Number(item.pricePerWeek) > 0),
        month: !!(item.pricePerMonth && Number(item.pricePerMonth) > 0),
      });

      // Auto-expand advanced section if multiple pricing tiers are set
      const pricingTiersSet = [
        item.pricePerHour,
        item.pricePerDay,
        item.pricePerWeek,
        item.pricePerMonth,
      ].filter((price) => price && Number(price) > 0).length;

      if (pricingTiersSet > 1) {
        setShowAdvancedPricing(true);
      }
    } catch (err: any) {
      setError(err.response?.data?.message || "Failed to fetch item");
    } finally {
      setLoading(false);
    }
  };

  const fetchAcceptedRentals = async () => {
    try {
      const response = await rentalAPI.getListings();
      const rentals: Rental[] = response.data;
      // Filter for accepted rentals for this specific item
      const itemRentals = rentals.filter(
        (rental) =>
          rental.itemId === id &&
          ["confirmed", "active"].includes(rental.status)
      );
      setAcceptedRentals(itemRentals);
    } catch (err) {
      console.error("Error fetching rentals:", err);
    }
  };

  const handleChange = (
    e: React.ChangeEvent<
      HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
    >
  ) => {
    const { name, value, type } = e.target;

    if (type === "checkbox") {
      const checked = (e.target as HTMLInputElement).checked;
      setFormData((prev) => ({ ...prev, [name]: checked }));
    } else if (type === "number") {
      setFormData((prev) => ({
        ...prev,
        [name]: value === "" ? "" : parseFloat(value) || 0,
      }));
    } else {
      setFormData((prev) => ({ ...prev, [name]: value }));
    }
  };

  const handleCoordinatesChange = (latitude: number, longitude: number) => {
    setFormData((prev) => ({
      ...prev,
      latitude,
      longitude,
    }));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    // Check total images (existing + new)
    const totalImages = existingImageKeys.length + imageFiles.length;
    if (totalImages === 0) {
      setError("At least one image is required for a listing");
      document.getElementById("image-upload-section")?.scrollIntoView({ behavior: "smooth", block: "center" });
      return;
    }

    if (!formData.name.trim()) {
      setError("Item name is required");
      document.getElementById("name")?.focus();
      return;
    }

    if (!formData.address1.trim()) {
      setError("Address is required");
      document.getElementById("address1")?.focus();
      return;
    }

    if (!formData.city.trim()) {
      setError("City is required");
      document.getElementById("city")?.focus();
      return;
    }

    if (!formData.state.trim()) {
      setError("State is required");
      document.getElementById("state")?.focus();
      return;
    }

    if (!formData.zipCode.trim()) {
      setError("ZIP code is required");
      document.getElementById("zipCode")?.focus();
      return;
    }

    if (!formData.replacementCost || Number(formData.replacementCost) <= 0) {
      setError("Replacement cost is required");
      document.getElementById("replacementCost")?.focus();
      return;
    }

    setSubmitting(true);

    // Try to geocode the address before submitting
    let geocodedCoordinates = null;
    if (geocodeLocationRef.current) {
      try {
        geocodedCoordinates = await geocodeLocationRef.current();
      } catch (error) {
        console.warn(
          "Geocoding failed, updating item without coordinates:",
          error
        );
      }
    } else {
      console.warn("No geocoding function available");
    }

    try {
      // Upload new images to S3 and get their keys (with resizing)
      let newImageKeys: string[] = [];
      if (imageFiles.length > 0) {
        const uploadResults = await uploadImagesWithVariants("item", imageFiles);
        newImageKeys = uploadResults.map((result) => result.baseKey);
      }

      // Combine existing S3 keys with newly uploaded keys
      const allImageKeys = [...existingImageKeys, ...newImageKeys];

      const updatePayload = {
        ...formData,
        // Use geocoded coordinates if available, otherwise fall back to formData
        latitude: geocodedCoordinates?.latitude ?? formData.latitude,
        longitude: geocodedCoordinates?.longitude ?? formData.longitude,
        pricePerDay: formData.pricePerDay
          ? parseFloat(formData.pricePerDay.toString())
          : undefined,
        pricePerHour: formData.pricePerHour
          ? parseFloat(formData.pricePerHour.toString())
          : undefined,
        pricePerWeek: formData.pricePerWeek
          ? parseFloat(formData.pricePerWeek.toString())
          : undefined,
        pricePerMonth: formData.pricePerMonth
          ? parseFloat(formData.pricePerMonth.toString())
          : undefined,
        replacementCost: formData.replacementCost
          ? parseFloat(formData.replacementCost.toString())
          : 0,
        availableAfter: formData.generalAvailableAfter,
        availableBefore: formData.generalAvailableBefore,
        specifyTimesPerDay: formData.specifyTimesPerDay,
        weeklyTimes: formData.weeklyTimes,
        imageFilenames: allImageKeys,
      };

      await itemAPI.updateItem(id!, updatePayload);

      // Check if user has other items - only save to user profile if no other items
      try {
        const userItemsResponse = await itemAPI.getItems({ owner: user?.id });
        const userItems = userItemsResponse.data.items || [];
        const hasOtherItems =
          userItems.filter((item: Item) => item.id !== id).length > 0;

        if (!hasOtherItems) {
          // Save to user profile - this is still their primary/only item
          await userAPI.updateAvailability({
            generalAvailableAfter: formData.generalAvailableAfter,
            generalAvailableBefore: formData.generalAvailableBefore,
            specifyTimesPerDay: formData.specifyTimesPerDay,
            weeklyTimes: formData.weeklyTimes,
          });
        }
      } catch (availabilityError) {
        console.error("Failed to save availability:", availabilityError);
        // Don't fail item update if availability save fails
      }

      setSuccess(true);
      setTimeout(() => {
        navigate(`/items/${id}`);
      }, 1500);
    } catch (err: any) {
      setError(err.response?.data?.message || err.message || "Failed to update item");
    } finally {
      setSubmitting(false);
    }
  };

  const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);

    if (imagePreviews.length + files.length > IMAGE_LIMITS.items) {
      setError(`You can upload a maximum of ${IMAGE_LIMITS.items} images`);
      return;
    }

    const newImageFiles = [...imageFiles, ...files];
    setImageFiles(newImageFiles);
    setError(null); // Clear any previous error

    // Create previews
    files.forEach((file) => {
      const reader = new FileReader();
      reader.onloadend = () => {
        setImagePreviews((prev) => [...prev, reader.result as string]);
      };
      reader.readAsDataURL(file);
    });
  };

  const removeImage = (index: number) => {
    // Check if removing an existing image or a new upload
    if (index < existingImageKeys.length) {
      // Removing an existing S3 image
      setExistingImageKeys((prev) => prev.filter((_, i) => i !== index));
    } else {
      // Removing a new upload - adjust index for the imageFiles array
      const newFileIndex = index - existingImageKeys.length;
      setImageFiles((prev) => prev.filter((_, i) => i !== newFileIndex));
    }
    // Always update previews
    setImagePreviews((prev) => prev.filter((_, i) => i !== index));
  };

  const handleAddressSelect = (addressId: string) => {
    if (addressId === "new") {
      setFormData((prev) => ({
        ...prev,
        address1: "",
        address2: "",
        city: "",
        state: "",
        zipCode: "",
        country: "US",
      }));
      setSelectedAddressId("");
    } else {
      const selectedAddress = userAddresses.find(
        (addr) => addr.id === addressId
      );
      if (selectedAddress) {
        setFormData((prev) => ({
          ...prev,
          address1: selectedAddress.address1,
          address2: selectedAddress.address2 || "",
          city: selectedAddress.city,
          state: selectedAddress.state,
          zipCode: selectedAddress.zipCode,
          country: selectedAddress.country,
          latitude: selectedAddress.latitude,
          longitude: selectedAddress.longitude,
        }));
        setSelectedAddressId(addressId);
      }
    }
  };

  const formatAddressDisplay = (address: Address) => {
    return `${address.address1}, ${address.city}, ${address.state} ${address.zipCode}`;
  };

  const handleWeeklyTimeChange = (
    day: string,
    field: "availableAfter" | "availableBefore",
    value: string
  ) => {
    setFormData((prev) => ({
      ...prev,
      weeklyTimes: {
        ...prev.weeklyTimes,
        [day]: {
          ...prev.weeklyTimes[day as keyof typeof prev.weeklyTimes],
          [field]: value,
        },
      },
    }));
  };

  const handlePricingUnitChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setSelectedPricingUnit(e.target.value);
  };

  const handleToggleAdvancedPricing = () => {
    setShowAdvancedPricing((prev) => !prev);
  };

  const handleTierToggle = (tier: string) => {
    setEnabledPricingTiers((prev) => ({
      ...prev,
      [tier]: !prev[tier as keyof typeof prev],
    }));
  };

  if (loading) {
    return (
      <div className="container mt-5">
        <div className="text-center">
          <div className="spinner-border" role="status">
            <span className="visually-hidden">Loading...</span>
          </div>
        </div>
      </div>
    );
  }

  if (error && error.includes("authorized")) {
    return (
      <div className="container mt-5">
        <div className="alert alert-danger" role="alert">
          {error}
        </div>
      </div>
    );
  }

  return (
    <div className="container mt-4">
      <div className="row justify-content-center">
        <div className="col-md-8">
          <h1>Edit Listing</h1>

          {error && (
            <div className="alert alert-danger" role="alert">
              {error}
            </div>
          )}

          {success && (
            <div className="alert alert-success" role="alert">
              Item updated successfully! Redirecting...
            </div>
          )}

          <form onSubmit={handleSubmit} noValidate>
            <div id="image-upload-section">
              <ImageUpload
                imageFiles={imageFiles}
                imagePreviews={imagePreviews}
                onImageChange={handleImageChange}
                onRemoveImage={removeImage}
                error={error || ""}
              />
            </div>

            <ItemInformation
              name={formData.name}
              description={formData.description}
              onChange={handleChange}
            />

            <LocationForm
              data={{
                address1: formData.address1,
                address2: formData.address2,
                city: formData.city,
                state: formData.state,
                zipCode: formData.zipCode,
                country: formData.country,
                latitude: formData.latitude,
                longitude: formData.longitude,
              }}
              userAddresses={userAddresses}
              selectedAddressId={selectedAddressId}
              addressesLoading={addressesLoading}
              onChange={handleChange}
              onAddressSelect={handleAddressSelect}
              formatAddressDisplay={formatAddressDisplay}
              onCoordinatesChange={handleCoordinatesChange}
              onGeocodeRef={(geocodeFunction) => {
                geocodeLocationRef.current = geocodeFunction;
              }}
            />

            <PricingForm
              pricePerHour={formData.pricePerHour || ""}
              pricePerDay={formData.pricePerDay || ""}
              pricePerWeek={formData.pricePerWeek || ""}
              pricePerMonth={formData.pricePerMonth || ""}
              replacementCost={formData.replacementCost}
              selectedPricingUnit={selectedPricingUnit}
              showAdvancedPricing={showAdvancedPricing}
              enabledTiers={enabledPricingTiers}
              onChange={handleChange}
              onPricingUnitChange={handlePricingUnitChange}
              onToggleAdvancedPricing={handleToggleAdvancedPricing}
              onTierToggle={handleTierToggle}
            />

            <div className="card mb-4">
              <div className="card-body">
                <AvailabilitySettings
                  data={{
                    generalAvailableAfter: formData.generalAvailableAfter,
                    generalAvailableBefore: formData.generalAvailableBefore,
                    specifyTimesPerDay: formData.specifyTimesPerDay,
                    weeklyTimes: formData.weeklyTimes,
                  }}
                  onChange={(field, value) => {
                    setFormData((prev) => ({ ...prev, [field]: value }));
                  }}
                  onWeeklyTimeChange={handleWeeklyTimeChange}
                />
              </div>
            </div>

            <RulesForm
              rules={formData.rules || ""}
              onChange={handleChange}
            />

            <div className="d-grid gap-2 mb-5">
              <button
                type="submit"
                className="btn btn-primary"
                disabled={submitting}
              >
                {submitting ? "Updating..." : "Update Listing"}
              </button>
              <button
                type="button"
                className="btn btn-secondary"
                onClick={() => navigate(-1)}
              >
                Back
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

export default EditItem;
