import { useEffect, useState } from 'react'
import { toast } from 'sonner'

import { Button } from '@evobgp/ui/components/button'
import { Checkbox } from '@evobgp/ui/components/checkbox'
import { Input } from '@evobgp/ui/components/input'
import { Label } from '@evobgp/ui/components/label'

import { FormDrawer } from '@/components/form-drawer'
import { LoadingButton } from '@/components/loading-button'
import { CommunitySelect } from '@/components/modules/community-select'
import { SelectField } from '@/components/select-field'
import {
  dohProfileShortLabel,
  moduleDohProfileIds,
} from '@/lib/modules/helpers'
import { dohPolicyRu, moduleTypeRu } from '@/lib/ui-labels'
import { useUpdateModuleMutation } from '@/queries/modules'
import type {
  BgpCommunity,
  DohProfile,
  DohResolverPolicy,
  ModulePatch,
  ModuleRow,
} from '@/types/api'

interface ModuleEditDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  mod: ModuleRow
  communities: BgpCommunity[]
  dohProfiles: DohProfile[]
}

const DOH_POLICY_ITEMS: { value: DohResolverPolicy; label: string }[] = [
  { value: 'primary_only', label: dohPolicyRu('primary_only') },
  { value: 'failover', label: dohPolicyRu('failover') },
  { value: 'union', label: dohPolicyRu('union') },
]

