import { useEffect, useState, type CSSProperties } from "react";

/**
 * Ввод времени суток в строгом 24-часовом формате `ЧЧ:ММ[:СС]` (локальное).
 *
 * Нативные `<input type="time">`/`type="datetime-local"` рендерят время по локали
 * браузера/ОС (часто AM/PM) и не подчиняются атрибуту `lang`, поэтому время вводим
 * обычным текстовым полем с собственной валидацией. Локальный черновик позволяет
 * печатать промежуточные значения; наружу отдаём только корректное `ЧЧ:ММ[:СС]`.
 */
type Time24FieldProps = {
  /** Текущее значение в формате `ЧЧ:ММ` или `ЧЧ:ММ:СС`. */
  value: string;
  /** Показывать и принимать секунды. */
  withSeconds?: boolean;
  /** Вызывается при вводе корректного значения. */
  onChange: (value: string) => void;
  className?: string;
  style?: CSSProperties;
  "aria-label"?: string;
};

const TIME_RE_HM = /^([01]\d|2[0-3]):[0-5]\d$/;
const TIME_RE_HMS = /^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/;

/**
 * Забирает из потока цифр один сегмент времени `00..max` (часы → 23, мин/сек → 59).
 * Если первая цифра заведомо больше старшего разряда (напр. `9` для часов), сразу
 * дополняет нулём (`09`) и переходит к следующему сегменту; двузначное значение
 * сверх максимума зажимается. Возвращает [сегмент, остаток цифр].
 */
function takeSegment(digits: string, max: number): [string, string] {
  if (digits.length === 0) return ["", ""];
  const firstMax = Math.floor(max / 10);
  if (Number(digits[0]) > firstMax) {
    return [`0${digits[0]}`, digits.slice(1)];
  }
  let segment = digits.slice(0, 2);
  if (segment.length === 2 && Number(segment) > max) {
    segment = String(max);
  }
  return [segment, digits.slice(2)];
}

/**
 * Маскирует произвольный ввод в `ЧЧ:ММ[:СС]`: оставляет только цифры, расставляет
 * двоеточия и зажимает каждый сегмент в допустимый диапазон, поэтому невозможные
 * значения (`99:99`, `30:70`) набрать нельзя — они приводятся к корректным.
 */
export function maskTime(input: string, withSeconds: boolean): string {
  const digits = input.replace(/\D/g, "").slice(0, withSeconds ? 6 : 4);
  const segments: string[] = [];
  let [segment, rest] = takeSegment(digits, 23);
  segments.push(segment);
  if (rest.length > 0) {
    [segment, rest] = takeSegment(rest, 59);
    segments.push(segment);
  }
  if (withSeconds && rest.length > 0) {
    [segment, rest] = takeSegment(rest, 59);
    segments.push(segment);
  }
  return segments.join(":");
}

export function Time24Field({ value, withSeconds = false, onChange, className, style, ...rest }: Time24FieldProps) {
  const re = withSeconds ? TIME_RE_HMS : TIME_RE_HM;
  const [draft, setDraft] = useState(value);
  const [editing, setEditing] = useState(false);

  // Пока поле не редактируется — синхронизируем отображение с внешним значением.
  useEffect(() => {
    if (!editing) setDraft(value);
  }, [value, editing]);

  return (
    <input
      {...rest}
      type="text"
      inputMode="numeric"
      maxLength={withSeconds ? 8 : 5}
      className={className}
      style={style}
      placeholder={withSeconds ? "чч:мм:сс" : "чч:мм"}
      value={draft}
      onFocus={() => setEditing(true)}
      onChange={(event) => {
        const next = maskTime(event.target.value, withSeconds);
        setDraft(next);
        if (re.test(next)) onChange(next);
      }}
      onBlur={() => {
        setEditing(false);
        if (re.test(draft)) onChange(draft);
        else setDraft(value); // невалидный ввод — откат к последнему корректному
      }}
    />
  );
}

/**
 * Замена нативного `<input type="datetime-local">`: нативный календарь для даты
 * (у даты нет проблемы AM/PM) + [Time24Field] для времени в 24-часовом формате.
 * Контракт значения тот же — строка `YYYY-MM-DDTHH:mm` (локальное), как у datetime-local.
 */
type DateTime24FieldProps = {
  value: string;
  onChange: (value: string) => void;
  className?: string;
};

export function DateTime24Field({ value, onChange, className }: DateTime24FieldProps) {
  const sep = value.indexOf("T");
  const datePart = sep >= 0 ? value.slice(0, sep) : value;
  const timePart = sep >= 0 ? value.slice(sep + 1, sep + 6) : "";

  const combine = (date: string, time: string) => `${date}T${time || "00:00"}`;

  return (
    <span className={`tgu-dt24${className ? ` ${className}` : ""}`} style={{ display: "flex", alignItems: "center", gap: "0.3rem" }}>
      <input
        type="date"
        lang="ru-RU"
        style={{ width: "8rem" }}
        value={datePart}
        onChange={(event) => onChange(combine(event.target.value, timePart))}
      />
      <Time24Field
        style={{ width: "4.6rem", textAlign: "center" }}
        value={timePart}
        onChange={(time) => onChange(combine(datePart, time))}
      />
    </span>
  );
}
