import { useState } from 'react';
import { NavLink } from 'react-router';
import { Card, CardHeader, CardTitle, CardContent } from './ui/card';
import { Button } from './ui/button';
import { Input, Label } from './ui';
import { Textarea } from './ui/textarea';
import { Alert, AlertDescription } from './ui/alert';
import {
  Router, Globe, Loader2, AlertCircle, CheckCircle, XCircle,
  Play, RotateCw, Copy, ChevronDown, ChevronUp, Edit2,
  RefreshCw, ExternalLink, TestTube2,
} from 'lucide-react';
import { Badge } from './ui/badge';
import { useConfig } from '../hooks';
import { useCloudflare } from '../hooks/useCloudflare';
import { useDnsmasq } from '../hooks/useDnsmasq';
import { useDdns } from '../hooks/useDdns';
import { apiService } from '../services/api-legacy';
import type { DdnsRecordStatus } from '../services/api/networking';

export function DnsComponent() {
  const { config: globalConfig, updateConfig, isUpdating } = useConfig();

  // ── LAN DNS (dnsmasq) ──
  const {
    status: dnsStatus,
    isLoadingStatus: isDnsStatusLoading,
    config: dnsConfig,
    fetchConfig: fetchDnsConfig,
    generateConfig: generateDnsConfig,
    isGenerating: isDnsGenerating,
    generateData: dnsGenerateData,
    restart: restartDns,
    isRestarting: isDnsRestarting,
    restartData: dnsRestartData,
    generateError: dnsGenerateError,
    restartError: dnsRestartError,
  } = useDnsmasq();

  const [showDnsAdvanced, setShowDnsAdvanced] = useState(false);
  const [editedDnsConfig, setEditedDnsConfig] = useState('');
  const [originalDnsConfig, setOriginalDnsConfig] = useState('');
  const [copiedDnsIp, setCopiedDnsIp] = useState(false);

  const isDnsRunning = dnsStatus?.status === 'active';
  const dnsIp = dnsStatus?.ip;

  const handleCopyDnsIp = () => {
    if (dnsIp) {
      navigator.clipboard.writeText(dnsIp);
      setCopiedDnsIp(true);
      setTimeout(() => setCopiedDnsIp(false), 2000);
    }
  };

  const handleShowDnsAdvanced = async () => {
    if (!showDnsAdvanced) {
      const result = await fetchDnsConfig();
      const content = result.data?.content || dnsConfig?.content || '';
      setEditedDnsConfig(content);
      setOriginalDnsConfig(content);
    }
    setShowDnsAdvanced(!showDnsAdvanced);
  };

  const handleSaveDnsConfig = async () => {
    try {
      await apiService.writeDnsmasqConfig(editedDnsConfig);
      fetchDnsConfig();
    } catch (error) {
      console.error('Failed to save config:', error);
    }
  };

  const handleSaveAndRestartDns = async () => {
    try {
      await apiService.writeDnsmasqConfig(editedDnsConfig);
      await apiService.restartDnsmasq();
      fetchDnsConfig();
    } catch (error) {
      console.error('Failed to save config and restart:', error);
    }
  };

  // ── Dynamic DNS ──
  const { status: ddnsStatus, isLoadingStatus: isDdnsLoading, trigger: triggerDdns, isTriggering: isDdnsTriggering } = useDdns();
  const { verification: cfVerification } = useCloudflare();

  const [editingDdnsConfig, setEditingDdnsConfig] = useState(false);
  const [ddnsConfigForm, setDdnsConfigForm] = useState({ enabled: false, records: '', intervalMinutes: 5 });

  const handleDdnsConfigEdit = () => {
    setDdnsConfigForm({
      enabled: globalConfig?.cloud?.ddns?.enabled ?? false,
      records: (globalConfig?.cloud?.ddns?.records ?? []).join('\n'),
      intervalMinutes: globalConfig?.cloud?.ddns?.intervalMinutes ?? 5,
    });
    setEditingDdnsConfig(true);
  };

  const handleDdnsConfigSave = async () => {
    if (!globalConfig) return;
    const records = ddnsConfigForm.records.split('\n').map(r => r.trim()).filter(Boolean);
    await updateConfig({
      ...globalConfig,
      cloud: {
        ...globalConfig.cloud,
        ddns: {
          enabled: ddnsConfigForm.enabled,
          provider: 'cloudflare',
          records,
          intervalMinutes: ddnsConfigForm.intervalMinutes,
        },
      },
    });
    setEditingDdnsConfig(false);
  };

  // ── DNS Lookup ──
  const [lookupDomain, setLookupDomain] = useState('');
  const [lookupTesting, setLookupTesting] = useState<'external' | 'internal' | null>(null);
  const [lookupResult, setLookupResult] = useState<{ type: string; success: boolean; message: string } | null>(null);

  const handleLookup = async (type: 'external' | 'internal') => {
    const domain = lookupDomain.trim();
    if (!domain) return;
    setLookupTesting(type);
    setLookupResult(null);
    try {
      if (type === 'external') {
        const response = await fetch(`https://cloudflare-dns.com/dns-query?name=${domain}&type=A`, {
          headers: { accept: 'application/dns-json' },
        });
        const data = await response.json();
        if (data.Status === 0 && data.Answer?.length > 0) {
          const aRecord = data.Answer.find((a: { type: number; data: string }) => a.type === 1);
          const ip = aRecord ? aRecord.data : data.Answer[data.Answer.length - 1].data;
          setLookupResult({ type: 'External', success: true, message: `Resolves to ${ip}` });
        } else {
          setLookupResult({ type: 'External', success: false, message: 'No public DNS record found' });
        }
      } else {
        const response = await fetch(`/api/v1/network/resolve?domain=${domain}`);
        const data = await response.json();
        if (data.success && data.ip) {
          setLookupResult({ type: 'LAN', success: true, message: `Resolves to ${data.ip}` });
        } else {
          setLookupResult({ type: 'LAN', success: false, message: data.error || 'Not resolved on LAN' });
        }
      }
    } catch {
      setLookupResult({ type: type === 'external' ? 'External' : 'LAN', success: false, message: 'Lookup failed' });
    } finally {
      setLookupTesting(null);
    }
  };

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-4">
        <div className="p-2 bg-primary/10 rounded-lg">
          <Globe className="h-6 w-6 text-primary" />
        </div>
        <div>
          <h2 className="text-2xl font-semibold">DNS</h2>
          <p className="text-muted-foreground">LAN name resolution and public DNS record management</p>
        </div>
      </div>

      {/* ── LAN DNS ── */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <Router className="h-5 w-5 text-muted-foreground" />
              <CardTitle>LAN DNS</CardTitle>
            </div>
            <Badge variant={isDnsRunning ? 'success' : 'warning'} className="gap-1">
              {isDnsStatusLoading ? (
                <Loader2 className="h-3 w-3 animate-spin" />
              ) : isDnsRunning ? (
                <CheckCircle className="h-3 w-3" />
              ) : null}
              {isDnsStatusLoading ? 'Checking...' : isDnsRunning ? 'Running' : 'Stopped'}
            </Badge>
          </div>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="flex items-center justify-between p-3 bg-muted/30 rounded-lg">
            <div>
              <div className="text-xs text-muted-foreground mb-0.5">Set as primary DNS in your router</div>
              <code className="text-lg font-mono font-bold">{dnsIp || 'Auto-detecting...'}</code>
            </div>
            <Button variant="outline" size="sm" onClick={handleCopyDnsIp} disabled={!dnsIp} className="gap-2">
              <Copy className="h-4 w-4" />
              {copiedDnsIp ? 'Copied!' : 'Copy'}
            </Button>
          </div>

          {globalConfig?.cloud?.router?.ip && (
            <div className="flex items-center justify-between text-sm">
              <span className="text-muted-foreground">
                Router: <span className="font-mono">{globalConfig.cloud.router.ip}</span>
              </span>
              <Button
                variant="ghost"
                size="sm"
                onClick={() => window.open(`http://${globalConfig?.cloud?.router?.ip}`, '_blank')}
                className="gap-1 text-xs"
              >
                <ExternalLink className="h-3 w-3" />
                Open Admin
              </Button>
            </div>
          )}

          <div className="flex gap-2">
            {!isDnsRunning ? (
              <Button onClick={() => generateDnsConfig(true)} disabled={isDnsGenerating} className="gap-2">
                {isDnsGenerating ? <Loader2 className="h-4 w-4 animate-spin" /> : <Play className="h-4 w-4" />}
                Start DNS
              </Button>
            ) : (
              <Button onClick={() => restartDns()} disabled={isDnsRestarting} variant="outline" className="gap-2">
                {isDnsRestarting ? <Loader2 className="h-4 w-4 animate-spin" /> : <RotateCw className="h-4 w-4" />}
                Restart
              </Button>
            )}
            <Button onClick={handleShowDnsAdvanced} variant="outline" className="gap-2">
              {showDnsAdvanced ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
              Advanced
            </Button>
          </div>

          {(dnsGenerateData || dnsRestartData) && (
            <Alert>
              <CheckCircle className="h-4 w-4" />
              <AlertDescription>{dnsGenerateData?.message || dnsRestartData?.message}</AlertDescription>
            </Alert>
          )}
          {(dnsGenerateError || dnsRestartError) && (
            <Alert variant="error">
              <AlertCircle className="h-4 w-4" />
              <AlertDescription>{(dnsGenerateError || dnsRestartError)?.toString()}</AlertDescription>
            </Alert>
          )}

          {showDnsAdvanced && (
            <div className="border-t pt-4 space-y-3">
              <span className="text-sm font-medium">Config file</span>
              <Textarea
                value={editedDnsConfig}
                onChange={(e) => setEditedDnsConfig(e.target.value)}
                className="font-mono text-xs min-h-[300px]"
                placeholder="# dnsmasq configuration"
              />
              <div className="flex gap-2">
                <Button variant="outline" size="sm" onClick={handleSaveDnsConfig} className="gap-2">
                  Save
                </Button>
                <Button size="sm" onClick={handleSaveAndRestartDns} className="gap-2">
                  Save & Restart
                </Button>
                <Button variant="ghost" size="sm" onClick={() => setEditedDnsConfig(originalDnsConfig)} disabled={editedDnsConfig === originalDnsConfig} className="gap-2">
                  Reset
                </Button>
              </div>
            </div>
          )}
        </CardContent>
      </Card>

      {/* ── Dynamic DNS ── */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <Globe className="h-5 w-5 text-muted-foreground" />
              <CardTitle>Dynamic DNS</CardTitle>
            </div>
            {isDdnsLoading ? (
              <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
            ) : ddnsStatus?.enabled ? (
              <Badge variant="success" className="gap-1">
                <CheckCircle className="h-3 w-3" />
                Active
              </Badge>
            ) : (
              <Badge variant="secondary">Disabled</Badge>
            )}
          </div>
        </CardHeader>
        <CardContent className="space-y-4">
          {ddnsStatus?.enabled && (
            <div className="space-y-3">
              <div className="grid grid-cols-2 gap-4 text-sm">
                <div>
                  <span className="text-muted-foreground">Public IP</span>
                  <div className="font-mono font-medium mt-0.5">{ddnsStatus.currentIP || '—'}</div>
                </div>
                <div>
                  <span className="text-muted-foreground">Last checked</span>
                  <div className="font-mono mt-0.5">
                    {ddnsStatus.lastChecked ? new Date(ddnsStatus.lastChecked).toLocaleTimeString() : '—'}
                  </div>
                </div>
              </div>
              {ddnsStatus.lastError && (
                <Alert variant="error">
                  <AlertCircle className="h-4 w-4" />
                  <AlertDescription className="text-xs">{ddnsStatus.lastError}</AlertDescription>
                </Alert>
              )}
              <Button
                variant="outline"
                size="sm"
                onClick={() => triggerDdns()}
                disabled={isDdnsTriggering}
                className="gap-2"
              >
                {isDdnsTriggering ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
                Check Now
              </Button>
            </div>
          )}

          <div className={ddnsStatus?.enabled ? 'border-t pt-4' : ''}>
            <div className="flex items-center justify-between mb-3">
              <span className="text-sm font-medium">A Records</span>
              {!editingDdnsConfig && (
                <Button variant="outline" size="sm" onClick={handleDdnsConfigEdit} className="gap-1">
                  <Edit2 className="h-3 w-3" />
                  Edit
                </Button>
              )}
            </div>
            {editingDdnsConfig ? (
              <div className="space-y-3">
                <div className="flex items-center gap-2">
                  <input
                    type="checkbox"
                    id="ddns-enabled"
                    checked={ddnsConfigForm.enabled}
                    onChange={e => setDdnsConfigForm(prev => ({ ...prev, enabled: e.target.checked }))}
                  />
                  <Label htmlFor="ddns-enabled">Enabled</Label>
                </div>
                <div>
                  <Label>Domains (one per line)</Label>
                  <Textarea
                    value={ddnsConfigForm.records}
                    onChange={e => setDdnsConfigForm(prev => ({ ...prev, records: e.target.value }))}
                    placeholder={'cloud.example.com\nexample.org'}
                    className="text-sm h-24 mt-1 font-mono"
                  />
                </div>
                <div>
                  <Label>Check interval (minutes)</Label>
                  <Input
                    type="number"
                    value={ddnsConfigForm.intervalMinutes}
                    onChange={e => setDdnsConfigForm(prev => ({ ...prev, intervalMinutes: parseInt(e.target.value) || 5 }))}
                    className="h-9 mt-1 w-24"
                    min={1}
                  />
                </div>
                <div className="flex gap-2">
                  <Button size="sm" onClick={handleDdnsConfigSave} disabled={isUpdating}>
                    {isUpdating ? <Loader2 className="h-3 w-3 animate-spin mr-1" /> : null}
                    Save
                  </Button>
                  <Button variant="outline" size="sm" onClick={() => setEditingDdnsConfig(false)}>Cancel</Button>
                </div>
              </div>
            ) : (
              <div className="space-y-1">
                {(globalConfig?.cloud?.ddns?.records ?? []).length > 0 ? (
                  <>
                    {(globalConfig?.cloud?.ddns?.records ?? []).map(r => {
                      const rs: DdnsRecordStatus | undefined = ddnsStatus?.records?.find(s => s.name === r);
                      return (
                        <div key={r} className="flex items-center gap-2 text-xs">
                          {rs?.ok ? (
                            <CheckCircle className="h-3.5 w-3.5 text-green-500 shrink-0" />
                          ) : rs && !rs.ok ? (
                            <XCircle className="h-3.5 w-3.5 text-red-500 shrink-0" />
                          ) : (
                            <div className="h-3.5 w-3.5 shrink-0" />
                          )}
                          <span className="font-mono bg-muted px-2 py-0.5 rounded">{r}</span>
                          {rs?.ok && rs.ip && <span className="text-muted-foreground font-mono">{rs.ip}</span>}
                          {rs && !rs.ok && rs.error && (
                            <span className="text-red-500 truncate" title={rs.error}>{rs.error}</span>
                          )}
                        </div>
                      );
                    })}
                    {(globalConfig?.cloud?.ddns?.intervalMinutes ?? 0) > 0 && (
                      <div className="text-muted-foreground text-xs pt-1">
                        Checks every {globalConfig!.cloud!.ddns!.intervalMinutes} min
                      </div>
                    )}
                  </>
                ) : (
                  <p className="text-xs text-muted-foreground">No records configured</p>
                )}
              </div>
            )}
          </div>

          {cfVerification && !cfVerification.tokenConfigured && (
            <div className="flex items-center gap-3 rounded-md border border-amber-300 bg-amber-50 dark:bg-amber-950/30 dark:border-amber-700 px-4 py-3 text-sm text-amber-800 dark:text-amber-300">
              <AlertCircle className="h-4 w-4 shrink-0" />
              <span>
                Cloudflare API token not configured. DDNS requires a valid token.{' '}
                <NavLink to="/central/cloudflare" className="underline font-medium">Configure token</NavLink>
              </span>
            </div>
          )}
        </CardContent>
      </Card>

      {/* ── DNS Lookup ── */}
      <Card>
        <CardHeader>
          <div className="flex items-center gap-3">
            <TestTube2 className="h-5 w-5 text-muted-foreground" />
            <CardTitle>DNS Lookup</CardTitle>
          </div>
        </CardHeader>
        <CardContent className="space-y-3">
          <div className="flex gap-2">
            <Input
              placeholder="cloud.example.com"
              value={lookupDomain}
              onChange={e => { setLookupDomain(e.target.value); setLookupResult(null); }}
              onKeyDown={e => e.key === 'Enter' && handleLookup('external')}
              className="font-mono text-sm"
            />
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleLookup('external')}
              disabled={!lookupDomain.trim() || !!lookupTesting}
              className="gap-1 shrink-0"
            >
              {lookupTesting === 'external' ? <Loader2 className="h-3 w-3 animate-spin" /> : <Globe className="h-3 w-3" />}
              External
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleLookup('internal')}
              disabled={!lookupDomain.trim() || !!lookupTesting}
              className="gap-1 shrink-0"
            >
              {lookupTesting === 'internal' ? <Loader2 className="h-3 w-3 animate-spin" /> : <Router className="h-3 w-3" />}
              LAN
            </Button>
          </div>
          {lookupResult && (
            <Alert className={lookupResult.success
              ? 'border-green-500 bg-green-50 dark:bg-green-950'
              : 'border-amber-500 bg-amber-50 dark:bg-amber-950'
            }>
              {lookupResult.success
                ? <CheckCircle className="h-4 w-4 text-green-600" />
                : <AlertCircle className="h-4 w-4 text-amber-600" />
              }
              <AlertDescription className={lookupResult.success
                ? 'text-green-800 dark:text-green-200'
                : 'text-amber-800 dark:text-amber-200'
              }>
                <span className="font-medium">{lookupResult.type}: </span>
                {lookupResult.message}
              </AlertDescription>
            </Alert>
          )}
        </CardContent>
      </Card>

    </div>
  );
}