export function ModuleEditDialog({
  open,
  onOpenChange,
  mod,
  communities,
  dohProfiles,
}: ModuleEditDialogProps) {
  const updateMutation = useUpdateModuleMutation()
  const isDomains = mod.type === 'DOMAINS'

  const [name, setName] = useState('')
  const [enabled, setEnabled] = useState(true)
  const [priority, setPriority] = useState('0')
  const [refreshIntervalSec, setRefreshIntervalSec] = useState('')
  const [cronExpr, setCronExpr] = useState('')
  const [defaultCommunityId, setDefaultCommunityId] = useState<string | null>(null)
  const [dohResolverPolicy, setDohResolverPolicy] = useState<DohResolverPolicy>('primary_only')
  const [dohProfileIds, setDohProfileIds] = useState<string[]>([])

  useEffect(() => {
    if (!open) return
    setName(mod.name ?? '')
    setEnabled(mod.enabled !== false)
    setPriority(String(mod.priority ?? 0))
    setRefreshIntervalSec(
      mod.refresh_interval_sec === null || mod.refresh_interval_sec === undefined
        ? ''
        : String(mod.refresh_interval_sec),
    )
    setCronExpr(mod.cron_expr ?? '')
    setDefaultCommunityId(mod.default_community_id ?? null)
    setDohResolverPolicy(mod.doh_resolver_policy ?? 'primary_only')
    setDohProfileIds(moduleDohProfileIds(mod))
  }, [mod, open])

  function toggleDohProfile(id: string, checked: boolean) {
    setDohProfileIds((prev) => {
      if (checked) {
        if (prev.includes(id)) return prev
        return [...prev, id]
      }
      return prev.filter((x) => x !== id)
    })
  }

  async function save() {
    const trimmedName = name.trim()
    if (!trimmedName) {
      toast.error('Укажите название модуля')
      return
    }

    const priorityNum = Number(priority)
    if (!Number.isFinite(priorityNum) || !Number.isInteger(priorityNum)) {
      toast.error('Приоритет должен быть целым числом')
      return
    }

    let refresh: number | null = null
    if (refreshIntervalSec.trim() !== '') {
      const n = Number(refreshIntervalSec)
      if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
        toast.error('Интервал обновления должен быть целым числом ≥ 0')
        return
      }
      refresh = n
    }

    const body: ModulePatch = {
      name: trimmedName,
      enabled,
      priority: priorityNum,
      refresh_interval_sec: refresh,
      cron_expr: cronExpr.trim() || null,
      default_community_id: defaultCommunityId,
    }

    if (isDomains) {
      body.doh_resolver_policy = dohResolverPolicy
      body.doh_profile_ids = dohProfileIds
    }

    try {
      await updateMutation.mutateAsync({ id: mod.id, body })
      onOpenChange(false)
    } catch {
      // toast in mutation
    }
  }

  return (
    <FormDrawer
      open={open}
      onOpenChange={onOpenChange}
      title="Редактировать модуль"
      description={`${moduleTypeRu(mod.type)} · ${mod.type}`}
      className="sm:max-w-md"
      footer={
        <>
          <Button variant="outline" type="button" onClick={() => onOpenChange(false)}>
            Отмена
          </Button>
          <LoadingButton type="button" loading={updateMutation.isPending} onClick={() => void save()}>
            Сохранить
          </LoadingButton>
        </>
      }
    >
      <div className="flex flex-col gap-2">
        <Label htmlFor="mod-name">Название</Label>
        <Input
          id="mod-name"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Имя модуля"
        />
      </div>

      <div className="flex flex-row items-center justify-between gap-4 rounded-lg border border-border bg-muted/30 p-3">
        <div className="grid min-w-0 flex-1 gap-1 pr-2">
          <Label htmlFor="mod-enabled">Включён</Label>
          <p className="text-xs text-muted-foreground">
            Выключенный модуль не участвует в обновлении и применении.
          </p>
        </div>
        <Checkbox
          id="mod-enabled"
          checked={enabled}
          onCheckedChange={(v) => setEnabled(v === true)}
        />
      </div>

      <div className="flex flex-col gap-2">
        <Label htmlFor="mod-priority">Приоритет</Label>
        <Input
          id="mod-priority"
          type="number"
          value={priority}
          onChange={(e) => setPriority(e.target.value)}
        />
      </div>

      <div className="flex flex-col gap-2">
        <Label htmlFor="mod-interval">Интервал обновления (сек)</Label>
        <Input
          id="mod-interval"
          type="number"
          min={0}
          placeholder="пусто = по умолчанию"
          value={refreshIntervalSec}
          onChange={(e) => setRefreshIntervalSec(e.target.value)}
        />
      </div>

      <div className="flex flex-col gap-2">
        <Label htmlFor="mod-cron">Cron (опционально)</Label>
        <Input
          id="mod-cron"
          placeholder="0 * * * *"
          value={cronExpr}
          onChange={(e) => setCronExpr(e.target.value)}
        />
      </div>

      <CommunitySelect
        id="mod-community"
        label="Community по умолчанию"
        value={defaultCommunityId}
        onValueChange={setDefaultCommunityId}
        communities={communities}
        nullable
      />

      {isDomains ? (
        <>
          <SelectField
            id="mod-doh-policy"
            label="Политика DoH"
            items={DOH_POLICY_ITEMS}
            value={dohResolverPolicy}
            onValueChange={(v) => setDohResolverPolicy(v as DohResolverPolicy)}
          />

          <div className="flex flex-col gap-2">
            <Label>DoH профили</Label>
            {dohProfiles.length === 0 ? (
              <p className="text-muted-foreground text-sm">Нет профилей в справочнике</p>
            ) : (
              <div className="flex flex-col gap-2 rounded-lg border border-border p-3">
                {dohProfiles.map((p) => {
                  const checked = dohProfileIds.includes(p.id)
                  return (
                    <label
                      key={p.id}
                      htmlFor={`mod-doh-${p.id}`}
                      className="flex cursor-pointer items-start gap-3"
                    >
                      <Checkbox
                        id={`mod-doh-${p.id}`}
                        checked={checked}
                        onCheckedChange={(v) => toggleDohProfile(p.id, v === true)}
                        className="mt-0.5"
                      />
                      <span className="flex min-w-0 flex-col gap-0.5">
                        <span className="text-sm font-medium">{dohProfileShortLabel(p.id, dohProfiles)}</span>
                        <span className="text-muted-foreground truncate text-xs" title={p.url}>
                          {p.url}
                        </span>
                      </span>
                    </label>
                  )
                })}
              </div>
            )}
          </div>
        </>
      ) : null}
    </FormDrawer>
  )
}
