import { useState, useEffect, Dispatch, SetStateAction } from 'react'
import { useParams, Link } from 'react-router-dom'
import Layout from '../components/Layout'
import DataTable, { Column } from '../components/DataTable'
import EntityForm, { FieldDef } from '../components/EntityForm'
import GenerateModal from '../components/GenerateModal'
import Box from '@mui/material/Box'
import Button from '@mui/material/Button'
import Tabs from '@mui/material/Tabs'
import Tab from '@mui/material/Tab'
import Typography from '@mui/material/Typography'
import Breadcrumbs from '@mui/material/Breadcrumbs'
import AddIcon from '@mui/icons-material/Add'
import BuildIcon from '@mui/icons-material/Build'
import { zonesApi, interfacesApi, policiesApi, rulesApi, snatApi, hostsApi, paramsApi, configsApi } from '../api'

// ---- Types ----
interface Zone { id: number; name: string; type: string; options: string }
interface Iface { id: number; name: string; zone_id: number; options: string }
interface Policy { id: number; src_zone_id: number; dst_zone_id: number; policy: string; log_level: string; comment: string; position: number }
interface Rule { id: number; action: string; src_zone_id: number | null; dst_zone_id: number | null; src_ip: string; dst_ip: string; proto: string; dport: string; sport: string; comment: string; position: number }
interface Snat { id: number; source_network: string; out_interface: string; to_address: string; comment: string }
interface Host { id: number; zone_id: number; interface: string; subnet: string; options: string }
interface Param { id: number; name: string; value: string }

type AnyEntity = { id: number } & Record<string, unknown>

