import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

import type { ClassValue } from 'clsx'


export const toDate = (d: string | Date): Date => typeof d === 'string' ? new Date (d) : d


export const cn = (...inputs: ClassValue[]) => twMerge (clsx (...inputs))


export const dateString = (
    d:        string | Date,
    unknown:  'month' | 'day' | 'hour' | 'minute' | 'second' | null = null): string =>
    toDate (d).toLocaleString (
	'ja-JP-u-ca-japanese',
	{ era: 'long',
	  year: 'numeric',
	  month: (unknown === 'month' ? undefined : 'long'),
	  day: unknown != null && ['month', 'day'].includes (unknown) ? undefined : 'numeric',
	  weekday: unknown != null && ['month', 'day'].includes (unknown) ? undefined : 'short',
	  hour: unknown == null || ['second', 'minute'].includes (unknown) ? 'numeric' : undefined,
	  minute: unknown == null || unknown === 'second' ? 'numeric' : undefined,
	  second: unknown == null ? 'numeric' : undefined })


export const originalCreatedAtString = (
    f:  string | Date | null,
    b:  string | Date | null): string => {
  const from = f ? toDate (f) : null
  const before = b ? toDate (b) : null

  if (from && before)
    {
      const diff = before.getTime () - from.getTime ()

      if (diff <= 60_000 /* 1 分 */)
	return dateString (from, 'second')

      if (from.getMinutes () === 0 && before.getMinutes () === 0)
	{
	  if (Math.abs (diff - 3_600_000 /* 1 時間 */) < 60_000)
	    return dateString (from, 'minute') + ' (分不詳)'

	  if (from.getHours () === 0 && before.getHours () === 0)
	    {
	      if (Math.abs (diff - 86_400_000 /* 1 日 */) < 60_000)
		return dateString (from, 'hour') + ' (時刻不詳)'

	      if (from.getDate () === 1 && before.getDate () === 1)
		{
		  if (2_332_800_000 /* 27 日 */ < diff && diff < 2_764_800_000 /* 32 日 */)
		    return dateString (from, 'day') + ' (日不詳)'

		  if (from.getMonth () === 0 && before.getMonth () === 0
		      && (31_449_600_000 /* 364 日 */ <= diff
			  && diff < 31_708_800_000 /* 367 日 */))
		    return dateString (from, 'month') + ' (月日不詳)'
		}
	    }
	}
    }

  const rtn = ([from ? `${ dateString (from, 'second') }` : '',
		'〜',
		before ? `${ dateString (new Date (before.getTime () - 60_000), 'second') }` : '']
	       .filter (Boolean)
	       .join (' '))
  return rtn === '〜' ? '年月日不詳' : rtn
}


export const msToTime = (ms: number): string => {
  const totalS = Math.trunc (ms / 1_000)
  const s = String (totalS % 60)
  const min = String (Math.trunc (totalS / 60) % 60)
  const h = Math.trunc (totalS / 3_600)
  const remainderMs = ms % 1_000

  const base =
      (h > 0
       ? `${ h }:${ min.padStart (2, '0') }:${ s.padStart (2, '0') }`
       : `${ min }:${ s.padStart (2, '0') }`)

  return remainderMs > 0 ? `${ base }.${ remainderMs.toString ().padStart (3, '0') }` : base
}


export const inputClass = (invalid?: boolean, className?: string): string =>
    cn ('w-full rounded border p-2',
	(invalid
	 ? ['border-red-500 bg-red-50 text-red-900',
	    'placeholder:text-red-300',
	    'focus:border-red-500 focus:outline-none focus:ring-2 focus:ring-red-200',
	    'dark:border-red-500 dark:bg-red-950/30 dark:text-red-100']
	 : ['border-gray-300',
	    'focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200']),
	className)
