import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useQueryClient } from "@tanstack/react-query";
import {
  useUpdateLanguage,
  useUpdateClockStyle,
  useUpdateClockHour12,
  getGetMeQueryKey,
  type AuthUser,
  type ClockStyle as ClockStyleType,
  type NotificationSoundId,
} from "@workspace/api-client-react";
import {
  Settings as SettingsIcon,
  BellOff,
  Volume2,
  VolumeX,
  Check,
  Eye,
  EyeOff,
  Play,
} from "lucide-react";
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet";
import {
  Clock,
  CLOCK_STYLES,
  resolveClockStyle,
  resolveClockHour12,
  useNow,
  useHomeClockVisibility,
  useTopbarClockVisibility,
} from "@/components/clock";
import {
  ALL_SOUND_IDS,
  notificationPlayer,
} from "@/lib/notification-sounds";
import { useAuth } from "@/contexts/AuthContext";
import { useUpdatePrefs } from "@/components/notification-settings";
import i18n from "@/i18n";

type Slot = "order" | "meeting" | "note";

const SLOT_KEYS: Record<
  Slot,
  {
    enabledKey: keyof Pick<
      AuthUser,
      "notifyOrdersEnabled" | "notifyMeetingsEnabled" | "notifyNotesEnabled"
    >;
    soundKey: keyof Pick<
      AuthUser,
      "notificationSoundOrder" | "notificationSoundMeeting" | "notificationSoundNote"
    >;
    vibrateKey: keyof Pick<
      AuthUser,
      "vibrationEnabledOrder" | "vibrationEnabledMeeting" | "vibrationEnabledNote"
    >;
    enabledLabel: string;
    vibrateLabel: string;
  }
> = {
  order: {
    enabledKey: "notifyOrdersEnabled",
    soundKey: "notificationSoundOrder",
    vibrateKey: "vibrationEnabledOrder",
    enabledLabel: "notifSettings.ordersEnabled",
    vibrateLabel: "notifSettings.vibrationOrder",
  },
  meeting: {
    enabledKey: "notifyMeetingsEnabled",
    soundKey: "notificationSoundMeeting",
    vibrateKey: "vibrationEnabledMeeting",
    enabledLabel: "notifSettings.meetingsEnabled",
    vibrateLabel: "notifSettings.vibrationMeeting",
  },
  note: {
    enabledKey: "notifyNotesEnabled",
    soundKey: "notificationSoundNote",
    vibrateKey: "vibrationEnabledNote",
    enabledLabel: "notifSettings.notesEnabled",
    vibrateLabel: "notifSettings.vibrationNote",
  },
};

