"use client";

import { useEffect, useState, useCallback } from "react";
import { useRouter } from "next/navigation";
import { Permission } from "../auth-context";
import { api } from "../api";
import { sharedStyles } from "../styles/shared";
import { Header } from "../components/Header";
import { useRequireAuth } from "../hooks/useRequireAuth";
import { components } from "../generated/api";
import constants from "../../../shared/constants.json";

const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays, noteMaxLength } = constants.booking;

type BookableSlot = components["schemas"]["BookableSlot"];
type AvailableSlotsResponse = components["schemas"]["AvailableSlotsResponse"];
type AppointmentResponse = components["schemas"]["AppointmentResponse"];

// Helper to format date as YYYY-MM-DD in local timezone
function formatDate(d: Date): string {
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
}

// Helper to format time from ISO string
function formatTime(isoString: string): string {
  const d = new Date(isoString);
  return d.toLocaleTimeString("en-US", { 
    hour: "2-digit", 
    minute: "2-digit",
    hour12: false,
  });
}

// Get date range for booking (tomorrow to +30 days)
function getBookableDates(): Date[] {
  const dates: Date[] = [];
  const today = new Date();
  for (let i = minAdvanceDays; i <= maxAdvanceDays; i++) {
    const d = new Date(today);
    d.setDate(today.getDate() + i);
    dates.push(d);
  }
  return dates;
}

