import { useState } from 'react'
import { createFileRoute, Link } from '@tanstack/react-router'
import { useTranslation } from 'react-i18next'
import {
  Alert,
  Badge,
  Button,
  EmptyState,
  IconButton,
  LoadingBlock,
  Modal,
  MultiSelect,
  PageHeader,
  Panel,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeaderCell,
  TableRow,
  TextArea,
  TextInput,
  type SelectOption,
} from '@/ui'
import {
  CopyIcon,
  PlusIcon,
  TrashIcon,
} from '@phosphor-icons/react'
import { useWebhookSubscriptions } from '@/api/queries'
import {
  useCreateWebhook,
  useDeleteWebhook,
} from '@/api/mutations'
import type {
  CreateWebhookSubscriptionRequest,
  DataScope,
  WebhookSubscription,
} from '@/api/client'
import { SCOPE_DOT } from '@/lib/scope-style'

export const Route = createFileRoute('/webhooks/')({
  component: WebhooksPage,
})

const SCOPE_OPTIONS: SelectOption[] = [
  { id: 'PUBLIC', label: 'PUBLIC' },
  { id: 'INTERNAL', label: 'INTERNAL' },
  { id: 'RESTRICTED', label: 'RESTRICTED' },
]

/**
 * Known outbox event types в порядке от самых частых (record CRUD) до
 * реже встречающихся (schema workflow). Backend emit'ит PascalCase
 * (см. DictionaryRecordService, DictionaryDefinitionService,
 * SchemaDraftService). При новых событиях — добавлять сюда.
 *
 * <p>Pre-v2.4: hint текст в форме фигурировал dot-case формат
 * `record.created` — это был docs bug, backend такие не emit'ит.
 * Multi-select закрывает дыру и не даёт пользователю ввести неверное
 * строковое имя.
 */
const EVENT_TYPE_OPTIONS: SelectOption[] = [
  // Record CRUD
  { id: 'RecordCreated', label: 'RecordCreated' },
  { id: 'RecordUpdated', label: 'RecordUpdated' },
  { id: 'RecordDeleted', label: 'RecordDeleted' },
  // Dict definition / schema
  { id: 'DefinitionCreated', label: 'DefinitionCreated' },
  { id: 'DefinitionUpdated', label: 'DefinitionUpdated' },
  // Schema workflow (v2.2.0+)
  { id: 'SchemaDraftCreated', label: 'SchemaDraftCreated' },
  { id: 'SchemaDraftUpdated', label: 'SchemaDraftUpdated' },
  { id: 'SchemaDraftReviewRequested', label: 'SchemaDraftReviewRequested' },
  { id: 'SchemaDraftDecided', label: 'SchemaDraftDecided' },
  { id: 'SchemaDraftPublished', label: 'SchemaDraftPublished' },
  { id: 'SchemaDraftWithdrawn', label: 'SchemaDraftWithdrawn' },
]

