import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { Helmet } from 'react-helmet-async'

import FormField from '@/components/common/FormField'
import PageTitle from '@/components/common/PageTitle'
import MainArea from '@/components/layout/MainArea'
import { Button } from '@/components/ui/button'
import { toast } from '@/components/ui/use-toast'
import { SITE_TITLE } from '@/config'
import { createMaterialSyncSuppression, fetchMaterialSyncSuppressions } from '@/lib/materials'
import { materialsKeys } from '@/lib/queryKeys'
import { dateString, inputClass } from '@/lib/utils'

import type { FC, FormEvent } from 'react'

import type { MaterialSyncSuppressionSourceKind } from '@/types'

const SOURCE_KIND_LABELS: Record<MaterialSyncSuppressionSourceKind, string> = {
    uri:               'URI',
    google_drive_path: 'Google Drive ファイル',
    google_drive_path_prefix: 'Google Drive フォルダ',
    google_drive_file: 'Google Drive ファイル Id.',
    legacy_drive_path: '汎用ファイル',
    legacy_drive_path_prefix: '汎用フォルダ' }

const REASONS = [
    'copyright_high_risk',
    'copyright_takedown',
    'adult_or_sensitive',
    'personal_information',
    'malware_or_dangerous_file',
    'duplicate_or_low_quality',
    'source_owner_request',
    'other'] as const

type MaterialSyncSuppressionReason = typeof REASONS[number]

const REASON_NAMES: Record<MaterialSyncSuppressionReason, string> = {
    ['copyright_high_risk']: '著作権への懸念',
    ['copyright_takedown']: '著作者からの申出',
    ['adult_or_sensitive']: '成人向け',
    ['personal_information']: '個人情報',
    ['malware_or_dangerous_file']: '危険なソフトウェア',
    ['duplicate_or_low_quality']: '重複',
    ['source_owner_request']: '同期元管理者からの申出',
    ['other']: 'その他' } as const


const reasonName = (reason: string): string =>
    REASON_NAMES[reason as MaterialSyncSuppressionReason] ?? reason


const MaterialSyncSuppressionsPage: FC = () => {
  const qc = useQueryClient ()
  const [sourceKind, setSourceKind] =
      useState<MaterialSyncSuppressionSourceKind> ('uri')
  const [sourceUri, setSourceUri] = useState ('')
  const [drivePath, setDrivePath] = useState ('')
  const [driveFileId, setDriveFileId] = useState ('')
  const [reason, setReason] = useState<MaterialSyncSuppressionReason> (REASONS[0])

  const { data, isError, isLoading } = useQuery ({
      queryKey: materialsKeys.suppressions (),
      queryFn:  fetchMaterialSyncSuppressions})

  const createMutation = useMutation ({
      mutationFn: async () =>
	  await createMaterialSyncSuppression ({
	      sourceKind,
	      sourceUri,
	      drivePath,
	      driveFileId,
	      reason}),
      onSuccess: async () => {
	await qc.invalidateQueries ({ queryKey: materialsKeys.suppressions () })
	await qc.invalidateQueries ({ queryKey: materialsKeys.root })
	setSourceUri ('')
	setDrivePath ('')
	setDriveFileId ('')
	toast ({ title: '同期元抑止を登録しました' })
      },
      onError: () => {
	toast ({ title: '同期元抑止の登録に失敗しました' })
      }})

  const handleSubmit = (event: FormEvent) => {
    event.preventDefault ()
    createMutation.mutate ()
  }

  const suppressions = data?.suppressions ?? []

  return (
      <MainArea>
	<Helmet>
	  <title>{`素材同期抑止 | ${ SITE_TITLE }`}</title>
	</Helmet>

	<div className="space-y-5">
	  <PageTitle>同期抑止</PageTitle>

	  <form
	      onSubmit={handleSubmit}
	      className="max-w-3xl rounded-lg border border-stone-200 bg-white p-4
			 text-stone-900 dark:border-stone-700 dark:bg-stone-900
			 dark:text-stone-100">
	    <div className="space-y-3">
	      <FormField label="同期元種別">
		{({ invalid }) => (
		    <select
			value={sourceKind}
			onChange={e => setSourceKind (
			    e.target.value as MaterialSyncSuppressionSourceKind)}
			className={inputClass (invalid)}>
		      {Object.entries (SOURCE_KIND_LABELS).map (([value, label]) => (
			  <option key={value} value={value}>
			    {label}
			  </option>))}
		    </select>)}
	      </FormField>

	      <FormField label="同期元 URI">
		{({ invalid }) => (
		    <input
			type="text"
			value={sourceUri}
			onChange={e => setSourceUri (e.target.value)}
			className={inputClass (invalid)}/>)}
	      </FormField>

	      <FormField label="Google Drive パス">
		{({ invalid }) => (
		    <input
			type="text"
			value={drivePath}
			onChange={e => setDrivePath (e.target.value)}
			className={inputClass (invalid)}/>)}
	      </FormField>

	      <FormField label="Google Drive ファイル Id.">
		{({ invalid }) => (
		    <input
			type="text"
			value={driveFileId}
			onChange={e => setDriveFileId (e.target.value)}
			className={inputClass (invalid)}/>)}
	      </FormField>

	      <FormField label="事由">
		{({ invalid }) => (
		    <select
			value={reason}
			onChange={e => setReason (e.target.value as MaterialSyncSuppressionReason)}
			className={inputClass (invalid)}>
		      {REASONS.map (value => (
			  <option key={value} value={value}>
			    {REASON_NAMES[value]}
			  </option>))}
		    </select>)}
	      </FormField>
	    </div>

	    <Button
		type="submit"
		className="mt-4 rounded bg-blue-600 px-4 py-2 text-white
			   disabled:bg-gray-400"
		disabled={createMutation.isPending}>
	      登録
	    </Button>
	  </form>

	  {isLoading && <p>Loading...</p>}
	  {isError && (
	      <p className="text-red-600 dark:text-red-300">
		同期元抑止一覧の取得に失敗しました．
	      </p>)}

	  <div className="space-y-3">
	    {suppressions.map (suppression => (
		<article
		    key={suppression.id}
		    className="rounded-lg border border-stone-200 bg-white p-3
			       text-stone-900 shadow-sm dark:border-stone-700
			       dark:bg-stone-900 dark:text-stone-100">
		  <div className="font-medium">
		    {SOURCE_KIND_LABELS[suppression.sourceKind]}
		  </div>
		  <div className="break-all text-sm text-stone-700 dark:text-stone-300">
		    {suppression.normalizedSourceKey}
		  </div>
		  <div className="mt-2 text-sm text-stone-600 dark:text-stone-400">
		    事由: {reasonName (suppression.reason)} /
		    登録: {dateString (suppression.createdAt)}
		  </div>
		</article>))}
	  </div>
	</div>
      </MainArea>)
}

export default MaterialSyncSuppressionsPage
