import { useQuery, useQueryClient } from '@tanstack/react-query'
import { ReloadOutlined, SaveOutlined } from '@ant-design/icons'
import {
  Alert,
  App,
  Button,
  Card,
  Form,
  Input,
  InputNumber,
  Popconfirm,
  Space,
  Switch,
  Tag,
  Typography,
} from 'antd'
import { useEffect, useState } from 'react'

import {
  addAdminMockCustomShop,
  deleteAdminMockCustomShop,
  fetchAdminMockCustomShops,
  fetchAdminScheduledJobsConfig,
  fetchAdminWorkerAnnouncement,
  renameAdminMockCustomShop,
  runAdminScheduledJob,
  saveAdminWorkerAnnouncement,
  saveAdminScheduledJobsConfig,
} from '@/services/admin'
import type { AdminScheduledJobItem, AdminScheduledJobRuntimeState } from '@/types/admin'
import type { WorkerAnnouncementConfig } from '@/types/worker-platform'
import { formatAdminDateTime } from '@/utils/admin-time'

import HallConfigPanel from './HallConfigPanel'

function isDepositUnfreezeJob(job: AdminScheduledJobItem) {
  return job.type === 'deposit_unfreeze' || job.id === 'deposit-unfreeze'
}

export default function AnnouncementPanel() {
  return (
    <Space direction="vertical" size={16} style={{ width: '100%' }}>
      <AnnouncementCard />
      <DepositUnfreezeCard />
      <MockCustomShopsCard />
      <HallConfigPanel />
    </Space>
  )
}

function DepositUnfreezeCard() {
  const { message } = App.useApp()
  const queryClient = useQueryClient()
  const [saving, setSaving] = useState(false)
  const [running, setRunning] = useState(false)
  const [draft, setDraft] = useState<AdminScheduledJobItem | null>(null)

  const jobsQuery = useQuery({
    queryKey: ['admin-scheduled-jobs'],
    queryFn: fetchAdminScheduledJobsConfig,
  })
  const source = jobsQuery.data?.data
  const currentJob = source?.source.jobs.find(isDepositUnfreezeJob) || null
  const runtime: AdminScheduledJobRuntimeState | null =
    source?.runtime.find((item) => item.id === (draft?.id || currentJob?.id)) || null

  useEffect(() => {
    setDraft(currentJob ? { ...currentJob } : null)
  }, [currentJob])

  function patchJob(patch: Partial<AdminScheduledJobItem>) {
    setDraft((prev) => (prev ? { ...prev, ...patch } : prev))
  }

  async function saveJob() {
    if (!draft || !source) return
    setSaving(true)
    try {
      await saveAdminScheduledJobsConfig({
        ...source.source,
        jobs: source.source.jobs.map((item) => (item.id === draft.id ? draft : item)),
      })
      await queryClient.invalidateQueries({ queryKey: ['admin-scheduled-jobs'] })
      message.success('押金解冻配置已保存')
    } catch (error) {
      message.error(error instanceof Error ? error.message : '保存押金解冻配置失败')
    } finally {
      setSaving(false)
    }
  }

  async function runNow() {
    const jobId = draft?.id || currentJob?.id || ''
    if (!jobId) return
    setRunning(true)
    try {
      await runAdminScheduledJob(jobId)
      await queryClient.invalidateQueries({ queryKey: ['admin-scheduled-jobs'] })
      message.success('押金解冻任务已执行')
    } catch (error) {
      message.error(error instanceof Error ? error.message : '执行押金解冻失败')
    } finally {
      setRunning(false)
    }
  }

  return (
    <Card
      title="押金到期解冻"
      bordered={false}
      extra={
        <Space wrap>
          <Button icon={<ReloadOutlined />} loading={running} onClick={() => void runNow()}>
            立即解冻
          </Button>
          <Button
            type="primary"
            icon={<SaveOutlined />}
            loading={saving}
            disabled={!draft}
            onClick={() => void saveJob()}
          >
            保存
          </Button>
        </Space>
      }
    >
      <Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
        验收后的报酬与押金进入待解冻队列，到期自动转入打手可用余额；
        解冻天数与报酬延迟在「财务」面板配置，调小后存量待解冻也会按新天数提前到期。
      </Typography.Paragraph>
      {draft ? (
        <Space direction="vertical" size={12} style={{ width: '100%', maxWidth: 520 }}>
          <Space wrap>
            <Switch
              checked={draft.enabled !== false}
              onChange={(enabled) => patchJob({ enabled })}
            />
            <Tag color={draft.enabled !== false ? 'green' : 'default'}>
              {draft.enabled !== false ? '已启用' : '已停用'}
            </Tag>
          </Space>
          <Space wrap>
            <Typography.Text type="secondary">执行间隔（秒）</Typography.Text>
            <InputNumber
              min={30}
              max={3600}
              value={draft.intervalSeconds}
              onChange={(value) => patchJob({ intervalSeconds: Number(value || 60) })}
            />
            <Typography.Text type="secondary">每次解冻数量</Typography.Text>
            <InputNumber
              min={1}
              max={2000}
              value={Number(draft.config?.scanLimit ?? 100)}
              onChange={(value) =>
                patchJob({ config: { ...draft.config, scanLimit: Number(value || 100) } })
              }
            />
          </Space>
        </Space>
      ) : (
        <Typography.Text type="secondary">加载中…</Typography.Text>
      )}
      {runtime ? (
        <Alert
          style={{ marginTop: 16, maxWidth: 640 }}
          type={
            runtime.lastStatus === 'ok' || runtime.lastStatus === 'success'
              ? 'success'
              : runtime.lastStatus
                ? 'warning'
                : 'info'
          }
          showIcon
          message={runtime.lastMessage || '尚未运行'}
          description={[
            `扫描 ${runtime.lastCheckedCount ?? 0}`,
            `解冻 ${runtime.lastAsset ?? 0}`,
            `上次：${formatAdminDateTime(runtime.lastFinishedAt || runtime.lastRunAt)}`,
            `下次：${formatAdminDateTime(runtime.nextRunAt)}`,
          ].join(' · ')}
        />
      ) : null}
    </Card>
  )
}

