import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import type { ClockStyle } from "@workspace/api-client-react";
import {
  formatTime,
  formatDate,
  formatHijri,
  formatWeekday,
} from "@/lib/i18n-format";

export const CLOCK_STYLES: ClockStyle[] = [
  "full",
  "digital",
  "digital-no-seconds",
  "analog",
  "minimal",
];

export const DEFAULT_CLOCK_STYLE: ClockStyle = "full";

export function resolveClockStyle(value: ClockStyle | null | undefined): ClockStyle {
  if (!value) return DEFAULT_CLOCK_STYLE;
  return CLOCK_STYLES.includes(value) ? value : DEFAULT_CLOCK_STYLE;
}

export function useNow(intervalMs = 1000): Date {
  const [now, setNow] = useState<Date>(() => new Date());
  useEffect(() => {
    const t = setInterval(() => setNow(new Date()), intervalMs);
    return () => clearInterval(t);
  }, [intervalMs]);
  return now;
}

type ClockProps = {
  style: ClockStyle | null | undefined;
  time: Date;
  lang: string;
  hour12?: boolean | null;
  size?: "sm" | "md";
};

export const DEFAULT_CLOCK_HOUR12 = false;

export function resolveClockHour12(value: boolean | null | undefined): boolean {
  return value ?? DEFAULT_CLOCK_HOUR12;
}

function AnalogClock({ time, size = "md" }: { time: Date; size?: "sm" | "md" }) {
  const hours = time.getHours() % 12;
  const minutes = time.getMinutes();
  const seconds = time.getSeconds();

  const hourAngle = (hours + minutes / 60) * 30;
  const minuteAngle = (minutes + seconds / 60) * 6;
  const secondAngle = seconds * 6;

  const px = size === "sm" ? 38 : 52;
  const center = px / 2;

  const ticks = Array.from({ length: 12 }, (_, i) => {
    const angle = (i * 30 * Math.PI) / 180;
    const outer = center - 2;
    const inner = center - (i % 3 === 0 ? 6 : 4);
    const x1 = center + Math.sin(angle) * inner;
    const y1 = center - Math.cos(angle) * inner;
    const x2 = center + Math.sin(angle) * outer;
    const y2 = center - Math.cos(angle) * outer;
    return (
      <line
        key={i}
        x1={x1}
        y1={y1}
        x2={x2}
        y2={y2}
        stroke="currentColor"
        strokeWidth={i % 3 === 0 ? 1.5 : 1}
        strokeLinecap="round"
        opacity={i % 3 === 0 ? 0.85 : 0.45}
      />
    );
  });

  const hand = (angle: number, length: number, width: number, color: string, opacity = 1) => {
    const rad = (angle * Math.PI) / 180;
    const x = center + Math.sin(rad) * length;
    const y = center - Math.cos(rad) * length;
    return (
      <line
        x1={center}
        y1={center}
        x2={x}
        y2={y}
        stroke={color}
        strokeWidth={width}
        strokeLinecap="round"
        opacity={opacity}
      />
    );
  };

  return (
    <svg
      width={px}
      height={px}
      viewBox={`0 0 ${px} ${px}`}
      className="text-foreground shrink-0"
      role="img"
      aria-label="Analog clock"
    >
      <circle
        cx={center}
        cy={center}
        r={center - 1}
        fill="none"
        stroke="currentColor"
        strokeWidth={1}
        opacity={0.25}
      />
      {ticks}
      {hand(hourAngle, center - 14, 2.2, "currentColor", 0.95)}
      {hand(minuteAngle, center - 8, 1.6, "currentColor", 0.85)}
      {hand(secondAngle, center - 6, 1, "hsl(var(--primary))", 0.95)}
      <circle cx={center} cy={center} r={1.6} fill="currentColor" />
    </svg>
  );
}

/**
 * Classic analog clock widget for the home screen. Latin digits 1-12,
 * 60 minute ticks, double-ring frame, sweeping seconds hand. Uses
 * currentColor so it inherits the foreground color and works in any
 * theme. The `size` prop controls overall pixel diameter.
 */