export default function ConfigDetail() {
  const { id } = useParams<{ id: string }>()
  const configId = Number(id)

  const [configName, setConfigName] = useState('')
  const [tab, setTab] = useState(0)
  const [zones, setZones] = useState<Zone[]>([])
  const [interfaces, setInterfaces] = useState<Iface[]>([])
  const [policies, setPolicies] = useState<Policy[]>([])
  const [rules, setRules] = useState<Rule[]>([])
  const [snat, setSnat] = useState<Snat[]>([])
  const [hosts, setHosts] = useState<Host[]>([])
  const [paramsList, setParamsList] = useState<Param[]>([])
  const [formOpen, setFormOpen] = useState(false)
  const [editing, setEditing] = useState<AnyEntity | null>(null)
  const [generateOpen, setGenerateOpen] = useState(false)

  useEffect(() => {
    configsApi.get(configId).then((r) => setConfigName(r.data.name))
    zonesApi.list(configId).then((r) => setZones(r.data))
    interfacesApi.list(configId).then((r) => setInterfaces(r.data))
    policiesApi.list(configId).then((r) => setPolicies(r.data))
    rulesApi.list(configId).then((r) => setRules(r.data))
    snatApi.list(configId).then((r) => setSnat(r.data))
    hostsApi.list(configId).then((r) => setHosts(r.data))
    paramsApi.list(configId).then((r) => setParamsList(r.data))
  }, [configId])

  const zoneOptions = zones.map((z) => ({ value: z.id, label: z.name }))

  // ---- Tab configs ----
  const tabConfig = [
    {
      label: 'Zones',
      rows: zones as unknown as AnyEntity[],
      setRows: setZones as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: zonesApi,
      columns: [
        { key: 'name' as const, label: 'Name' },
        { key: 'type' as const, label: 'Type' },
        { key: 'options' as const, label: 'Options' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'name', label: 'Name', required: true },
        { name: 'type', label: 'Type', required: true, type: 'select' as const, options: [{ value: 'ipv4', label: 'ipv4' }, { value: 'ipv6', label: 'ipv6' }, { value: 'firewall', label: 'firewall' }] },
        { name: 'options', label: 'Options' },
      ] as FieldDef[],
    },
    {
      label: 'Interfaces',
      rows: interfaces as unknown as AnyEntity[],
      setRows: setInterfaces as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: interfacesApi,
      columns: [
        { key: 'name' as const, label: 'Interface' },
        {
          key: 'zone_id' as const,
          label: 'Zone',
          render: (r: AnyEntity) => r['zone_id'] == null ? '-' : (zones.find((z) => z.id === r['zone_id'])?.name ?? String(r['zone_id'])),
        },
        { key: 'broadcast' as const, label: 'Broadcast' },
        { key: 'options' as const, label: 'Options' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'name', label: 'Interface Name', required: true },
        { name: 'zone_id', label: 'Zone', type: 'select' as const, options: [{ value: '', label: '- (no zone)' }, ...zoneOptions] },
        { name: 'broadcast', label: 'Broadcast' },
        { name: 'options', label: 'Options' },
      ] as FieldDef[],
    },
    {
      label: 'Policies',
      rows: policies as unknown as AnyEntity[],
      setRows: setPolicies as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: policiesApi,
      columns: [
        {
          key: 'src_zone_id' as const,
          label: 'Source',
          render: (r: AnyEntity) => zones.find((z) => z.id === r['src_zone_id'])?.name ?? String(r['src_zone_id']),
        },
        {
          key: 'dst_zone_id' as const,
          label: 'Destination',
          render: (r: AnyEntity) => zones.find((z) => z.id === r['dst_zone_id'])?.name ?? String(r['dst_zone_id']),
        },
        { key: 'policy' as const, label: 'Policy' },
        { key: 'log_level' as const, label: 'Log Level' },
        { key: 'position' as const, label: 'Position' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'src_zone_id', label: 'Source Zone', required: true, type: 'select' as const, options: zoneOptions },
        { name: 'dst_zone_id', label: 'Destination Zone', required: true, type: 'select' as const, options: zoneOptions },
        { name: 'policy', label: 'Policy', required: true, type: 'select' as const, options: [{ value: 'ACCEPT', label: 'ACCEPT' }, { value: 'DROP', label: 'DROP' }, { value: 'REJECT', label: 'REJECT' }, { value: 'CONTINUE', label: 'CONTINUE' }] },
        { name: 'log_level', label: 'Log Level' },
        { name: 'comment', label: 'Comment' },
        { name: 'position', label: 'Position', type: 'number' as const },
      ] as FieldDef[],
    },
    {
      label: 'Rules',
      rows: rules as unknown as AnyEntity[],
      setRows: setRules as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: rulesApi,
      columns: [
        { key: 'action' as const, label: 'Action' },
        {
          key: 'src_zone_id' as const,
          label: 'Source',
          render: (r: AnyEntity) => r['src_zone_id'] ? (zones.find((z) => z.id === r['src_zone_id'])?.name ?? String(r['src_zone_id'])) : 'all',
        },
        {
          key: 'dst_zone_id' as const,
          label: 'Destination',
          render: (r: AnyEntity) => r['dst_zone_id'] ? (zones.find((z) => z.id === r['dst_zone_id'])?.name ?? String(r['dst_zone_id'])) : 'all',
        },
        { key: 'proto' as const, label: 'Proto' },
        { key: 'dport' as const, label: 'DPort' },
        { key: 'position' as const, label: 'Position' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'action', label: 'Action', required: true },
        { name: 'src_zone_id', label: 'Source Zone', type: 'select' as const, options: zoneOptions },
        { name: 'dst_zone_id', label: 'Dest Zone', type: 'select' as const, options: zoneOptions },
        { name: 'src_ip', label: 'Source IP/CIDR' },
        { name: 'dst_ip', label: 'Dest IP/CIDR' },
        { name: 'proto', label: 'Protocol' },
        { name: 'dport', label: 'Dest Port' },
        { name: 'sport', label: 'Source Port' },
        { name: 'comment', label: 'Comment' },
        { name: 'position', label: 'Position', type: 'number' as const },
      ] as FieldDef[],
    },
    {
      label: 'SNAT',
      rows: snat as unknown as AnyEntity[],
      setRows: setSnat as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: snatApi,
      columns: [
        { key: 'out_interface' as const, label: 'Out Interface' },
        { key: 'source_network' as const, label: 'Source Network' },
        { key: 'to_address' as const, label: 'To Address' },
        { key: 'comment' as const, label: 'Comment' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'out_interface', label: 'Out Interface', required: true },
        { name: 'source_network', label: 'Source Network', required: true },
        { name: 'to_address', label: 'To Address' },
        { name: 'comment', label: 'Comment' },
      ] as FieldDef[],
    },
    {
      label: 'Hosts',
      rows: hosts as unknown as AnyEntity[],
      setRows: setHosts as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: hostsApi,
      columns: [
        { key: 'zone_id' as const, label: 'Zone' },
        { key: 'interface' as const, label: 'Interface' },
        { key: 'subnet' as const, label: 'Subnet' },
        { key: 'options' as const, label: 'Options' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'zone_id', label: 'Zone', type: 'select' as const, options: zoneOptions, required: true },
        { name: 'interface', label: 'Interface', required: true },
        { name: 'subnet', label: 'Subnet', required: true },
        { name: 'options', label: 'Options' },
      ] as FieldDef[],
    },
    {
      label: 'Params',
      rows: paramsList as unknown as AnyEntity[],
      setRows: setParamsList as unknown as Dispatch<SetStateAction<AnyEntity[]>>,
      api: paramsApi,
      columns: [
        { key: 'name' as const, label: 'Name' },
        { key: 'value' as const, label: 'Value' },
      ] as Column<AnyEntity>[],
      fields: [
        { name: 'name', label: 'Name', required: true },
        { name: 'value', label: 'Value', required: true },
      ] as FieldDef[],
    },
  ]

  const current = tabConfig[tab]

  const handleSubmit = async (values: Record<string, unknown>) => {
    if (editing) {
      await current.api.update(configId, editing.id, values)
    } else {
      await current.api.create(configId, values)
    }
    const res = await current.api.list(configId)
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    current.setRows(res.data as any)
    setFormOpen(false)
    setEditing(null)
  }

  const handleDelete = async (row: AnyEntity) => {
    if (!confirm('Delete this entry?')) return
    await current.api.delete(configId, row.id)
    const res = await current.api.list(configId)
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    current.setRows(res.data as any)
  }

  return (
    <Layout title={configName || 'Config Detail'}>
      <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
        <Breadcrumbs>
          <Link to="/configs" style={{ color: 'inherit', textDecoration: 'none' }}>
            <Typography variant="body2" color="text.secondary">Configurations</Typography>
          </Link>
          <Typography variant="body2">{configName}</Typography>
        </Breadcrumbs>
        <Button variant="contained" startIcon={<BuildIcon />} onClick={() => setGenerateOpen(true)}>
          Generate Config
        </Button>
      </Box>

      <Box sx={{ bgcolor: 'white', borderRadius: 2, border: '1px solid #e2e8f0', overflow: 'hidden' }}>
        <Tabs value={tab} onChange={(_, v) => setTab(v)} sx={{ borderBottom: 1, borderColor: 'divider', px: 2 }}>
          {tabConfig.map((tc) => <Tab key={tc.label} label={tc.label} />)}
        </Tabs>
        <Box sx={{ p: 3 }}>
          <Box sx={{ display: 'flex', justifyContent: 'flex-end', mb: 2 }}>
            <Button size="small" variant="outlined" startIcon={<AddIcon />} onClick={() => { setEditing(null); setFormOpen(true) }}>
              Add {current.label.replace('/NAT', '')}
            </Button>
          </Box>
          <DataTable
            columns={current.columns}
            rows={current.rows}
            onEdit={(row) => { setEditing(row); setFormOpen(true) }}
            onDelete={handleDelete}
          />
        </Box>
      </Box>

      <EntityForm
        open={formOpen}
        title={`${editing ? 'Edit' : 'Add'} ${current.label}`}
        fields={current.fields}
        initialValues={editing ?? undefined}
        onClose={() => { setFormOpen(false); setEditing(null) }}
        onSubmit={handleSubmit}
      />

      <GenerateModal
        open={generateOpen}
        configId={configId}
        configName={configName}
        onClose={() => setGenerateOpen(false)}
      />
    </Layout>
  )
}
