import { Picker, Text, View } from "@tarojs/components";
import { useEffect, useMemo, useState } from "react";
import { normalizeDisplayDateTime, pad2 } from "../../utils/datetime";
import "./index.scss";

type Props = {
  value: string;
  placeholder?: string;
  className?: string;
  onChange: (value: string) => void;
};

const START_YEAR = 2000;
const END_YEAR = 2099;
const MINUTE_STEP = 5;

function isLeapYear(year: number) {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}

function daysInMonth(year: number, month: number) {
  if ([1, 3, 5, 7, 8, 10, 12].includes(month)) return 31;
  if ([4, 6, 9, 11].includes(month)) return 30;
  return isLeapYear(year) ? 29 : 28;
}

function toDisplay(y: number, m: number, d: number, h: number, mm: number) {
  return `${y}-${pad2(m)}-${pad2(d)} ${pad2(h)}:${pad2(mm)}`;
}

function parseOrNow(value?: string) {
  const normalized = normalizeDisplayDateTime(value);
  const fallback = new Date();
  if (!normalized) {
    return {
      year: fallback.getFullYear(),
      month: fallback.getMonth() + 1,
      day: fallback.getDate(),
      hour: fallback.getHours(),
      minute: Math.floor(fallback.getMinutes() / MINUTE_STEP) * MINUTE_STEP
    };
  }
  const [datePart, timePart] = normalized.split(" ");
  const [year, month, day] = datePart.split("-").map(Number);
  const [hour, minute] = timePart.split(":").map(Number);
  return { year, month, day, hour, minute: Math.floor(minute / MINUTE_STEP) * MINUTE_STEP };
}

export default function DateTimeField({ value, placeholder = "请选择时间", className = "", onChange }: Props) {
  const years = useMemo(() => Array.from({ length: END_YEAR - START_YEAR + 1 }, (_, i) => START_YEAR + i), []);
  const months = useMemo(() => Array.from({ length: 12 }, (_, i) => i + 1), []);
  const hours = useMemo(() => Array.from({ length: 24 }, (_, i) => i), []);
  const minutes = useMemo(() => Array.from({ length: 60 / MINUTE_STEP }, (_, i) => i * MINUTE_STEP), []);

  const parsed = parseOrNow(value);

  const [pickerValue, setPickerValue] = useState<number[]>([
    Math.max(0, years.indexOf(parsed.year)),
    Math.max(0, months.indexOf(parsed.month)),
    Math.max(0, parsed.day - 1),
    Math.max(0, hours.indexOf(parsed.hour)),
    Math.max(0, minutes.indexOf(parsed.minute))
  ]);

  const [dayOptions, setDayOptions] = useState<number[]>(
    Array.from({ length: daysInMonth(parsed.year, parsed.month) }, (_, i) => i + 1)
  );

  useEffect(() => {
    const p = parseOrNow(value);
    const dayMax = daysInMonth(p.year, p.month);
    const safeDay = Math.min(p.day, dayMax);
    const safeMinute = minutes.includes(p.minute) ? p.minute : 0;
    setDayOptions(Array.from({ length: dayMax }, (_, i) => i + 1));
    setPickerValue([
      Math.max(0, years.indexOf(p.year)),
      Math.max(0, months.indexOf(p.month)),
      Math.max(0, safeDay - 1),
      Math.max(0, hours.indexOf(p.hour)),
      Math.max(0, minutes.indexOf(safeMinute))
    ]);
  }, [value, years, months, hours, minutes]);

  const selectorRange = useMemo(
    () => [
      years.map((v) => `${v}年`),
      months.map((v) => `${pad2(v)}月`),
      dayOptions.map((v) => `${pad2(v)}日`),
      hours.map((v) => `${pad2(v)}时`),
      minutes.map((v) => `${pad2(v)}分`)
    ],
    [years, months, dayOptions, hours, minutes]
  );

  const displayText = normalizeDisplayDateTime(value);

  const onColumnChange = (e: any) => {
    const { column, value: colValue } = e.detail;
    const next = [...pickerValue];
    next[column] = colValue;

    if (column === 0 || column === 1) {
      const year = years[next[0]];
      const month = months[next[1]];
      const maxDays = daysInMonth(year, month);
      const newDays = Array.from({ length: maxDays }, (_, i) => i + 1);
      setDayOptions(newDays);
      if (next[2] > maxDays - 1) next[2] = maxDays - 1;
    }

    setPickerValue(next);
  };

  const onPickerChange = (e: any) => {
    const [yi, mi, di, hi, mini] = e.detail.value as number[];
    const year = years[yi];
    const month = months[mi];
    const day = dayOptions[di];
    const hour = hours[hi];
    const minute = minutes[mini];
    const output = toDisplay(year, month, day, hour, minute);
    setPickerValue([yi, mi, di, hi, mini]);
    onChange(output);
  };

  return (
    <Picker mode="multiSelector" range={selectorRange} value={pickerValue} onChange={onPickerChange} onColumnChange={onColumnChange}>
      <View className={`dtf ${className}`.trim()}>
        <Text className={`dtf__text ${displayText ? "" : "is-placeholder"}`}>{displayText || placeholder}</Text>
      </View>
    </Picker>
  );
}