function ToggleRow({
  active,
  onClick,
  label,
  leftIcon,
}: {
  active: boolean;
  onClick: () => void;
  label: string;
  leftIcon?: React.ReactNode;
}) {
  return (
    <button
      type="button"
      role="switch"
      aria-checked={active}
      aria-label={label}
      onClick={onClick}
      className="w-full flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg text-start hover:bg-foreground/5 transition-colors"
    >
      <div className="flex items-center gap-2 min-w-0">
        {leftIcon}
        <span className="text-sm text-foreground font-medium truncate">{label}</span>
      </div>
      <span
        className={`relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors ${
          active ? "bg-primary" : "bg-foreground/15"
        }`}
        aria-hidden="true"
      >
        <span
          className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${
            active
              ? "translate-x-[18px] rtl:-translate-x-[18px]"
              : "translate-x-0.5 rtl:-translate-x-0.5"
          }`}
        />
      </span>
    </button>
  );
}

function SectionTitle({ children }: { children: React.ReactNode }) {
  return (
    <div className="px-2 pb-1.5 pt-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
      {children}
    </div>
  );
}

function GroupCard({ children }: { children: React.ReactNode }) {
  return (
    <div className="rounded-xl border border-foreground/10 bg-background/40 p-2">
      {children}
    </div>
  );
}

function LanguageGroup() {
  const { t, i18n: i18nInstance } = useTranslation();
  const queryClient = useQueryClient();
  const updateLanguage = useUpdateLanguage();
  const current = i18nInstance.language === "ar" ? "ar" : "en";

  const choose = (next: "ar" | "en") => {
    if (next === current) return;
    i18n.changeLanguage(next);
    updateLanguage.mutate(
      { data: { language: next } },
      {
        onSuccess: () => {
          queryClient.invalidateQueries({ queryKey: getGetMeQueryKey() });
        },
      },
    );
  };

  const options: Array<{ value: "ar" | "en"; label: string }> = [
    { value: "ar", label: t("settingsPanel.lang.ar") },
    { value: "en", label: t("settingsPanel.lang.en") },
  ];

  return (
    <GroupCard>
      <SectionTitle>{t("settingsPanel.section.language")}</SectionTitle>
      <div
        className="grid grid-cols-2 gap-1 mx-1 mb-1 p-1 rounded-lg bg-foreground/5"
        role="radiogroup"
        aria-label={t("settingsPanel.section.language")}
      >
        {options.map((opt) => {
          const isActive = opt.value === current;
          return (
            <button
              key={opt.value}
              type="button"
              role="radio"
              aria-checked={isActive}
              onClick={() => choose(opt.value)}
              data-testid={`settings-lang-${opt.value}`}
              className={`text-sm font-medium px-2 py-1.5 rounded-md transition-colors ${
                isActive
                  ? "bg-background text-foreground shadow-sm"
                  : "text-muted-foreground hover:text-foreground"
              }`}
            >
              {opt.label}
            </button>
          );
        })}
      </div>
    </GroupCard>
  );
}

function SoundList({
  current,
  onPick,
}: {
  current: NotificationSoundId;
  onPick: (id: NotificationSoundId) => void;
}) {
  const { t } = useTranslation();
  return (
    <div className="flex flex-col gap-0.5 max-h-56 overflow-y-auto">
      {ALL_SOUND_IDS.map((id) => {
        const isActive = id === current;
        return (
          <div
            key={id}
            className={`flex items-center justify-between gap-2 px-2 py-1.5 rounded-lg ${
              isActive ? "bg-primary/10" : "hover:bg-foreground/5"
            }`}
          >
            <button
              type="button"
              onClick={() => onPick(id)}
              className="flex-1 flex items-center gap-2 text-start min-w-0"
            >
              {isActive ? (
                <Check size={14} className="text-primary shrink-0" />
              ) : (
                <span className="w-3.5 shrink-0" />
              )}
              <span className="text-sm text-foreground font-medium truncate">
                {t(`notifSettings.sounds.${id}`)}
              </span>
            </button>
            <button
              type="button"
              onClick={() => notificationPlayer.testPlay(id)}
              aria-label={t("notifSettings.preview")}
              className="p-1 rounded hover:bg-foreground/10 text-muted-foreground"
            >
              <Play size={12} />
            </button>
          </div>
        );
      })}
    </div>
  );
}

function NotificationsGroup() {
  const { t } = useTranslation();
  const { user } = useAuth();
  const apply = useUpdatePrefs();
  const [slot, setSlot] = useState<Slot>("order");
  if (!user) return null;
  const cfg = SLOT_KEYS[slot];
  return (
    <GroupCard>
      <SectionTitle>{t("settingsPanel.section.notifications")}</SectionTitle>
      <div
        className="grid grid-cols-3 gap-1 mx-1 mb-1 p-1 rounded-lg bg-foreground/5"
        role="group"
      >
        {(["order", "meeting", "note"] as const).map((s) => {
          const isActive = s === slot;
          return (
            <button
              key={s}
              type="button"
              onClick={() => setSlot(s)}
              aria-pressed={isActive}
              className={`text-xs font-medium px-2 py-1.5 rounded-md transition-colors ${
                isActive
                  ? "bg-background text-foreground shadow-sm"
                  : "text-muted-foreground hover:text-foreground"
              }`}
            >
              {t(`notifSettings.slot.${s}`)}
            </button>
          );
        })}
      </div>
      <ToggleRow
        active={user[cfg.enabledKey]}
        onClick={() =>
          apply({ [cfg.enabledKey]: !user[cfg.enabledKey] } as Record<string, boolean>)
        }
        label={t(cfg.enabledLabel)}
      />
      <ToggleRow
        active={user[cfg.vibrateKey]}
        onClick={() =>
          apply({ [cfg.vibrateKey]: !user[cfg.vibrateKey] } as Record<string, boolean>)
        }
        label={t(cfg.vibrateLabel)}
      />
      <div className="h-px bg-foreground/10 mx-1 my-1" />
      <SoundList
        current={user[cfg.soundKey]}
        onPick={(id) => apply({ [cfg.soundKey]: id } as Record<string, NotificationSoundId>)}
      />
    </GroupCard>
  );
}

function SoundGroup() {
  const { t } = useTranslation();
  const { user } = useAuth();
  const apply = useUpdatePrefs();
  if (!user) return null;
  const muted = user.notificationsMuted;
  return (
    <GroupCard>
      <SectionTitle>{t("settingsPanel.section.sound")}</SectionTitle>
      <ToggleRow
        active={!muted}
        onClick={() => apply({ notificationsMuted: !muted })}
        label={t("settingsPanel.sound.master")}
        leftIcon={
          muted ? (
            <VolumeX size={16} className="text-muted-foreground shrink-0" />
          ) : (
            <Volume2 size={16} className="text-primary shrink-0" />
          )
        }
      />
    </GroupCard>
  );
}

function ClockGroup() {
  const { t, i18n: i18nInstance } = useTranslation();
  const lang = i18nInstance.language;
  const queryClient = useQueryClient();
  const now = useNow();
  const { user } = useAuth();
  const updateClockStyle = useUpdateClockStyle();
  const updateClockHour12 = useUpdateClockHour12();
  const [homeClockVisible, setHomeClockVisible] = useHomeClockVisibility();
  const [topbarClockVisible, setTopbarClockVisible] = useTopbarClockVisibility();

  if (!user) return null;
  const active = resolveClockStyle(user.clockStyle);
  const activeHour12 = resolveClockHour12(user.clockHour12);

  const chooseStyle = (style: ClockStyleType) => {
    const previous = queryClient.getQueryData<AuthUser>(getGetMeQueryKey());
    if (previous) {
      queryClient.setQueryData<AuthUser>(getGetMeQueryKey(), { ...previous, clockStyle: style });
    }
    updateClockStyle.mutate(
      { data: { clockStyle: style } },
      {
        onSuccess: (data) => queryClient.setQueryData(getGetMeQueryKey(), data),
        onError: () => {
          if (previous) queryClient.setQueryData(getGetMeQueryKey(), previous);
          else queryClient.invalidateQueries({ queryKey: getGetMeQueryKey() });
        },
      },
    );
  };

  const chooseHour12 = (next: boolean) => {
    if (next === activeHour12) return;
    const previous = queryClient.getQueryData<AuthUser>(getGetMeQueryKey());
    if (previous) {
      queryClient.setQueryData<AuthUser>(getGetMeQueryKey(), { ...previous, clockHour12: next });
    }
    updateClockHour12.mutate(
      { data: { clockHour12: next } },
      {
        onSuccess: (data) => queryClient.setQueryData(getGetMeQueryKey(), data),
        onError: () => {
          if (previous) queryClient.setQueryData(getGetMeQueryKey(), previous);
          else queryClient.invalidateQueries({ queryKey: getGetMeQueryKey() });
        },
      },
    );
  };

  return (
    <GroupCard>
      <SectionTitle>{t("settingsPanel.section.clock")}</SectionTitle>
      <ToggleRow
        active={homeClockVisible}
        onClick={() => setHomeClockVisible(!homeClockVisible)}
        label={t("home.clockStyle.showWidget")}
        leftIcon={
          homeClockVisible ? (
            <Eye size={16} className="text-primary shrink-0" />
          ) : (
            <EyeOff size={16} className="text-muted-foreground shrink-0" />
          )
        }
      />
      <ToggleRow
        active={topbarClockVisible}
        onClick={() => setTopbarClockVisible(!topbarClockVisible)}
        label={t("home.clockStyle.showTopbar")}
        leftIcon={
          topbarClockVisible ? (
            <Eye size={16} className="text-primary shrink-0" />
          ) : (
            <EyeOff size={16} className="text-muted-foreground shrink-0" />
          )
        }
      />
      <div className="h-px bg-foreground/10 mx-1 my-1" />
      <div className="px-2 py-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
        {t("home.clockStyle.hourFormat.label")}
      </div>
      <div
        className="grid grid-cols-2 gap-1 mx-1 mb-1 p-1 rounded-lg bg-foreground/5"
        role="group"
        aria-label={t("home.clockStyle.hourFormat.label")}
      >
        {([false, true] as const).map((value) => {
          const isActive = value === activeHour12;
          const labelKey = value ? "h12" : "h24";
          return (
            <button
              key={labelKey}
              type="button"
              onClick={() => chooseHour12(value)}
              disabled={updateClockHour12.isPending}
              aria-pressed={isActive}
              className={`text-sm font-medium px-2 py-1.5 rounded-md transition-colors ${
                isActive
                  ? "bg-background text-foreground shadow-sm"
                  : "text-muted-foreground hover:text-foreground"
              }`}
            >
              {t(`home.clockStyle.hourFormat.${labelKey}`)}
            </button>
          );
        })}
      </div>
      <div className="h-px bg-foreground/10 mx-1 my-1" />
      <div className="px-2 py-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
        {t("home.clockStyle.label")}
      </div>
      <div className="flex flex-col gap-1 max-h-56 overflow-y-auto">
        {CLOCK_STYLES.map((style) => {
          const isActive = style === active;
          return (
            <button
              key={style}
              type="button"
              onClick={() => chooseStyle(style)}
              disabled={updateClockStyle.isPending}
              className={`flex items-center justify-between gap-3 px-2 py-2 rounded-lg text-start hover:bg-foreground/5 transition-colors ${
                isActive ? "bg-primary/10" : ""
              }`}
            >
              <div className="flex items-center gap-3 min-w-0 flex-1">
                <div className="shrink-0">
                  <Clock
                    style={style}
                    time={now}
                    lang={lang}
                    hour12={activeHour12}
                    size="sm"
                  />
                </div>
                <div className="text-sm text-foreground font-medium truncate">
                  {t(`home.clockStyle.options.${style}`)}
                </div>
              </div>
              {isActive && <Check size={14} className="text-primary shrink-0" />}
            </button>
          );
        })}
      </div>
    </GroupCard>
  );
}

/**
 * Unified per-user Settings panel (Task #527). Consolidates the four
 * preferences that previously each had their own topbar button:
 *   - Language (was: globe button)
 *   - Notifications: per-category sound + vibration (was: bell #2 popover)
 *   - Sound: master mute toggle (was: volume button)
 *   - Clock: visibility, 12/24h, style (was: clock-style picker button)
 *
 * Renders as a right-side Sheet on every viewport — full-width on
 * phones, capped width on desktop. Keeps the same persistence paths
 * as the original controls (DB columns via the existing hooks +
 * localStorage for clock visibility), so no migration is required.
 */
export function SettingsPanel() {
  const { t } = useTranslation();
  const [open, setOpen] = useState(false);
  const { user } = useAuth();
  if (!user) return null;
  const muted = user.notificationsMuted;
  return (
    <Sheet open={open} onOpenChange={setOpen}>
      <SheetTrigger asChild>
        <button
          type="button"
          aria-label={t("settingsPanel.title")}
          aria-haspopup="dialog"
          data-testid="topbar-settings-button"
          className="text-muted-foreground hover:text-foreground transition-colors p-1.5 md:p-2.5 rounded-lg md:rounded-xl hover:bg-foreground/5 relative"
        >
          <SettingsIcon className="w-[18px] h-[18px] md:w-6 md:h-6" />
          {muted && (
            <BellOff
              aria-hidden="true"
              className="absolute -top-0.5 -right-0.5 w-3 h-3 text-destructive bg-background rounded-full p-px"
            />
          )}
        </button>
      </SheetTrigger>
      <SheetContent
        side="right"
        className="w-full sm:max-w-md p-0 flex flex-col"
        data-testid="settings-panel"
      >
        <SheetHeader className="px-4 pt-4 pb-2 shrink-0 border-b border-foreground/10">
          <SheetTitle className="flex items-center gap-2 text-base">
            <SettingsIcon size={18} />
            {t("settingsPanel.title")}
          </SheetTitle>
        </SheetHeader>
        <div className="flex-1 overflow-y-auto p-3 space-y-3">
          <LanguageGroup />
          <NotificationsGroup />
          <SoundGroup />
          <ClockGroup />
        </div>
      </SheetContent>
    </Sheet>
  );
}
