'use client'
import {createWhitelist, removeWhitelist, listWhitelist, Whitelist, updateWhitelist} from '@/actions/whitelist'
import {Button} from '@/components/ui/button'
import {Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle} from '@/components/ui/dialog'
import {useEffect, useRef, useState} from 'react'
import {PageRecord} from '@/lib/api'
import {useStatus} from '@/lib/states'
import {toast} from 'sonner'
import {Form, FormField} from '@/components/ui/form'
import {useForm} from 'react-hook-form'
import {Input} from '@/components/ui/input'
import {Textarea} from '@/components/ui/textarea'
import {zodResolver} from '@hookform/resolvers/zod'
import {z} from 'zod'
import {Edit, Plus, Trash2, Loader2} from 'lucide-react'
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogDescription, AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import Page from '@/components/page'
import DataTable from '@/components/data-table'
import {format, parseISO} from 'date-fns'
import {getClientIp} from '@/actions/ip'
const schema = z.object({
  host: z.string().min(1, {message: 'IP地址不能为空'}),
  remark: z.string().optional(),
})

type SchemaType = z.infer<typeof schema>

export type WhitelistPageProps = {}

const MAX_WHITELIST_COUNT = 5

export default function WhitelistPage(props: WhitelistPageProps) {
  const [wait, setWait] = useState(false)

  // ======================
  // 数据
  // ======================

  const [status, setStatus] = useStatus()
  const [data, setData] = useState<PageRecord<Whitelist>>({
    page: 1,
    size: 10,
    total: 0,
    list: [],
  })

  const refresh = async (page: number, size: number) => {
    setStatus('load')
    setWait(true)
    try {
      const resp = await listWhitelist({page, size})
      console.log(resp, '白名单resp')

      if (!resp.success) {
        throw new Error(resp.message)
      }

      setStatus('done')
      setData(resp.data)
    }
    catch (e) {
      setStatus('fail')
      toast.error('加载数据失败', {
        description: e instanceof Error ? e.message : String(e),
      })
    }
    finally {
      setWait(false)
    }
  }

  // ======================
  // 弹窗
  // ======================

  const [dialogVisible, setDialogVisible] = useState(false)
  const [dialogType, setDialogType] = useState<'add' | 'edit'>('add')
  const [dialogData, setDialogData] = useState<Whitelist>()

  const openDialog = (type: 'add' | 'edit', data?: Whitelist) => {
    form.reset({
      host: data?.host || '',
      remark: data?.remark || '',
    })
    setDialogVisible(true)
    setDialogType(type)
    setDialogData(data)
  }

  const toggleDialog = (open: boolean) => {
    setDialogVisible(open)
    if (!open) {
      form.reset()
    }
  }

  const [alertVisible, setAlertVisible] = useState(false)
  const removeId = useRef<number | undefined>(undefined)
  const confirmRemove = (id?: number) => {
    setAlertVisible(true)
    if (id) {
      removeId.current = id
    }
    else {
      removeId.current = undefined
    }
  }

  const remove = async () => {
    setWait(true)
    try {
      const ids = removeId.current === undefined
        ? Array.from(selection).map(id => ({id}))
        : [{id: removeId.current}]
      const resp = await removeWhitelist(ids)
      if (resp && resp.success) {
        setAlertVisible(false)
        toast.success('删除成功')
        await refresh(data.page, data.size)
      }
      else {
        toast.error('删除失败')
      }
    }
    catch (error) {
      toast.error('删除失败')
    }
    finally {
      setWait(false)
    }
  }

  const [selection, setSelection] = useState(new Set<number>())

  const toggleSelect = (id: number) => {
    if (selection.has(id)) {
      selection.delete(id)
    }
    else {
      selection.add(id)
    }
    setSelection(new Set(selection))
  }

  const toggleSelectAll = () => {
    if (selection.size === data.list.length) {
      setSelection(new Set())
    }
    else {
      const newSelection = new Set<number>()
      data.list.forEach((item) => {
        newSelection.add(item.id)
      })
      setSelection(newSelection)
    }
  }

  // ======================
  // 表单
  // ======================

  const form = useForm<SchemaType>({
    resolver: zodResolver(schema),
    defaultValues: {
      host: '',
      remark: '',
    },
  })

  const onSubmit = async (value: SchemaType) => {
    setWait(true)
    try {
      // 添加白名单
      if (dialogType === 'add') {
        const resp = await createWhitelist(value)
        if (!resp.success) {
          throw new Error(resp.message)
        }

        await refresh(1, data.size)
        toggleDialog(false)
        toast.success('添加成功')
      }
      // 编辑白名单
      else {
        if (!dialogData) {
          throw new Error('编辑数据出错')
        }

        const resp = await updateWhitelist({...value, id: dialogData.id})
        if (!resp.success) {
          throw new Error(resp.message)
        }

        await refresh(1, data.size)
        toggleDialog(false)
        toast.success('编辑成功')
      }
    }
    catch (e) {
      toast.error(dialogType === 'add' ? '添加失败' : '编辑失败', {
        description: e instanceof Error ? e.message : String(e),
      })
    }
    finally {
      setWait(false)
    }
  }

  // ======================
  // region render
  // ======================

  useEffect(() => {
    refresh(1, 10).then()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  if (status === 'fail') {
    return <div className="flex items-center justify-center h-full">加载失败，请重试</div>
  }

  const getCurrentIP = async () => {
    setWait(true)

    try {
      const result = await getClientIp()

      if (result.ip) {
        form.setValue('host', result.ip)
        toast.success('已获取当前IP地址')
      }
      else {
        toast.error('获取失败', {
          description: result.error || '请手动输入IP地址',
        })
      }
    }
    finally {
      setWait(false)
    }
  }

  return (
    <Page>

      {/* 全局操作 */}
      <section>
        <Button onClick={() => openDialog('add')} disabled={wait || data.total >= MAX_WHITELIST_COUNT}>
          <Plus/>
          添加白名单
          {data.total >= MAX_WHITELIST_COUNT && '（已达上限）'}
        </Button>
      </section>

      {/* 数据表 */}
      <DataTable
        status={status}
        data={data.list}
        pagination={{
          total: data.total,
          page: data.page,
          size: data.size,
          onPageChange: (page: number) => refresh(page, data.size),
          onSizeChange: (size: number) => refresh(1, size),
        }}
        columns={[
          {
            header: `IP 地址`, accessorKey: 'ip',
          },
          {
            header: `备注`, accessorKey: 'remark',
          },
          {
            header: `添加时间`, cell: ({row}) => format(parseISO(row.original.created_at), 'yyyy-MM-dd HH:mm'),
          },
          {
            id: 'actions', header: `操作`, cell: ({row}) => (
              <div className="flex gap-2">
                <Button
                  className="h-9 w-9"
                  theme="outline"
                  onClick={() => openDialog('edit', row.original)}
                  disabled={wait}
                >
                  <Edit className="w-4 h-4"/>
                </Button>
                <Button
                  className="h-9 w-9"
                  onClick={() => confirmRemove(row.original.id)}
                  theme="fail"
                  disabled={wait}
                >
                  <Trash2 className="w-4 h-4"/>
                </Button>
              </div>
            ),
          },
        ]}
      />

      {/* 编辑表单 */}
      <Dialog open={dialogVisible} onOpenChange={toggleDialog}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>
              {dialogType === 'add' ? '添加白名单' : '编辑白名单'}
            </DialogTitle>
          </DialogHeader>
          <Form<SchemaType>
            className="flex flex-col gap-4 py-4"
            form={form}
            onSubmit={onSubmit}>
            <FormField name="host" label="IP地址">
              {({id, field}) => (
                <div className="flex gap-2">
                  <Input
                    {...field}
                    id={id}
                    placeholder="输入IP地址"
                    className="flex-1"
                  />
                  <Button
                    type="button"
                    onClick={getCurrentIP}
                    disabled={wait}
                    className="shrink-0"
                    theme="outline"
                  >
                    {wait ? <Loader2 className="w-4 h-4 animate-spin"/> : '获取当前IP'}
                  </Button>
                </div>
              )}
            </FormField>
            <FormField name="remark" label="备注">
              {({id, field}) => (
                <Textarea {...field} id={id} placeholder="输入备注信息（可选）" disabled={wait}/>
              )}
            </FormField>
            <DialogFooter className="gap-4 mt-4">
              <Button theme="outline" type="button" onClick={() => toggleDialog(false)} disabled={wait}>取消</Button>
              <Button type="submit" disabled={wait}>
                {wait && <Loader2 className="w-4 h-4 mr-2 animate-spin"/>}
                保存
              </Button>
            </DialogFooter>
          </Form>
        </DialogContent>
      </Dialog>

      {/* 删除表单 */}
      <AlertDialog open={alertVisible} onOpenChange={setAlertVisible}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>删除白名单</AlertDialogTitle>
            <AlertDialogDescription>
              确定要删除该白名单吗？
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <Button theme="outline" onClick={() => setAlertVisible(false)}>取消</Button>
            <Button theme="fail" onClick={() => remove()}>删除</Button>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </Page>
  )

  // endregion
}
