import React, { useState, useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
import api, { addressAPI, userAPI, itemAPI } from "../services/api";
import { uploadImagesWithVariants } 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 VerificationCodeModal from "../components/VerificationCodeModal";
import { Address } from "../types";
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 CreateItem: React.FC = () => {
  const navigate = useNavigate();
  const { user, checkAuth } = useAuth();
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [showVerificationModal, setShowVerificationModal] = useState(false);
  const [pendingSubmit, setPendingSubmit] = useState(false);
  const [formData, setFormData] = useState<ItemFormData>({
    name: "",
    description: "",
    pricePerDay: "",
    replacementCost: "",
    address1: "",
    address2: "",
    city: "",
    state: "",
    zipCode: "",
    country: "US",
    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" },
    },
  });
  const [imageFiles, setImageFiles] = useState<File[]>([]);
  const [imagePreviews, setImagePreviews] = useState<string[]>([]);
  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);

  useEffect(() => {
    fetchUserAddresses();
    fetchUserAvailability();
  }, []);

  const fetchUserAvailability = async () => {
    try {
      const response = await userAPI.getAvailability();
      const userAvailability = response.data;
      setFormData((prev) => ({
        ...prev,
        generalAvailableAfter: userAvailability.generalAvailableAfter,
        generalAvailableBefore: userAvailability.generalAvailableBefore,
        specifyTimesPerDay: userAvailability.specifyTimesPerDay,
        weeklyTimes: userAvailability.weeklyTimes,
      }));
    } catch (error) {
      console.error("Error fetching user availability:", error);
      // Use default values if fetch fails
    }
  };

  useEffect(() => {
    // Auto-populate if user has exactly one address and addresses have finished loading
    if (
      !addressesLoading &&
      userAddresses.length === 1 &&
      selectedAddressId === ""
    ) {
      const address = userAddresses[0];
      setFormData((prev) => ({
        ...prev,
        address1: address.address1,
        address2: address.address2 || "",
        city: address.city,
        state: address.state,
        zipCode: address.zipCode,
        country: address.country,
        latitude: address.latitude,
        longitude: address.longitude,
      }));
      setSelectedAddressId(address.id);
    }
  }, [userAddresses, addressesLoading]);

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

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!user) {
      setError("You must be logged in to create a listing");
      return;
    }

    if (imageFiles.length === 0) {
      setError("At least one image is required to create 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;
    }

    setLoading(true);
    setError("");

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

    try {
      // Upload images to S3 first (with resizing to thumbnail, medium, original)
      let imageFilenames: string[] = [];
      if (imageFiles.length > 0) {
        const uploadResults = await uploadImagesWithVariants("item", imageFiles);
        imageFilenames = uploadResults.map((result) => result.baseKey);
      }

      // Construct location from address components
      const locationParts = [
        formData.address1,
        formData.address2,
        formData.city,
        formData.state,
        formData.zipCode,
        formData.country,
      ].filter((part) => part && part.trim());

      const location = locationParts.join(", ");

      const response = await api.post("/items", {
        ...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,
        location,
        imageFilenames,
      });

      // Auto-save address if user has no addresses and entered manual address
      if (userAddresses.length === 0 && formData.address1) {
        try {
          await addressAPI.createAddress({
            address1: formData.address1,
            address2: formData.address2,
            city: formData.city,
            state: formData.state,
            zipCode: formData.zipCode,
            country: formData.country,
            latitude: geocodedCoordinates?.latitude ?? formData.latitude,
            longitude: geocodedCoordinates?.longitude ?? formData.longitude,
            isPrimary: true,
          });
        } catch (addressError) {
          console.error("Failed to save address:", addressError);
          // Don't fail item creation if address save fails
        }
      }

      // Check if this is user's first item and save availability settings
      try {
        const userItemsResponse = await itemAPI.getItems({ owner: user.id });
        const userItems = userItemsResponse.data.items || [];

        // If this is their first item (the one we just created), save availability to user
        if (userItems.length <= 1) {
          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 creation if availability save fails
      }

      navigate(`/items/${response.data.id}`);
    } catch (err: any) {
      // Check if it's a 403 verification required error
      if (
        err.response?.status === 403 &&
        err.response?.data?.code === "EMAIL_NOT_VERIFIED"
      ) {
        setPendingSubmit(true);
        setShowVerificationModal(true);
        setError("");
      } else {
        setError(
          err.response?.data?.error || err.message || "Failed to create listing"
        );
      }
    } finally {
      setLoading(false);
    }
  };

  // Handle successful verification - retry form submission
  const handleVerificationSuccess = async () => {
    setShowVerificationModal(false);
    await checkAuth(); // Refresh user data
    if (pendingSubmit) {
      setPendingSubmit(false);
      // Create a synthetic event to trigger handleSubmit
      const syntheticEvent = {
        preventDefault: () => {},
      } as React.FormEvent<HTMLFormElement>;
      handleSubmit(syntheticEvent);
    }
  };

  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 handleAddressSelect = (addressId: string) => {
    if (addressId === "new") {
      // Clear form for new address entry
      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 handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);

    if (imageFiles.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(""); // 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) => {
    setImageFiles((prev) => prev.filter((_, i) => i !== index));
    setImagePreviews((prev) => prev.filter((_, i) => i !== index));
  };

  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],
    }));
  };

  return (
    <div className="container mt-4">
      <div className="row justify-content-center">
        <div className="col-md-8">
          <h1>List an Item for Rent</h1>

          {/* Email verification warning banner */}
          {user && !user.isVerified && (
            <div
              className="alert alert-warning d-flex align-items-center"
              role="alert"
            >
              <i className="bi bi-exclamation-triangle-fill me-2"></i>
              <div className="flex-grow-1">
                Verify your email to create a listing.
              </div>
              <button
                type="button"
                className="btn btn-warning btn-sm"
                onClick={() => setShowVerificationModal(true)}
              >
                Verify Now
              </button>
            </div>
          )}

          {error && (
            <div className="alert alert-danger" role="alert">
              {error}
            </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;
              }}
            />

            {/* Availability Card */}
            <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>

            <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}
            />

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

            <div className="d-grid gap-2 mb-5">
              <button
                type="submit"
                className="btn btn-primary"
                disabled={loading}
              >
                {loading ? "Creating..." : "Create Listing"}
              </button>
              <button
                type="button"
                className="btn btn-secondary"
                onClick={() => navigate(-1)}
              >
                Cancel
              </button>
            </div>
          </form>
        </div>
      </div>

      {/* Verification Code Modal */}
      {showVerificationModal && user && (
        <VerificationCodeModal
          show={showVerificationModal}
          onHide={() => {
            setShowVerificationModal(false);
            setPendingSubmit(false);
          }}
          email={user.email || ""}
          onVerified={handleVerificationSuccess}
        />
      )}
    </div>
  );
};

export default CreateItem;