export default function BookingPage() {
  const router = useRouter();
  const { user, isLoading, isAuthorized } = useRequireAuth({
    requiredPermission: Permission.BOOK_APPOINTMENT,
    fallbackRedirect: "/",
  });

  const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const [availableSlots, setAvailableSlots] = useState<BookableSlot[]>([]);
  const [selectedSlot, setSelectedSlot] = useState<BookableSlot | null>(null);
  const [note, setNote] = useState("");
  const [isLoadingSlots, setIsLoadingSlots] = useState(false);
  const [isBooking, setIsBooking] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);

  const dates = getBookableDates();

  const fetchSlots = useCallback(async (date: Date) => {
    setIsLoadingSlots(true);
    setError(null);
    setAvailableSlots([]);
    setSelectedSlot(null);
    
    try {
      const dateStr = formatDate(date);
      const data = await api.get<AvailableSlotsResponse>(`/api/booking/slots?date=${dateStr}`);
      setAvailableSlots(data.slots);
    } catch (err) {
      console.error("Failed to fetch slots:", err);
      setError("Failed to load available slots");
    } finally {
      setIsLoadingSlots(false);
    }
  }, []);

  useEffect(() => {
    if (selectedDate && user && isAuthorized) {
      fetchSlots(selectedDate);
    }
  }, [selectedDate, user, isAuthorized, fetchSlots]);

  const handleDateSelect = (date: Date) => {
    setSelectedDate(date);
    setSuccessMessage(null);
  };

  const handleSlotSelect = (slot: BookableSlot) => {
    setSelectedSlot(slot);
    setNote("");
    setError(null);
  };

  const handleBook = async () => {
    if (!selectedSlot) return;
    
    setIsBooking(true);
    setError(null);
    
    try {
      const appointment = await api.post<AppointmentResponse>("/api/booking", {
        slot_start: selectedSlot.start_time,
        note: note || null,
      });
      
      setSuccessMessage(`Appointment booked for ${formatTime(appointment.slot_start)} - ${formatTime(appointment.slot_end)}`);
      setSelectedSlot(null);
      setNote("");
      
      // Refresh slots to show the booked one is gone
      if (selectedDate) {
        await fetchSlots(selectedDate);
      }
    } catch (err) {
      if (err instanceof Error) {
        setError(err.message);
      } else {
        setError("Failed to book appointment");
      }
    } finally {
      setIsBooking(false);
    }
  };

  const cancelSlotSelection = () => {
    setSelectedSlot(null);
    setNote("");
    setError(null);
  };

  if (isLoading) {
    return (
      <div style={sharedStyles.pageContainer}>
        <Header currentPage="booking" />
        <main style={sharedStyles.mainContent}>
          <p>Loading...</p>
        </main>
      </div>
    );
  }

  if (!isAuthorized) {
    return null;
  }

  return (
    <div style={sharedStyles.pageContainer}>
      <Header currentPage="booking" />
      <main style={sharedStyles.mainContent}>
        <h1 style={{ marginBottom: "0.5rem" }}>Book an Appointment</h1>
        <p style={{ color: "#666", marginBottom: "1.5rem" }}>
          Select a date to see available {slotDurationMinutes}-minute slots
        </p>

        {successMessage && (
          <div style={{
            background: "#d4edda",
            border: "1px solid #c3e6cb",
            color: "#155724",
            padding: "1rem",
            borderRadius: "8px",
            marginBottom: "1rem",
          }}>
            {successMessage}
          </div>
        )}

        {error && (
          <div style={{
            background: "#f8d7da",
            border: "1px solid #f5c6cb",
            color: "#721c24",
            padding: "1rem",
            borderRadius: "8px",
            marginBottom: "1rem",
          }}>
            {error}
          </div>
        )}

        {/* Date Selection */}
        <div style={{ marginBottom: "1.5rem" }}>
          <h2 style={{ fontSize: "1.1rem", marginBottom: "0.75rem" }}>Select a Date</h2>
          <div style={{
            display: "flex",
            flexWrap: "wrap",
            gap: "0.5rem",
          }}>
            {dates.map((date) => {
              const isSelected = selectedDate && formatDate(selectedDate) === formatDate(date);
              return (
                <button
                  key={formatDate(date)}
                  onClick={() => handleDateSelect(date)}
                  style={{
                    padding: "0.5rem 1rem",
                    border: isSelected ? "2px solid #0070f3" : "1px solid #ddd",
                    borderRadius: "8px",
                    background: isSelected ? "#e7f3ff" : "#fff",
                    cursor: "pointer",
                    fontSize: "0.875rem",
                    minWidth: "100px",
                  }}
                >
                  <div style={{ fontWeight: 500 }}>
                    {date.toLocaleDateString("en-US", { weekday: "short" })}
                  </div>
                  <div style={{ color: "#666" }}>
                    {date.toLocaleDateString("en-US", { month: "short", day: "numeric" })}
                  </div>
                </button>
              );
            })}
          </div>
        </div>

        {/* Available Slots */}
        {selectedDate && (
          <div style={{ marginBottom: "1.5rem" }}>
            <h2 style={{ fontSize: "1.1rem", marginBottom: "0.75rem" }}>
              Available Slots for {selectedDate.toLocaleDateString("en-US", { 
                weekday: "long", 
                month: "long", 
                day: "numeric" 
              })}
            </h2>
            
            {isLoadingSlots ? (
              <p>Loading slots...</p>
            ) : availableSlots.length === 0 ? (
              <p style={{ color: "#666" }}>No available slots for this date</p>
            ) : (
              <div style={{
                display: "flex",
                flexWrap: "wrap",
                gap: "0.5rem",
              }}>
                {availableSlots.map((slot) => {
                  const isSelected = selectedSlot?.start_time === slot.start_time;
                  return (
                    <button
                      key={slot.start_time}
                      onClick={() => handleSlotSelect(slot)}
                      style={{
                        padding: "0.5rem 1rem",
                        border: isSelected ? "2px solid #0070f3" : "1px solid #ddd",
                        borderRadius: "8px",
                        background: isSelected ? "#e7f3ff" : "#fff",
                        cursor: "pointer",
                        fontSize: "0.875rem",
                      }}
                    >
                      {formatTime(slot.start_time)}
                    </button>
                  );
                })}
              </div>
            )}
          </div>
        )}

        {/* Booking Form */}
        {selectedSlot && (
          <div style={{
            background: "#f9f9f9",
            border: "1px solid #ddd",
            borderRadius: "8px",
            padding: "1.5rem",
            maxWidth: "400px",
          }}>
            <h3 style={{ marginBottom: "1rem" }}>
              Confirm Booking
            </h3>
            <p style={{ marginBottom: "1rem" }}>
              <strong>Time:</strong> {formatTime(selectedSlot.start_time)} - {formatTime(selectedSlot.end_time)}
            </p>
            
            <div style={{ marginBottom: "1rem" }}>
              <label style={{ display: "block", marginBottom: "0.5rem", fontWeight: 500 }}>
                Note (optional, max {noteMaxLength} chars)
              </label>
              <textarea
                value={note}
                onChange={(e) => setNote(e.target.value.slice(0, noteMaxLength))}
                placeholder="Add a note about your appointment..."
                style={{
                  width: "100%",
                  padding: "0.5rem",
                  border: "1px solid #ddd",
                  borderRadius: "4px",
                  minHeight: "80px",
                  resize: "vertical",
                  fontFamily: "inherit",
                }}
              />
              <div style={{ 
                fontSize: "0.75rem", 
                color: note.length >= noteMaxLength ? "#dc3545" : "#666",
                textAlign: "right",
              }}>
                {note.length}/{noteMaxLength}
              </div>
            </div>
            
            <div style={{ display: "flex", gap: "0.5rem" }}>
              <button
                onClick={handleBook}
                disabled={isBooking}
                style={{
                  flex: 1,
                  padding: "0.75rem",
                  background: isBooking ? "#ccc" : "#0070f3",
                  color: "#fff",
                  border: "none",
                  borderRadius: "4px",
                  cursor: isBooking ? "not-allowed" : "pointer",
                  fontWeight: 500,
                }}
              >
                {isBooking ? "Booking..." : "Book Appointment"}
              </button>
              <button
                onClick={cancelSlotSelection}
                disabled={isBooking}
                style={{
                  padding: "0.75rem 1rem",
                  background: "#fff",
                  border: "1px solid #ddd",
                  borderRadius: "4px",
                  cursor: "pointer",
                }}
              >
                Cancel
              </button>
            </div>
          </div>
        )}
      </main>
    </div>
  );
}