function AnnouncementCard() {
  const { message } = App.useApp()
  const queryClient = useQueryClient()
  const [form] = Form.useForm<WorkerAnnouncementConfig>()
  const [saving, setSaving] = useState(false)
  const announcementQuery = useQuery({
    queryKey: ['admin-worker-announcement'],
    queryFn: fetchAdminWorkerAnnouncement,
  })

  useEffect(() => {
    if (announcementQuery.data?.data) form.setFieldsValue(announcementQuery.data.data)
  }, [announcementQuery.data, form])

  async function saveAnnouncement(values: WorkerAnnouncementConfig) {
    setSaving(true)
    try {
      await saveAdminWorkerAnnouncement({
        enabled: values.enabled !== false,
        content: String(values.content || '').trim(),
      })
      await queryClient.invalidateQueries({ queryKey: ['admin-worker-announcement'] })
      message.success('公告已保存')
    } catch (error) {
      message.error(error instanceof Error ? error.message : '保存公告失败')
    } finally {
      setSaving(false)
    }
  }

  return (
    <Card title="打手端滚动公告" bordered={false}>
      <Form form={form} layout="vertical" onFinish={saveAnnouncement} style={{ maxWidth: 760 }}>
        <Form.Item name="enabled" valuePropName="checked" label="展示公告">
          <Switch />
        </Form.Item>
        <Form.Item
          name="content"
          label="公告内容"
          rules={[{ required: true, whitespace: true, message: '请填写公告内容' }]}
          extra="公告会显示在打手端各页面顶部并横向滚动。"
        >
          <Input.TextArea rows={4} maxLength={300} showCount placeholder="请输入打手端公告内容" />
        </Form.Item>
        <Space>
          <Button type="primary" htmlType="submit" loading={saving}>
            保存公告
          </Button>
          <Typography.Text type="secondary">关闭后打手端不显示公告栏。</Typography.Text>
        </Space>
      </Form>
    </Card>
  )
}

