"use client";

import { useEffect, useState, useCallback } from "react";
import { Permission } from "../../auth-context";
import { adminApi } from "../../api";
import { Header } from "../../components/Header";
import { useRequireAuth } from "../../hooks/useRequireAuth";
import { components } from "../../generated/api";
import constants from "../../../../shared/constants.json";
import {
  formatDate,
  formatDisplayDate,
  getDateRange,
  formatTimeString,
  isWeekend,
} from "../../utils/date";
import {
  layoutStyles,
  typographyStyles,
  bannerStyles,
  buttonStyles,
  modalStyles,
} from "../../styles/shared";

const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays } = constants.exchange;

type _AvailabilityDay = components["schemas"]["AvailabilityDay"];
type TimeSlot = components["schemas"]["TimeSlot"];

// Generate time options for dropdowns (15-min intervals)
// Moved outside component since slotDurationMinutes is a constant
function generateTimeOptions(slotDurationMinutes: number): string[] {
  const options: string[] = [];
  for (let h = 0; h < 24; h++) {
    for (let m = 0; m < 60; m += slotDurationMinutes) {
      const hh = h.toString().padStart(2, "0");
      const mm = m.toString().padStart(2, "0");
      options.push(`${hh}:${mm}`);
    }
  }
  return options;
}

const TIME_OPTIONS = generateTimeOptions(slotDurationMinutes);

interface EditSlot {
  start_time: string;
  end_time: string;
}