function WebhooksPage() {
  const { t } = useTranslation()
  const { data, isLoading, error } = useWebhookSubscriptions()
  const [createOpen, setCreateOpen] = useState(false)
  const [revealedSecret, setRevealedSecret] = useState<{
    name: string
    secret: string
  } | null>(null)
  const deleteMut = useDeleteWebhook()

  const handleDelete = (sub: WebhookSubscription) => {
    if (!window.confirm(t('webhooks.confirmDelete', { name: sub.name }))) return
    deleteMut.mutate(sub.id)
  }

  if (isLoading) return <LoadingBlock size="md" label={t('loading')} />
  if (error) {
    return (
      <Alert variant="error" title={t('error.failed')}>
        {String(error)}
      </Alert>
    )
  }

  return (
    <div className="space-y-6">
      <PageHeader
        title={t('webhooks.title')}
        description={t('webhooks.subtitle')}
        actions={
          <Button
            type="button"
            variant="primary"
            leftIcon={<PlusIcon weight="bold" size={16} />}
            onClick={() => setCreateOpen(true)}
          >
            {t('webhooks.action.create')}
          </Button>
        }
      />

      {!data || data.length === 0 ? (
        <EmptyState title={t('webhooks.empty')} />
      ) : (
        <Panel>
          <Table>
            <TableHead>
              <TableRow>
                <TableHeaderCell>{t('webhooks.col.name')}</TableHeaderCell>
                <TableHeaderCell>{t('webhooks.col.url')}</TableHeaderCell>
                <TableHeaderCell>{t('webhooks.col.scopes')}</TableHeaderCell>
                <TableHeaderCell>{t('webhooks.col.dictionaries')}</TableHeaderCell>
                <TableHeaderCell>{t('webhooks.col.status')}</TableHeaderCell>
                <TableHeaderCell align="right">{t('dict.col.actions')}</TableHeaderCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {data.map((sub) => (
                <TableRow key={sub.id}>
                  <TableCell>
                    <Link
                      to="/webhooks/$id"
                      params={{ id: sub.id }}
                      className="font-medium text-accent hover:underline"
                    >
                      {sub.name}
                    </Link>
                  </TableCell>
                  <TableCell>
                    <span className="text-mono truncate max-w-xs inline-block align-middle">
                      {sub.url}
                    </span>
                  </TableCell>
                  <TableCell>
                    <ScopeChips scopes={sub.scopeFilter} />
                  </TableCell>
                  <TableCell>
                    {sub.dictionaryFilter && sub.dictionaryFilter.length > 0 ? (
                      <span className="text-cell text-ink">
                        {sub.dictionaryFilter.slice(0, 3).join(', ')}
                        {sub.dictionaryFilter.length > 3 && ` +${sub.dictionaryFilter.length - 3}`}
                      </span>
                    ) : (
                      <span className="text-cell text-mute">{t('webhooks.allDicts')}</span>
                    )}
                  </TableCell>
                  <TableCell>
                    <Badge variant={sub.active ? 'success' : 'neutral'}>
                      {sub.active ? t('webhooks.active') : t('webhooks.inactive')}
                    </Badge>
                  </TableCell>
                  <TableCell align="right">
                    <IconButton
                      label={t('webhooks.action.delete')}
                      variant="danger"
                      icon={<TrashIcon weight="regular" />}
                      onClick={() => handleDelete(sub)}
                    />
                  </TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </Panel>
      )}

      <CreateWebhookDialog
        open={createOpen}
        onClose={() => setCreateOpen(false)}
        onSuccess={(sub, secret) => {
          setCreateOpen(false)
          setRevealedSecret({ name: sub.name, secret })
        }}
      />

      <SecretRevealModal
        revealed={revealedSecret}
        onClose={() => setRevealedSecret(null)}
      />
    </div>
  )
}

function ScopeChips({ scopes }: { scopes?: DataScope[] | null }) {
  const { t } = useTranslation()
  if (!scopes || scopes.length === 0) {
    return <span className="text-cell text-mute">{t('webhooks.allScopes')}</span>
  }
  return (
    <div className="flex gap-1">
      {scopes.map((s) => (
        <span
          key={s}
          className="text-cap inline-flex items-center gap-1"
          title={s}
        >
          <span className={`inline-block size-2 rounded-full ${SCOPE_DOT[s]}`} aria-hidden />
        </span>
      ))}
    </div>
  )
}

type CreateDialogProps = {
  open: boolean
  onClose: () => void
  onSuccess: (sub: WebhookSubscription, secret: string) => void
}

function CreateWebhookDialog({ open, onClose, onSuccess }: CreateDialogProps) {
  const { t } = useTranslation()
  const create = useCreateWebhook()

  const [name, setName] = useState('')
  const [url, setUrl] = useState('')
  const [scopeFilter, setScopeFilter] = useState<string[]>([])
  const [dictionaryFilterCsv, setDictionaryFilterCsv] = useState('')
  const [eventTypeFilter, setEventTypeFilter] = useState<string[]>([])
  const [description, setDescription] = useState('')
  const [errorMsg, setErrorMsg] = useState<string | null>(null)

  const reset = () => {
    setName('')
    setUrl('')
    setScopeFilter([])
    setDictionaryFilterCsv('')
    setEventTypeFilter([])
    setDescription('')
    setErrorMsg(null)
  }

  const csvToArray = (s: string): string[] | undefined => {
    const arr = s
      .split(',')
      .map((x) => x.trim())
      .filter(Boolean)
    return arr.length > 0 ? arr : undefined
  }

  const handleSubmit = () => {
    setErrorMsg(null)
    if (!name.trim() || !url.trim()) {
      setErrorMsg(t('webhooks.error.nameUrlRequired'))
      return
    }
    if (!/^https?:\/\//.test(url)) {
      setErrorMsg(t('webhooks.error.urlScheme'))
      return
    }
    const req: CreateWebhookSubscriptionRequest = {
      name: name.trim(),
      url: url.trim(),
      scopeFilter: scopeFilter.length > 0 ? (scopeFilter as DataScope[]) : undefined,
      dictionaryFilter: csvToArray(dictionaryFilterCsv),
      eventTypeFilter: eventTypeFilter.length > 0 ? eventTypeFilter : undefined,
      active: true,
      description: description.trim() || undefined,
    }
    create.mutate(req, {
      onSuccess: (sub) => {
        const plaintext = sub.hmacSecret
        reset()
        onSuccess(sub, plaintext)
      },
      onError: (e) => setErrorMsg(String(e)),
    })
  }

  return (
    <Modal
      isOpen={open}
      onClose={() => {
        reset()
        onClose()
      }}
      title={t('webhooks.action.create')}
      maxWidth="max-w-2xl"
    >
      <div className="space-y-4">
        <TextInput
          label={t('webhooks.field.name')}
          required
          placeholder="altum-imaging-pull"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
        <TextInput
          label={t('webhooks.field.url')}
          required
          placeholder="https://altum.example.com/hooks/ordinis"
          hint={t('webhooks.field.urlHint')}
          value={url}
          onChange={(e) => setUrl(e.target.value)}
        />
        <MultiSelect
          label={t('webhooks.field.scopeFilter')}
          options={SCOPE_OPTIONS}
          value={scopeFilter}
          onChange={(ids) => setScopeFilter(ids as string[])}
          hint={t('webhooks.field.scopeFilterHint')}
        />
        <TextInput
          label={t('webhooks.field.dictionaryFilter')}
          placeholder="spacecraft, satellite_type"
          hint={t('webhooks.field.dictionaryFilterHint')}
          value={dictionaryFilterCsv}
          onChange={(e) => setDictionaryFilterCsv(e.target.value)}
        />
        <MultiSelect
          label={t('webhooks.field.eventTypeFilter')}
          options={EVENT_TYPE_OPTIONS}
          value={eventTypeFilter}
          onChange={(ids) => setEventTypeFilter(ids as string[])}
          hint={t('webhooks.field.eventTypeFilterHint')}
          searchable
          searchPlaceholder={t('webhooks.field.eventTypeSearch', {
            defaultValue: 'Поиск типа события',
          })}
        />
        <TextArea
          label={t('webhooks.field.description')}
          rows={2}
          value={description}
          onChange={(e) => setDescription(e.target.value)}
        />

        {errorMsg && <Alert variant="error">{errorMsg}</Alert>}

        <div className="flex justify-end gap-2 pt-2">
          <Button
            variant="ghost"
            onClick={() => {
              reset()
              onClose()
            }}
            disabled={create.isPending}
          >
            {t('form.cancel')}
          </Button>
          <Button
            variant="primary"
            loading={create.isPending}
            onClick={handleSubmit}
          >
            {t('webhooks.action.create')}
          </Button>
        </div>
      </div>
    </Modal>
  )
}

function SecretRevealModal({
  revealed,
  onClose,
}: {
  revealed: { name: string; secret: string } | null
  onClose: () => void
}) {
  const { t } = useTranslation()
  const [copied, setCopied] = useState(false)

  if (!revealed) return null

  const handleCopy = () => {
    navigator.clipboard?.writeText(revealed.secret).then(() => {
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    })
  }

  return (
    <Modal
      isOpen={true}
      onClose={onClose}
      title={t('webhooks.secret.title', { name: revealed.name })}
      maxWidth="max-w-xl"
    >
      <div className="space-y-4">
        <Alert variant="warning" title={t('webhooks.secret.warningTitle')}>
          {t('webhooks.secret.warning')}
        </Alert>
        <div className="bg-ink/5 border border-line rounded-md p-3">
          <code className="text-mono break-all">{revealed.secret}</code>
        </div>
        <div className="flex justify-end gap-2">
          <Button
            variant="secondary"
            leftIcon={<CopyIcon weight="bold" size={16} />}
            onClick={handleCopy}
          >
            {copied ? t('webhooks.secret.copied') : t('webhooks.secret.copy')}
          </Button>
          <Button variant="primary" onClick={onClose}>
            {t('webhooks.secret.acknowledge')}
          </Button>
        </div>
      </div>
    </Modal>
  )
}