export function AnalogClockWidget({
  time,
  lang,
  hour12,
  className,
  size = 240,
  showLabels = true,
}: {
  time: Date;
  lang: string;
  hour12?: boolean | null;
  className?: string;
  size?: number;
  showLabels?: boolean;
}) {
  const use12 = resolveClockHour12(hour12);
  const hours = time.getHours() % 12;
  const minutes = time.getMinutes();
  const seconds = time.getSeconds();

  const hourAngle = (hours + minutes / 60) * 30;
  const minuteAngle = (minutes + seconds / 60) * 6;
  const secondAngle = seconds * 6;

  const cx = size / 2;
  const cy = size / 2;
  const r = cx - 4;
  const scale = size / 240;

  const DIGITS = [
    "12",
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
    "10",
    "11",
  ];

  const numeralOffset = Math.max(10, 18 * scale);
  const numeralFont = Math.max(8, 14 * scale);
  const numerals = DIGITS.map((digit, i) => {
    const angle = ((i * 30 - 90) * Math.PI) / 180;
    const numR = r - numeralOffset;
    const x = cx + Math.cos(angle) * numR;
    const y = cy + Math.sin(angle) * numR;
    return (
      <text
        key={i}
        x={x}
        y={y}
        textAnchor="middle"
        dominantBaseline="central"
        fontSize={numeralFont}
        fontFamily="ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif"
        fontWeight="700"
        fill="currentColor"
        opacity={0.9}
      >
        {digit}
      </text>
    );
  });

  const ticks = Array.from({ length: 60 }, (_, i) => {
    const angle = (i * 6 * Math.PI) / 180;
    const isHour = i % 5 === 0;
    const outer = r - 2 * scale;
    const inner = isHour ? r - 8 * scale : r - 5 * scale;
    const x1 = cx + Math.sin(angle) * inner;
    const y1 = cy - Math.cos(angle) * inner;
    const x2 = cx + Math.sin(angle) * outer;
    const y2 = cy - Math.cos(angle) * outer;
    return (
      <line
        key={i}
        x1={x1}
        y1={y1}
        x2={x2}
        y2={y2}
        stroke="currentColor"
        strokeWidth={isHour ? 1.8 : 0.7}
        strokeLinecap="round"
        opacity={isHour ? 0.85 : 0.35}
      />
    );
  });

  const hand = (
    angle: number,
    length: number,
    width: number,
    color: string,
    opacity = 1,
    tailLength = 0,
  ) => {
    const rad = (angle * Math.PI) / 180;
    const x = cx + Math.sin(rad) * length;
    const y = cy - Math.cos(rad) * length;
    const tx = cx - Math.sin(rad) * tailLength;
    const ty = cy + Math.cos(rad) * tailLength;
    return (
      <line
        x1={tx}
        y1={ty}
        x2={x}
        y2={y}
        stroke={color}
        strokeWidth={width}
        strokeLinecap="round"
        opacity={opacity}
      />
    );
  };

  return (
    <div
      className={`flex flex-col items-center gap-3 ${className ?? ""}`}
      dir="ltr"
    >
      <div className="relative drop-shadow-sm">
        <svg
          width={size}
          height={size}
          viewBox={`0 0 ${size} ${size}`}
          className="text-foreground"
          role="img"
          aria-label="Analog clock"
        >
          <defs>
            <radialGradient id="tbo-clock-face" cx="50%" cy="38%" r="65%">
              <stop offset="0%" stopColor="white" stopOpacity="0.95" />
              <stop offset="100%" stopColor="white" stopOpacity="0.55" />
            </radialGradient>
            <radialGradient id="tbo-clock-bezel" cx="50%" cy="50%" r="50%">
              <stop offset="85%" stopColor="currentColor" stopOpacity="0" />
              <stop offset="100%" stopColor="currentColor" stopOpacity="0.2" />
            </radialGradient>
          </defs>
          {/* Outer bezel ring */}
          <circle
            cx={cx}
            cy={cy}
            r={r + 6}
            fill="none"
            stroke="currentColor"
            strokeWidth={1.2}
            opacity={0.25}
          />
          {/* Face */}
          <circle
            cx={cx}
            cy={cy}
            r={r + 2}
            fill="url(#tbo-clock-face)"
            stroke="currentColor"
            strokeWidth={1}
            opacity={0.9}
          />
          <circle cx={cx} cy={cy} r={r + 2} fill="url(#tbo-clock-bezel)" />
          {/* Inner ring */}
          <circle
            cx={cx}
            cy={cy}
            r={r - 14}
            fill="none"
            stroke="currentColor"
            strokeWidth={0.5}
            opacity={0.18}
          />
          {ticks}
          {numerals}
          {/* Hour hand */}
          {hand(hourAngle, r - 50 * scale, 4.5 * scale, "currentColor", 0.95, 8 * scale)}
          {/* Minute hand */}
          {hand(minuteAngle, r - 22 * scale, 3 * scale, "currentColor", 0.85, 10 * scale)}
          {/* Second hand */}
          {hand(secondAngle, r - 14 * scale, 1.2 * scale, "hsl(var(--primary))", 1, 18 * scale)}
          {/* Center pin */}
          <circle cx={cx} cy={cy} r={4 * scale} fill="currentColor" />
          <circle cx={cx} cy={cy} r={1.5 * scale} fill="hsl(var(--primary))" />
        </svg>
      </div>
      {showLabels && (
        <div className="text-center">
          <div className="font-mono text-sm font-semibold tabular-nums text-foreground tracking-tight">
            {formatTime(time, lang, {
              hour: "2-digit",
              minute: "2-digit",
              second: "2-digit",
              hour12: use12,
            })}
          </div>
          <div className="text-[10px] text-muted-foreground mt-0.5 tabular-nums">
            {formatWeekday(time, lang)} · {formatDate(time, lang)}
          </div>
        </div>
      )}
    </div>
  );
}

