import { useState } from 'react'
import {
  Alert, Button, Card, Form, Input, InputNumber, Modal, Popconfirm, Select, Space, Switch, Table, Tag, Tooltip, Typography, message,
} from 'antd'
import type { ColumnsType } from 'antd/es/table'
import {
  ExperimentOutlined, PlusOutlined,
} from '@ant-design/icons'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useTranslation } from 'react-i18next'
import dayjs from 'dayjs'

import apiClient, { isEnvelope } from '../../api/client'

const { Text } = Typography

interface RemoteTarget {
  id: number
  name: string
  kind: 's3' | 'sftp'
  target_url: string
  settings: Record<string, unknown>
  active: boolean
  last_upload_at?: string
  last_error?: string
}

interface FormValues {
  name: string
  kind: 's3' | 'sftp'
  target_url: string
  active: boolean
  // S3
  endpoint?: string
  region?: string
  bucket?: string
  access_key?: string
  secret_key?: string
  path_prefix?: string
  use_ssl?: boolean
  // SFTP
  host?: string
  port?: number
  username?: string
  password?: string
  private_key?: string
  remote_dir?: string
  host_key_fingerprint?: string
}

function buildPayload(v: FormValues): RemoteTarget {
  const settings: Record<string, unknown> = {}
  if (v.kind === 's3') {
    if (v.endpoint)    settings.endpoint    = v.endpoint
    if (v.region)      settings.region      = v.region
    if (v.bucket)      settings.bucket      = v.bucket
    if (v.access_key)  settings.access_key  = v.access_key
    if (v.secret_key && v.secret_key !== '***SET***') settings.secret_key  = v.secret_key
    else if (v.secret_key === '***SET***')            settings.secret_key  = '***SET***'
    if (v.path_prefix) settings.path_prefix = v.path_prefix
    settings.use_ssl = !!v.use_ssl
  } else {
    if (v.host)      settings.host      = v.host
    if (v.port)      settings.port      = v.port
    if (v.username)  settings.username  = v.username
    if (v.password && v.password !== '***SET***')       settings.password    = v.password
    else if (v.password === '***SET***')                settings.password    = '***SET***'
    if (v.private_key && v.private_key !== '***SET***') settings.private_key = v.private_key
    else if (v.private_key === '***SET***')             settings.private_key = '***SET***'
    if (v.remote_dir)            settings.remote_dir            = v.remote_dir
    if (v.host_key_fingerprint)  settings.host_key_fingerprint  = v.host_key_fingerprint
  }
  return {
    id: 0,
    name: v.name,
    kind: v.kind,
    target_url: v.target_url,
    settings,
    active: v.active,
  }
}