function MockCustomShopsCard() {
  const { message, modal } = App.useApp()
  const queryClient = useQueryClient()
  const [adding, setAdding] = useState(false)
  const [addForm] = Form.useForm<{ name: string }>()
  const customShopsQuery = useQuery({
    queryKey: ['admin-mock-custom-shops'],
    queryFn: fetchAdminMockCustomShops,
  })
  const shops = customShopsQuery.data?.data.items || []

  async function refresh() {
    await queryClient.invalidateQueries({ queryKey: ['admin-mock-custom-shops'] })
  }

  async function runShopAction(action: () => Promise<unknown>, successMessage: string) {
    try {
      await action()
      await refresh()
      message.success(successMessage)
    } catch (error) {
      message.error(error instanceof Error ? error.message : '操作失败')
    }
  }

  async function addShop(values: { name: string }) {
    setAdding(true)
    try {
      await runShopAction(
        () => addAdminMockCustomShop(String(values.name || '').trim()),
        '自定义店铺已新增',
      )
      addForm.resetFields()
    } finally {
      setAdding(false)
    }
  }

  function renameShop(name: string) {
    let nextName = ''
    modal.confirm({
      title: '重命名自定义店铺',
      content: (
        <Input
          defaultValue={name}
          maxLength={64}
          placeholder="请输入新的店铺名称"
          onChange={(event) => {
            nextName = String(event.target.value || '')
          }}
        />
      ),
      onOk: async () => {
        const trimmed = nextName.trim()
        if (!trimmed || trimmed === name) return
        await runShopAction(() => renameAdminMockCustomShop(name, trimmed), '自定义店铺已重命名')
      },
    })
  }

  return (
    <Card title="本地 Mock 自定义店铺" bordered={false}>
      <Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
        在接单工单「本地 Mock」中录入过的外部平台店铺会自动记忆到这里；也可以直接维护，
        维护后的店铺会出现在 Mock 表单的下拉选项中。
      </Typography.Paragraph>
      <Form form={addForm} layout="inline" onFinish={addShop} style={{ marginBottom: 12 }}>
        <Form.Item
          name="name"
          rules={[{ required: true, whitespace: true, message: '请输入店铺名称' }]}
          style={{ minWidth: 260 }}
        >
          <Input maxLength={64} placeholder="输入店铺名称，如：抖音-某某小店" />
        </Form.Item>
        <Form.Item>
          <Button type="primary" htmlType="submit" loading={adding}>
            新增店铺
          </Button>
        </Form.Item>
      </Form>
      {shops.length === 0 ? (
        <Typography.Text type="secondary">
          还没有自定义店铺，先在上方新增或通过本地 Mock 录入。
        </Typography.Text>
      ) : (
        <Space size={[8, 8]} wrap>
          {shops.map((name) => (
            <Space key={name} size={4} wrap>
              <Typography.Text>{name}</Typography.Text>
              <Button size="small" type="text" onClick={() => renameShop(name)}>
                重命名
              </Button>
              <Popconfirm
                title={`删除自定义店铺「${name}」？`}
                description="不影响已用它生成的工单，仅从 Mock 下拉选项移除。"
                okText="删除"
                okButtonProps={{ danger: true }}
                onConfirm={() =>
                  runShopAction(() => deleteAdminMockCustomShop(name), '自定义店铺已删除')
                }
              >
                <Button size="small" type="text" danger>
                  删除
                </Button>
              </Popconfirm>
            </Space>
          ))}
        </Space>
      )}
    </Card>
  )
}