const HOME_CLOCK_STORAGE_KEY = "tx:home-clock-visible";
const HOME_CLOCK_EVENT = "tx:home-clock-changed";

function readHomeClockVisible(): boolean {
  if (typeof window === "undefined") return true;
  try {
    const v = window.localStorage.getItem(HOME_CLOCK_STORAGE_KEY);
    return v === null ? true : v === "1";
  } catch {
    return true;
  }
}

/**
 * Small hook to read & persist whether the big home-screen analog
 * clock widget is visible. Persists in localStorage and broadcasts
 * a custom event so multiple consumers stay in sync within the same
 * tab (storage events only fire across tabs).
 */
export function useHomeClockVisibility(): [boolean, (next: boolean) => void] {
  const [visible, setVisibleState] = useState<boolean>(readHomeClockVisible);

  useEffect(() => {
    const onChange = () => setVisibleState(readHomeClockVisible());
    window.addEventListener(HOME_CLOCK_EVENT, onChange);
    window.addEventListener("storage", onChange);
    return () => {
      window.removeEventListener(HOME_CLOCK_EVENT, onChange);
      window.removeEventListener("storage", onChange);
    };
  }, []);

  const setVisible = (next: boolean) => {
    try {
      window.localStorage.setItem(HOME_CLOCK_STORAGE_KEY, next ? "1" : "0");
    } catch {
      /* ignore */
    }
    setVisibleState(next);
    window.dispatchEvent(new Event(HOME_CLOCK_EVENT));
  };

  return [visible, setVisible];
}

const TOPBAR_CLOCK_STORAGE_KEY = "tx:topbar-clock-visible";
const TOPBAR_CLOCK_EVENT = "tx:topbar-clock-changed";

function readTopbarClockVisible(): boolean {
  if (typeof window === "undefined") return true;
  try {
    const v = window.localStorage.getItem(TOPBAR_CLOCK_STORAGE_KEY);
    return v === null ? true : v === "1";
  } catch {
    return true;
  }
}

/**
 * Visibility for the small clock displayed in the home page top bar.
 * Independent of useHomeClockVisibility, which controls the large
 * grid widget on the home screen.
 */
export function useTopbarClockVisibility(): [boolean, (next: boolean) => void] {
  const [visible, setVisibleState] = useState<boolean>(readTopbarClockVisible);

  useEffect(() => {
    const onChange = () => setVisibleState(readTopbarClockVisible());
    window.addEventListener(TOPBAR_CLOCK_EVENT, onChange);
    window.addEventListener("storage", onChange);
    return () => {
      window.removeEventListener(TOPBAR_CLOCK_EVENT, onChange);
      window.removeEventListener("storage", onChange);
    };
  }, []);

  const setVisible = (next: boolean) => {
    try {
      window.localStorage.setItem(TOPBAR_CLOCK_STORAGE_KEY, next ? "1" : "0");
    } catch {
      /* ignore */
    }
    setVisibleState(next);
    window.dispatchEvent(new Event(TOPBAR_CLOCK_EVENT));
  };

  return [visible, setVisible];
}

const HOME_CLOCK_SIZE_EVENT = "tx:home-clock-size-changed";
export type HomeClockSize = "compact" | "large";

function homeClockSizeKey(userId: number | string | null | undefined): string {
  return userId == null
    ? "tx:home-clock-size"
    : `tx:home-clock-size:${userId}`;
}

function readHomeClockSize(userId: number | string | null | undefined): HomeClockSize {
  if (typeof window === "undefined") return "compact";
  try {
    const v = window.localStorage.getItem(homeClockSizeKey(userId));
    return v === "large" ? "large" : "compact";
  } catch {
    return "compact";
  }
}

export function useHomeClockSize(
  userId: number | string | null | undefined,
): [HomeClockSize, (next: HomeClockSize) => void] {
  const [size, setSizeState] = useState<HomeClockSize>(() => readHomeClockSize(userId));
  useEffect(() => {
    setSizeState(readHomeClockSize(userId));
    const onChange = () => setSizeState(readHomeClockSize(userId));
    window.addEventListener(HOME_CLOCK_SIZE_EVENT, onChange);
    window.addEventListener("storage", onChange);
    return () => {
      window.removeEventListener(HOME_CLOCK_SIZE_EVENT, onChange);
      window.removeEventListener("storage", onChange);
    };
  }, [userId]);
  const setSize = (next: HomeClockSize) => {
    try {
      window.localStorage.setItem(homeClockSizeKey(userId), next);
    } catch {
      /* ignore */
    }
    setSizeState(next);
    window.dispatchEvent(new Event(HOME_CLOCK_SIZE_EVENT));
  };
  return [size, setSize];
}