export default function AdminAvailabilityPage() {
  const { user, isLoading, isAuthorized } = useRequireAuth({
    requiredPermission: Permission.MANAGE_AVAILABILITY,
    fallbackRedirect: "/",
  });

  const [availability, setAvailability] = useState<Map<string, TimeSlot[]>>(new Map());
  const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const [editSlots, setEditSlots] = useState<EditSlot[]>([]);
  const [isSaving, setIsSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [copySource, setCopySource] = useState<string | null>(null);
  const [copyTargets, setCopyTargets] = useState<Set<string>>(new Set());
  const [isCopying, setIsCopying] = useState(false);

  const dates = getDateRange(minAdvanceDays, maxAdvanceDays);

  const fetchAvailability = useCallback(async () => {
    const dateRange = getDateRange(minAdvanceDays, maxAdvanceDays);
    if (!dateRange.length) return;

    try {
      const fromDate = formatDate(dateRange[0]);
      const toDate = formatDate(dateRange[dateRange.length - 1]);
      const data = await adminApi.getAvailability(fromDate, toDate);

      const map = new Map<string, TimeSlot[]>();
      for (const day of data.days) {
        map.set(day.date, day.slots);
      }
      setAvailability(map);
    } catch (err) {
      console.error("Failed to fetch availability:", err);
    }
  }, []);

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

  const openEditModal = (date: Date) => {
    const dateStr = formatDate(date);
    const existingSlots = availability.get(dateStr) || [];
    setEditSlots(
      existingSlots.length > 0
        ? existingSlots.map((s) => ({
            start_time: formatTimeString(s.start_time),
            end_time: formatTimeString(s.end_time),
          }))
        : [{ start_time: "09:00", end_time: "17:00" }]
    );
    setSelectedDate(date);
    setError(null);
  };

  const closeModal = () => {
    setSelectedDate(null);
    setEditSlots([]);
    setError(null);
  };

  const addSlot = () => {
    setEditSlots([...editSlots, { start_time: "09:00", end_time: "17:00" }]);
  };

  const removeSlot = (index: number) => {
    setEditSlots(editSlots.filter((_, i) => i !== index));
  };

  const updateSlot = (index: number, field: "start_time" | "end_time", value: string) => {
    const updated = [...editSlots];
    updated[index][field] = value;
    setEditSlots(updated);
  };

  const saveAvailability = async () => {
    if (!selectedDate) return;

    setIsSaving(true);
    setError(null);

    try {
      const slots = editSlots.map((s) => ({
        start_time: s.start_time + ":00",
        end_time: s.end_time + ":00",
      }));

      await adminApi.updateAvailability({
        date: formatDate(selectedDate),
        slots,
      });

      await fetchAvailability();
      closeModal();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to save");
    } finally {
      setIsSaving(false);
    }
  };

  const clearAvailability = async () => {
    if (!selectedDate) return;

    setIsSaving(true);
    setError(null);

    try {
      await adminApi.updateAvailability({
        date: formatDate(selectedDate),
        slots: [],
      });

      await fetchAvailability();
      closeModal();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to clear");
    } finally {
      setIsSaving(false);
    }
  };

  const startCopyMode = (dateStr: string) => {
    setCopySource(dateStr);
    setCopyTargets(new Set());
  };

  const cancelCopyMode = () => {
    setCopySource(null);
    setCopyTargets(new Set());
  };

  const toggleCopyTarget = (dateStr: string) => {
    if (dateStr === copySource) return;
    const newTargets = new Set(copyTargets);
    if (newTargets.has(dateStr)) {
      newTargets.delete(dateStr);
    } else {
      newTargets.add(dateStr);
    }
    setCopyTargets(newTargets);
  };

  const executeCopy = async () => {
    if (!copySource || copyTargets.size === 0) return;

    setIsCopying(true);
    setError(null);

    try {
      await adminApi.copyAvailability({
        source_date: copySource,
        target_dates: Array.from(copyTargets),
      });

      await fetchAvailability();
      cancelCopyMode();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to copy");
    } finally {
      setIsCopying(false);
    }
  };

  const formatSlotTime = (slot: TimeSlot): string => {
    return `${formatTimeString(slot.start_time)} - ${formatTimeString(slot.end_time)}`;
  };

  if (isLoading) {
    return (
      <main style={layoutStyles.main}>
        <div style={layoutStyles.loader}>Loading...</div>
      </main>
    );
  }

  if (!user || !isAuthorized) {
    return null;
  }

  return (
    <main style={layoutStyles.main}>
      <Header currentPage="admin-availability" />

      <div style={layoutStyles.contentScrollable}>
        <div style={styles.pageContainer}>
          <div style={styles.headerRow}>
            <div>
              <h1 style={typographyStyles.pageTitle}>Availability</h1>
              <p style={typographyStyles.pageSubtitle}>
                Configure your available time slots for the next {maxAdvanceDays} days
              </p>
            </div>
            {copySource && (
              <div style={styles.copyActions}>
                <span style={styles.copyHint}>Select days to copy to, then click Copy</span>
                <button
                  onClick={executeCopy}
                  disabled={copyTargets.size === 0 || isCopying}
                  style={buttonStyles.accentButton}
                >
                  {isCopying ? "Copying..." : `Copy to ${copyTargets.size} day(s)`}
                </button>
                <button onClick={cancelCopyMode} style={buttonStyles.secondaryButton}>
                  Cancel
                </button>
              </div>
            )}
          </div>

          {error && !selectedDate && <div style={bannerStyles.errorBanner}>{error}</div>}

          <div style={styles.calendar}>
            {dates.map((date) => {
              const dateStr = formatDate(date);
              const slots = availability.get(dateStr) || [];
              const hasSlots = slots.length > 0;
              const isSource = copySource === dateStr;
              const isTarget = copyTargets.has(dateStr);
              const isWeekendDate = isWeekend(date);

              return (
                <div
                  key={dateStr}
                  data-testid={`day-card-${dateStr}`}
                  style={{
                    ...styles.dayCard,
                    ...(hasSlots ? styles.dayCardActive : {}),
                    ...(isSource ? styles.dayCardSource : {}),
                    ...(isTarget ? styles.dayCardTarget : {}),
                    ...(isWeekendDate ? styles.dayCardWeekend : {}),
                  }}
                  onClick={() => {
                    if (copySource) {
                      toggleCopyTarget(dateStr);
                    } else {
                      openEditModal(date);
                    }
                  }}
                >
                  <div style={styles.dayHeader}>
                    <span style={styles.dayName}>{formatDisplayDate(date)}</span>
                    {hasSlots && !copySource && (
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          startCopyMode(dateStr);
                        }}
                        style={styles.copyFromButton}
                        title="Copy to other days"
                      >
                        📋
                      </button>
                    )}
                  </div>
                  <div style={styles.slotList}>
                    {slots.length === 0 ? (
                      <span style={styles.noSlots}>No availability</span>
                    ) : (
                      slots.map((slot, i) => (
                        <span key={i} style={styles.slotBadge}>
                          {formatSlotTime(slot)}
                        </span>
                      ))
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* Edit Modal */}
      {selectedDate && (
        <div style={modalStyles.modalOverlay} onClick={closeModal}>
          <div style={modalStyles.modal} onClick={(e) => e.stopPropagation()}>
            <h2 style={modalStyles.modalTitle}>
              Edit Availability - {formatDisplayDate(selectedDate)}
            </h2>

            {error && <div style={modalStyles.modalError}>{error}</div>}

            <div style={styles.slotsEditor}>
              {editSlots.map((slot, index) => (
                <div key={index} style={styles.slotRow}>
                  <select
                    value={slot.start_time}
                    onChange={(e) => updateSlot(index, "start_time", e.target.value)}
                    style={styles.timeSelect}
                  >
                    {TIME_OPTIONS.map((t) => (
                      <option key={t} value={t}>
                        {t}
                      </option>
                    ))}
                  </select>
                  <span style={styles.slotDash}>→</span>
                  <select
                    value={slot.end_time}
                    onChange={(e) => updateSlot(index, "end_time", e.target.value)}
                    style={styles.timeSelect}
                  >
                    {TIME_OPTIONS.map((t) => (
                      <option key={t} value={t}>
                        {t}
                      </option>
                    ))}
                  </select>
                  <button
                    onClick={() => removeSlot(index)}
                    style={styles.removeSlotButton}
                    title="Remove slot"
                  >
                    ×
                  </button>
                </div>
              ))}
              <button onClick={addSlot} style={styles.addSlotButton}>
                + Add Time Range
              </button>
            </div>

            <div style={modalStyles.modalActions}>
              <button onClick={clearAvailability} disabled={isSaving} style={styles.clearButton}>
                Clear All
              </button>
              <div style={modalStyles.modalActionsRight}>
                <button onClick={closeModal} style={buttonStyles.secondaryButton}>
                  Cancel
                </button>
                <button
                  onClick={saveAvailability}
                  disabled={isSaving}
                  style={buttonStyles.accentButton}
                >
                  {isSaving ? "Saving..." : "Save"}
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </main>
  );
}

// Page-specific styles
const styles: Record<string, React.CSSProperties> = {
  pageContainer: {
    maxWidth: "1200px",
    margin: "0 auto",
  },
  headerRow: {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "flex-start",
    marginBottom: "2rem",
    flexWrap: "wrap",
    gap: "1rem",
  },
  copyActions: {
    display: "flex",
    alignItems: "center",
    gap: "1rem",
  },
  copyHint: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "0.85rem",
    color: "rgba(255, 255, 255, 0.6)",
  },
  calendar: {
    display: "grid",
    gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))",
    gap: "1rem",
  },
  dayCard: {
    background: "rgba(255, 255, 255, 0.03)",
    border: "1px solid rgba(255, 255, 255, 0.08)",
    borderRadius: "12px",
    padding: "1rem",
    cursor: "pointer",
    transition: "all 0.2s",
  },
  dayCardActive: {
    background: "rgba(99, 102, 241, 0.1)",
    border: "1px solid rgba(99, 102, 241, 0.3)",
  },
  dayCardSource: {
    background: "rgba(34, 197, 94, 0.15)",
    border: "1px solid rgba(34, 197, 94, 0.5)",
  },
  dayCardTarget: {
    background: "rgba(99, 102, 241, 0.2)",
    border: "1px solid rgba(99, 102, 241, 0.6)",
  },
  dayCardWeekend: {
    opacity: 0.7,
  },
  dayHeader: {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    marginBottom: "0.5rem",
  },
  dayName: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "0.85rem",
    fontWeight: 600,
    color: "rgba(255, 255, 255, 0.9)",
  },
  copyFromButton: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "1rem",
    padding: "0.25rem 0.5rem",
    background: "transparent",
    color: "rgba(255, 255, 255, 0.5)",
    border: "none",
    cursor: "pointer",
  },
  slotList: {
    display: "flex",
    flexDirection: "column",
    gap: "0.25rem",
  },
  noSlots: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "0.75rem",
    color: "rgba(255, 255, 255, 0.3)",
  },
  slotBadge: {
    fontFamily: "'DM Mono', monospace",
    fontSize: "0.7rem",
    padding: "0.2rem 0.4rem",
    background: "rgba(99, 102, 241, 0.2)",
    borderRadius: "4px",
    color: "rgba(129, 140, 248, 0.9)",
  },
  slotsEditor: {
    display: "flex",
    flexDirection: "column",
    gap: "0.75rem",
    marginBottom: "1.5rem",
  },
  slotRow: {
    display: "flex",
    alignItems: "center",
    gap: "0.5rem",
  },
  timeSelect: {
    fontFamily: "'DM Mono', monospace",
    fontSize: "0.9rem",
    padding: "0.5rem",
    background: "rgba(255, 255, 255, 0.05)",
    border: "1px solid rgba(255, 255, 255, 0.1)",
    borderRadius: "6px",
    color: "#fff",
    cursor: "pointer",
    flex: 1,
  },
  slotDash: {
    color: "rgba(255, 255, 255, 0.4)",
  },
  removeSlotButton: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "1.2rem",
    width: "32px",
    height: "32px",
    background: "rgba(239, 68, 68, 0.15)",
    color: "rgba(239, 68, 68, 0.9)",
    border: "1px solid rgba(239, 68, 68, 0.3)",
    borderRadius: "6px",
    cursor: "pointer",
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
  },
  addSlotButton: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "0.85rem",
    padding: "0.5rem",
    background: "transparent",
    color: "rgba(99, 102, 241, 0.9)",
    border: "1px dashed rgba(99, 102, 241, 0.4)",
    borderRadius: "6px",
    cursor: "pointer",
  },
  clearButton: {
    fontFamily: "'DM Sans', system-ui, sans-serif",
    fontSize: "0.85rem",
    padding: "0.6rem 1rem",
    background: "rgba(239, 68, 68, 0.15)",
    color: "rgba(239, 68, 68, 0.9)",
    border: "1px solid rgba(239, 68, 68, 0.3)",
    borderRadius: "8px",
    cursor: "pointer",
  },
};