export default function RemoteTargetsTab() {
  const { t } = useTranslation()
  const qc = useQueryClient()
  const [msg, msgCtx] = message.useMessage()

  const list = useQuery({
    queryKey: ['backup-remotes'],
    queryFn: async () => {
      const r = await apiClient.get('/backup-remotes')
      return isEnvelope(r.data) ? (r.data.data as { remotes: RemoteTarget[] }).remotes : []
    },
  })

  const [edit, setEdit] = useState<RemoteTarget | null>(null)
  const [creating, setCreating] = useState(false)
  const [form] = Form.useForm<FormValues>()
  const kind = Form.useWatch('kind', form)

  const create = useMutation({
    mutationFn: async (v: FormValues) => { await apiClient.post('/backup-remotes', buildPayload(v)) },
    onSuccess: () => {
      msg.success(t('common.save')); setCreating(false); form.resetFields()
      qc.invalidateQueries({ queryKey: ['backup-remotes'] })
    },
    onError: (e: Error) => msg.error(e.message),
  })
  const update = useMutation({
    mutationFn: async ({ id, v }: { id: number; v: FormValues }) => {
      await apiClient.put(`/backup-remotes/${id}`, buildPayload(v))
    },
    onSuccess: () => {
      msg.success(t('common.save')); setEdit(null); form.resetFields()
      qc.invalidateQueries({ queryKey: ['backup-remotes'] })
    },
    onError: (e: Error) => msg.error(e.message),
  })
  const del = useMutation({
    mutationFn: async (id: number) => { await apiClient.delete(`/backup-remotes/${id}`) },
    onSuccess: () => { qc.invalidateQueries({ queryKey: ['backup-remotes'] }) },
    onError: (e: Error) => msg.error(e.message),
  })
  const test = useMutation({
    mutationFn: async (id: number) => { await apiClient.post(`/backup-remotes/${id}/test`) },
    onSuccess: () => msg.success(t('remotes.testOk')),
    onError: (e: Error) => msg.error(t('remotes.testFailed') + ': ' + e.message),
  })

  const columns: ColumnsType<RemoteTarget> = [
    { title: t('remotes.col.name'), dataIndex: 'name' },
    {
      title: t('remotes.col.kind'), dataIndex: 'kind', width: 80,
      render: (v: string) =>
        <Tag color={v === 's3' ? 'blue' : 'purple'}>{v.toUpperCase()}</Tag>,
    },
    {
      title: t('remotes.col.target'), dataIndex: 'target_url',
      render: (v: string) =>
        <Text style={{ fontFamily: 'monospace', fontSize: 12 }}>{v}</Text>,
    },
    {
      title: t('remotes.col.lastUpload'), dataIndex: 'last_upload_at', width: 200,
      render: (v?: string, row?) => {
        if (!v) return <Text type="secondary">—</Text>
        const failed = !!row?.last_error
        return (
          <Space size={4}>
            <Text type={failed ? 'danger' : undefined} style={{ fontSize: 12 }}>
              {dayjs(v).format('YYYY-MM-DD HH:mm:ss')}
            </Text>
            {failed && <Tooltip title={row?.last_error}><Tag color="red">FAIL</Tag></Tooltip>}
          </Space>
        )
      },
    },
    {
      title: t('remotes.col.active'), dataIndex: 'active', width: 80,
      render: (v: boolean) => v ? <Tag color="green">an</Tag> : <Tag>aus</Tag>,
    },
    {
      title: t('common.actions'), key: 'a', width: 240,
      render: (_, r) => (
        <Space size={4}>
          <Button size="small" icon={<ExperimentOutlined />}
            loading={test.isPending}
            onClick={() => test.mutate(r.id)}>
            {t('remotes.test')}
          </Button>
          <Button size="small" onClick={() => {
            setEdit(r); form.resetFields()
            const settings = (r.settings ?? {}) as Record<string, unknown>
            form.setFieldsValue({
              name: r.name, kind: r.kind, target_url: r.target_url, active: r.active,
              endpoint:    settings.endpoint as string,
              region:      settings.region as string,
              bucket:      settings.bucket as string,
              access_key:  settings.access_key as string,
              secret_key:  settings.secret_key as string,
              path_prefix: settings.path_prefix as string,
              use_ssl:     settings.use_ssl as boolean,
              host:                  settings.host as string,
              port:                  settings.port as number,
              username:              settings.username as string,
              password:              settings.password as string,
              private_key:           settings.private_key as string,
              remote_dir:            settings.remote_dir as string,
              host_key_fingerprint:  settings.host_key_fingerprint as string,
            })
          }}>{t('common.edit')}</Button>
          <Popconfirm title={t('remotes.confirmDelete', { name: r.name })}
            onConfirm={() => del.mutate(r.id)}>
            <Button size="small" danger>{t('common.delete')}</Button>
          </Popconfirm>
        </Space>
      ),
    },
  ]

  return (
    <div>
      {msgCtx}
      <Alert
        type="info"
        showIcon
        className="mb-16"
        message={t('remotes.scopeTitle')}
        description={t('remotes.scopeDesc')}
      />
      <Card size="small" extra={
        <Button type="primary" size="small" icon={<PlusOutlined />}
          onClick={() => {
            setCreating(true); form.resetFields()
            form.setFieldsValue({ kind: 's3', active: true, use_ssl: true, port: 22 })
          }}>
          {t('remotes.add')}
        </Button>
      }>
        <Table size="small" rowKey="id" loading={list.isFetching}
          dataSource={list.data ?? []} columns={columns}
          pagination={false}
          locale={{ emptyText: t('remotes.empty') }} />
      </Card>

      <Modal
        title={edit ? t('remotes.editTitle') : t('remotes.addTitle')}
        open={edit !== null || creating}
        onCancel={() => { setEdit(null); setCreating(false); form.resetFields() }}
        onOk={() => form.submit()}
        confirmLoading={create.isPending || update.isPending}
        width={640}
      >
        <Form form={form} layout="vertical"
          onFinish={(v) => edit ? update.mutate({ id: edit.id, v }) : create.mutate(v)}>
          <Form.Item label={t('remotes.col.name')} name="name" rules={[{ required: true }]}>
            <Input placeholder="MinIO offsite / Hetzner Storage Box" />
          </Form.Item>
          <Form.Item label={t('remotes.col.kind')} name="kind" rules={[{ required: true }]}>
            <Select options={[
              { value: 's3',   label: 'S3 (AWS / MinIO / R2 / B2 / Hetzner Object)' },
              { value: 'sftp', label: 'SFTP (SSH)' },
            ]} />
          </Form.Item>
          <Form.Item label={t('remotes.col.target')} name="target_url" rules={[{ required: true }]}
            extra={t('remotes.targetExtra')}>
            <Input placeholder={kind === 's3' ? 's3://my-bucket' : 'sftp://backup@host.example.com'} />
          </Form.Item>

          {kind === 's3' && (
            <>
              <Form.Item label="Endpoint" name="endpoint" rules={[{ required: true }]}
                extra="s3.amazonaws.com / minio.example.com:9000 / fsn1.your-objectstorage.com">
                <Input />
              </Form.Item>
              <Form.Item label="Region" name="region">
                <Input placeholder="eu-central-1 / auto (R2)" />
              </Form.Item>
              <Form.Item label="Bucket" name="bucket" rules={[{ required: true }]}>
                <Input />
              </Form.Item>
              <Form.Item label="Access Key" name="access_key" rules={[{ required: true }]}>
                <Input autoComplete="off" />
              </Form.Item>
              <Form.Item label="Secret Key" name="secret_key" rules={[{ required: !edit }]}>
                <Input.Password autoComplete="new-password" />
              </Form.Item>
              <Form.Item label="Path Prefix" name="path_prefix"
                extra="z.B. edgeguard/utm-1 — wird vor jedem Filename gesetzt">
                <Input />
              </Form.Item>
              <Form.Item label="HTTPS (use_ssl)" name="use_ssl" valuePropName="checked">
                <Switch />
              </Form.Item>
            </>
          )}

          {kind === 'sftp' && (
            <>
              <Form.Item label="Host" name="host" rules={[{ required: true }]}>
                <Input placeholder="backup.example.com" />
              </Form.Item>
              <Form.Item label="Port" name="port" rules={[{ required: true }]}>
                <InputNumber min={1} max={65535} style={{ width: '100%' }} />
              </Form.Item>
              <Form.Item label="Username" name="username" rules={[{ required: true }]}>
                <Input autoComplete="off" />
              </Form.Item>
              <Form.Item label="Password" name="password"
                extra="Entweder Password ODER Private-Key.">
                <Input.Password autoComplete="new-password" />
              </Form.Item>
              <Form.Item label="Private Key (OpenSSH, base64)" name="private_key">
                <Input.TextArea rows={3} autoComplete="off"
                  placeholder="base64-encoded OpenSSH private key" />
              </Form.Item>
              <Form.Item label="Remote Dir" name="remote_dir" rules={[{ required: true }]}
                extra="z.B. /backups/edgeguard">
                <Input />
              </Form.Item>
              <Form.Item label="Host-Key-Fingerprint" name="host_key_fingerprint"
                extra="optional, SHA256:... — wenn leer wird TOFU verwendet (unsicher gegen MitM)">
                <Input placeholder="SHA256:abc123..." />
              </Form.Item>
            </>
          )}

          <Form.Item label={t('remotes.col.active')} name="active" valuePropName="checked">
            <Switch />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  )
}