const HOME_CLOCK_POS_EVENT = "tx:home-clock-pos-changed";

function homeClockPosKey(userId: number | string | null | undefined): string {
  return userId == null
    ? "tx:home-clock-position"
    : `tx:home-clock-position:${userId}`;
}

function readHomeClockPosition(userId: number | string | null | undefined): number {
  if (typeof window === "undefined") return -1;
  try {
    const v = window.localStorage.getItem(homeClockPosKey(userId));
    if (v === null) return -1;
    const n = Number(v);
    return Number.isFinite(n) && n >= 0 ? Math.floor(n) : -1;
  } catch {
    return -1;
  }
}

export function useHomeClockPosition(
  userId: number | string | null | undefined,
): [number, (next: number) => void] {
  const [pos, setPosState] = useState<number>(() => readHomeClockPosition(userId));
  useEffect(() => {
    setPosState(readHomeClockPosition(userId));
    const onChange = () => setPosState(readHomeClockPosition(userId));
    window.addEventListener(HOME_CLOCK_POS_EVENT, onChange);
    window.addEventListener("storage", onChange);
    return () => {
      window.removeEventListener(HOME_CLOCK_POS_EVENT, onChange);
      window.removeEventListener("storage", onChange);
    };
  }, [userId]);
  const setPos = (next: number) => {
    try {
      window.localStorage.setItem(homeClockPosKey(userId), String(next));
    } catch {
      /* ignore */
    }
    setPosState(next);
    window.dispatchEvent(new Event(HOME_CLOCK_POS_EVENT));
  };
  return [pos, setPos];
}

export function Clock({ style, time, lang, hour12, size = "md" }: ClockProps) {
  const resolved = resolveClockStyle(style);
  const use12 = resolveClockHour12(hour12);
  const dayName = formatWeekday(time, lang);
  const hijriDate = formatHijri(time, lang);
  const gregorianDate = formatDate(time, lang);
  const timeNoSec = formatTime(time, lang, {
    hour: "2-digit",
    minute: "2-digit",
    hour12: use12,
  });
  const timeWithSec = formatTime(time, lang, {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
    hour12: use12,
  });

  const timeFontClass =
    size === "sm"
      ? "font-mono text-sm font-bold tabular-nums tracking-tight"
      : "font-mono text-base sm:text-lg font-bold tabular-nums tracking-tight";

  if (resolved === "analog") {
    return (
      <div className="flex items-center gap-2 text-foreground leading-tight min-w-0">
        <AnalogClock time={time} size={size} />
        <div className="flex flex-col items-start min-w-0">
          <div className={timeFontClass}>{timeNoSec}</div>
          <div className="text-[10px] text-muted-foreground truncate max-w-[40vw]">
            {dayName}
          </div>
        </div>
      </div>
    );
  }

  if (resolved === "minimal") {
    return (
      <div className="flex flex-col items-center text-foreground leading-tight min-w-0">
        <div className={timeFontClass}>{timeNoSec}</div>
      </div>
    );
  }

  if (resolved === "digital-no-seconds") {
    return (
      <div className="flex flex-col items-center text-foreground leading-tight min-w-0">
        <div className={timeFontClass}>{timeNoSec}</div>
        <div className="text-[10px] text-muted-foreground/80 max-w-[60vw] truncate tabular-nums">
          {gregorianDate}
        </div>
      </div>
    );
  }

  if (resolved === "digital") {
    return (
      <div className="flex flex-col items-center text-foreground leading-tight min-w-0">
        <div className={timeFontClass}>{timeWithSec}</div>
        <div className="text-[10px] text-muted-foreground/80 max-w-[60vw] truncate tabular-nums">
          {gregorianDate}
        </div>
      </div>
    );
  }

  // full (default)
  return (
    <div className="flex flex-col items-center text-foreground leading-tight min-w-0">
      <div className={timeFontClass}>{timeNoSec}</div>
      <div className="text-[10px] text-muted-foreground flex items-center gap-1 mt-0.5 max-w-[60vw] truncate">
        <span className="truncate">{dayName}</span>
        <span aria-hidden="true">·</span>
        <span className="truncate tabular-nums">{hijriDate}</span>
      </div>
      <div className="text-[10px] text-muted-foreground/80 max-w-[60vw] truncate tabular-nums">
        {gregorianDate}
      </div>
    </div>
  );
}
