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

import PrefetchLink from '@/components/PrefetchLink'
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 path',
    google_drive_file: 'Google Drive file ID',
    legacy_drive_path: 'Legacy Drive path'}

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


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 (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">
	  <div className="flex flex-wrap items-center justify-between gap-3">
	    <PageTitle>同期元抑止</PageTitle>
	    <PrefetchLink
		to="/materials"
		className="text-sm text-sky-700 underline underline-offset-2 dark:text-sky-300">
	      素材一覧へ戻る
	    </PrefetchLink>
	  </div>

	  <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="Source URI">
		{({ invalid }) => (
		    <input
			type="text"
			value={sourceUri}
			onChange={e => setSourceUri (e.target.value)}
			className={inputClass (invalid)}/>)}
	      </FormField>

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

	      <FormField label="Drive file 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)}
			className={inputClass (invalid)}>
		      {REASONS.map (value => (
			  <option key={value} value={value}>
			    {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">
		    理由: {suppression.reason} / 登録: {dateString (suppression.createdAt)}
		  </div>
		</article>))}
	  </div>
	</div>
      </MainArea>)
}

export default MaterialSyncSuppressionsPage
