import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Shield, Loader2, Edit2, Plus, Trash2, Copy, Check, CheckCircle, RefreshCw, KeyRound, Play, ChevronDown, ChevronUp } from 'lucide-react';
import { QRCodeSVG } from 'qrcode.react';
import { Card, CardHeader, CardTitle, CardContent } from './ui/card';
import { Button } from './ui/button';
import { Input } from './ui/input';
import { Label } from './ui/label';
import { Badge } from './ui/badge';
import { Alert, AlertDescription } from './ui/alert';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from './ui/dialog';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetFooter } from './ui/sheet';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from './ui/alert-dialog';
import { useVpn } from '../hooks/useVpn';
import { vpnApi, type VpnPeer, type VpnPeerConfig } from '../services/api/vpn';

interface ConfigFormValues {
  enabled: boolean;
  listenPort: number;
  address: string;
  endpoint: string;
  dns: string;
  lanCIDR: string;
}

function CopyButton({ text }: { text: string }) {
  const [copied, setCopied] = useState(false);
  const handleCopy = async () => {
    await navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };
  return (
    <Button variant="ghost" size="sm" onClick={handleCopy} className="h-7 w-7 p-0">
      {copied ? <Check className="h-3.5 w-3.5 text-green-500" /> : <Copy className="h-3.5 w-3.5" />}
    </Button>
  );
}

export function VpnComponent() {
  const {
    status, isLoadingStatus,
    config, isLoadingConfig,
    peers, isLoadingPeers,
    updateConfig, isUpdatingConfig,
    generateKeypair, isGeneratingKeypair,
    apply, isApplying, applyError,
    addPeer, isAddingPeer, addPeerError,
    deletePeer,
  } = useVpn();

  const [editingConfig, setEditingConfig] = useState(false);
  const [confirmKeygen, setConfirmKeygen] = useState(false);
  const [addPeerOpen, setAddPeerOpen] = useState(false);
  const [newPeerName, setNewPeerName] = useState('');
  const [peerConfigModal, setPeerConfigModal] = useState<VpnPeerConfig | null>(null);
  const [loadingPeerConfig, setLoadingPeerConfig] = useState<string | null>(null);
  const [deleteConfirmPeer, setDeleteConfirmPeer] = useState<VpnPeer | null>(null);
  const [showAdvanced, setShowAdvanced] = useState(false);
  const [successMessage, setSuccessMessage] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);

  const { register, handleSubmit, reset, formState: { errors } } = useForm<ConfigFormValues>();

  const showSuccess = (msg: string) => {
    setSuccessMessage(msg);
    setTimeout(() => setSuccessMessage(null), 5000);
  };

  const showError = (msg: string) => {
    setErrorMessage(msg);
    setTimeout(() => setErrorMessage(null), 8000);
  };

  const handleEditConfig = () => {
    reset({
      enabled: config?.enabled ?? false,
      listenPort: config?.listenPort ?? 51820,
      address: config?.address ?? '10.8.0.1/24',
      endpoint: config?.endpoint ?? '',
      dns: config?.dns ?? '',
      lanCIDR: config?.lanCIDR ?? '',
    });
    setEditingConfig(true);
  };

  const handleSaveConfig = async (values: ConfigFormValues) => {
    try {
      await updateConfig({ ...values, listenPort: Number(values.listenPort) });
      setEditingConfig(false);
      if (values.enabled) {
        await apply();
        showSuccess('Configuration saved and applied');
      } else {
        showSuccess('Configuration saved');
      }
    } catch (e) {
      showError(`Save failed: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  const handleGenerateKeypair = async () => {
    setConfirmKeygen(false);
    try {
      await generateKeypair();
      showSuccess('Server keypair generated — re-add all peers to update their configs');
    } catch (e) {
      showError(`Keygen failed: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  const handleApply = async () => {
    try {
      await apply();
      showSuccess('WireGuard interface applied');
    } catch (e) {
      showError(`Apply failed: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  const handleAddPeer = async () => {
    if (!newPeerName.trim()) return;
    try {
      await addPeer(newPeerName.trim());
      setNewPeerName('');
      setAddPeerOpen(false);
      showSuccess(`Peer "${newPeerName.trim()}" added`);
    } catch (e) {
      showError(`Add peer failed: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  const handleShowPeerConfig = async (peer: VpnPeer) => {
    setLoadingPeerConfig(peer.id);
    try {
      const cfg = await vpnApi.getPeerConfig(peer.id);
      setPeerConfigModal(cfg);
    } catch (e) {
      showError(`Failed to get peer config: ${e instanceof Error ? e.message : String(e)}`);
    } finally {
      setLoadingPeerConfig(null);
    }
  };

  const handleDeletePeer = async () => {
    if (!deleteConfirmPeer) return;
    try {
      await deletePeer(deleteConfirmPeer.id);
      setDeleteConfirmPeer(null);
      showSuccess(`Peer "${deleteConfirmPeer.name}" deleted`);
    } catch (e) {
      showError(`Delete failed: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  if (isLoadingStatus && isLoadingConfig) {
    return (
      <div className="flex items-center justify-center h-48">
        <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Page header */}
      <div className="flex items-center gap-4">
        <div className="p-2 bg-primary/10 rounded-lg">
          <Shield className="h-6 w-6 text-primary" />
        </div>
        <div>
          <h2 className="text-2xl font-semibold">VPN</h2>
          <p className="text-muted-foreground">WireGuard remote access to your Wild Cloud network</p>
        </div>
      </div>

      {/* Alerts */}
      {successMessage && (
        <Alert className="border-green-200 bg-green-50 dark:border-green-800 dark:bg-green-950/20">
          <Check className="h-4 w-4 text-green-600" />
          <AlertDescription className="text-green-700 dark:text-green-300">{successMessage}</AlertDescription>
        </Alert>
      )}
      {(errorMessage || applyError || addPeerError) && (
        <Alert variant="error">
          <AlertDescription>{errorMessage ?? String(applyError ?? addPeerError)}</AlertDescription>
        </Alert>
      )}

      {/* Status card */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle>Status</CardTitle>
            <div className="flex items-center gap-2">
              <Badge variant={status?.running ? 'success' : config?.enabled ? 'warning' : 'secondary'} className="gap-1">
                {status?.running && <CheckCircle className="h-3 w-3" />}
                {status?.running ? 'Running' : 'Stopped'}
              </Badge>
              <Button
                size="sm"
                onClick={handleApply}
                disabled={isApplying || !config?.enabled}
                className="gap-1 h-7 text-xs"
              >
                {isApplying ? <Loader2 className="h-3 w-3 animate-spin" /> : <Play className="h-3 w-3" />}
                Apply
              </Button>
            </div>
          </div>
        </CardHeader>
        <CardContent>
          <div className="grid grid-cols-2 gap-4 text-sm sm:grid-cols-3">
            <div>
              <p className="text-muted-foreground">Interface</p>
              <p className="font-mono">{status?.interface ?? 'wg0'}</p>
            </div>
            <div>
              <p className="text-muted-foreground">Connected peers</p>
              <p className="font-mono">{status?.peerCount ?? 0}</p>
            </div>
            <div>
              <p className="text-muted-foreground">Listen port</p>
              <p className="font-mono">{status?.listenPort ?? config?.listenPort ?? 51820}</p>
            </div>
          </div>
          <div className="flex gap-2 pt-2">
            <Button
              variant="outline"
              size="sm"
              className="gap-1 h-7 text-xs"
              onClick={() => setShowAdvanced(!showAdvanced)}
            >
              {showAdvanced ? <ChevronUp className="h-3 w-3" /> : <ChevronDown className="h-3 w-3" />}
              Advanced
            </Button>
          </div>
          {showAdvanced && status?.rawOutput && (
            <div className="border-t pt-3">
              <span className="text-sm font-medium">WireGuard interface status</span>
              <pre className="bg-muted p-3 rounded-lg overflow-x-auto text-xs font-mono mt-2">
                {status.rawOutput}
              </pre>
            </div>
          )}
        </CardContent>
      </Card>

      {/* Server configuration card */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle>Server Configuration</CardTitle>
            {!editingConfig && (
              <div className="flex items-center gap-2">
                <Button
                  variant="outline"
                  size="sm"
                  onClick={() => setConfirmKeygen(true)}
                  disabled={isGeneratingKeypair}
                  className="gap-1 h-7 text-xs"
                >
                  {isGeneratingKeypair ? <Loader2 className="h-3 w-3 animate-spin" /> : <KeyRound className="h-3 w-3" />}
                  Generate Keys
                </Button>
                <Button
                  variant="outline"
                  size="sm"
                  onClick={handleEditConfig}
                  className="gap-1 h-7 text-xs"
                >
                  <Edit2 className="h-3 w-3" />
                  Configure
                </Button>
              </div>
            )}
          </div>
        </CardHeader>
        <CardContent>
          {isLoadingConfig ? (
            <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
          ) : editingConfig ? (
            <form onSubmit={handleSubmit(handleSaveConfig)} className="space-y-3">
              <div className="flex items-center gap-3">
                <input
                  type="checkbox"
                  id="enabled"
                  {...register('enabled')}
                  className="h-4 w-4"
                />
                <Label htmlFor="enabled">Enabled</Label>
              </div>
              <div>
                <Label htmlFor="endpoint">Public Endpoint</Label>
                <Input
                  id="endpoint"
                  {...register('endpoint')}
                  placeholder="vpn.example.com or 1.2.3.4"
                  className="mt-1"
                />
                <p className="text-xs text-muted-foreground mt-1">
                  Public hostname or IP clients use to connect. Port appended automatically if omitted.
                </p>
              </div>
              <div>
                <Label htmlFor="listenPort">Listen Port</Label>
                <Input
                  id="listenPort"
                  type="number"
                  {...register('listenPort', { required: 'Required', min: { value: 1, message: 'Invalid port' }, max: { value: 65535, message: 'Invalid port' } })}
                  className="mt-1"
                />
                {errors.listenPort && <p className="text-sm text-red-600 mt-1">{errors.listenPort.message}</p>}
              </div>
              <div>
                <Label htmlFor="address">Server VPN Address</Label>
                <Input
                  id="address"
                  {...register('address', { required: 'Required' })}
                  placeholder="10.8.0.1/24"
                  className="mt-1 font-mono"
                />
                {errors.address && <p className="text-sm text-red-600 mt-1">{errors.address.message}</p>}
              </div>
              <div>
                <Label htmlFor="dns">DNS for Clients</Label>
                <Input
                  id="dns"
                  {...register('dns')}
                  placeholder="10.8.0.1"
                  className="mt-1 font-mono"
                />
              </div>
              <div>
                <Label htmlFor="lanCIDR">LAN CIDR (optional)</Label>
                <Input
                  id="lanCIDR"
                  {...register('lanCIDR')}
                  placeholder="192.168.8.0/24"
                  className="mt-1 font-mono"
                />
                <p className="text-xs text-muted-foreground mt-1">
                  Routes LAN traffic through the VPN and enables masquerade on the server.
                </p>
              </div>
              <div className="flex gap-2 pt-2">
                <Button type="submit" size="sm" disabled={isUpdatingConfig}>
                  {isUpdatingConfig && <Loader2 className="h-3 w-3 animate-spin mr-1" />}
                  Save
                </Button>
                <Button type="button" variant="outline" size="sm" onClick={() => setEditingConfig(false)}>
                  Cancel
                </Button>
              </div>
            </form>
          ) : (
            <div className="space-y-3 text-sm">
              <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
                <div>
                  <p className="text-muted-foreground">Status</p>
                  <Badge variant={config?.enabled ? 'success' : 'secondary'} className="mt-0.5 gap-1">
                    {config?.enabled && <CheckCircle className="h-3 w-3" />}
                    {config?.enabled ? 'Enabled' : 'Disabled'}
                  </Badge>
                </div>
                <div>
                  <p className="text-muted-foreground">Public Endpoint</p>
                  <p className="font-mono bg-muted rounded px-2 py-1 mt-0.5">
                    {config?.endpoint || <span className="text-muted-foreground italic">not set</span>}
                  </p>
                </div>
                <div>
                  <p className="text-muted-foreground">Listen Port</p>
                  <p className="font-mono bg-muted rounded px-2 py-1 mt-0.5">{config?.listenPort ?? 51820}</p>
                </div>
                <div>
                  <p className="text-muted-foreground">VPN Subnet</p>
                  <p className="font-mono bg-muted rounded px-2 py-1 mt-0.5">{config?.address || '—'}</p>
                </div>
                <div>
                  <p className="text-muted-foreground">DNS for Clients</p>
                  <p className="font-mono bg-muted rounded px-2 py-1 mt-0.5">{config?.dns || '—'}</p>
                </div>
                <div>
                  <p className="text-muted-foreground">LAN CIDR</p>
                  <p className="font-mono bg-muted rounded px-2 py-1 mt-0.5">{config?.lanCIDR || '—'}</p>
                </div>
                <div>
                  <p className="text-muted-foreground">Public Key</p>
                  <div className="flex items-center gap-1 mt-0.5">
                    <p className="font-mono bg-muted rounded px-2 py-1 truncate text-xs flex-1">
                      {config?.publicKey || <span className="italic">not generated</span>}
                    </p>
                    {config?.publicKey && <CopyButton text={config.publicKey} />}
                  </div>
                </div>
              </div>
              {!config?.publicKey && (
                <Alert>
                  <KeyRound className="h-4 w-4" />
                  <AlertDescription>
                    No server keypair yet. Click <strong>Generate Keys</strong> before adding peers.
                  </AlertDescription>
                </Alert>
              )}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Peers card */}
      <Card>
        <CardHeader>
          <div className="flex items-center justify-between">
            <CardTitle>Peers</CardTitle>
            <Button
              size="sm"
              onClick={() => setAddPeerOpen(true)}
              disabled={!config?.publicKey}
              className="gap-1 h-7 text-xs"
            >
              <Plus className="h-3 w-3" />
              Add Peer
            </Button>
          </div>
        </CardHeader>
        <CardContent>
          {isLoadingPeers ? (
            <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
          ) : peers.length === 0 ? (
            <div className="text-center py-8 text-muted-foreground">
              <Shield className="h-10 w-10 mx-auto mb-2 opacity-30" />
              <p className="text-sm">No peers yet. Add a peer to get started.</p>
            </div>
          ) : (
            <div className="divide-y">
              {peers.map((peer) => (
                <div key={peer.id} className="flex items-center justify-between py-3">
                  <div>
                    <p className="font-medium text-sm">{peer.name}</p>
                    <p className="text-xs text-muted-foreground font-mono">{peer.allowedIPs}</p>
                  </div>
                  <div className="flex items-center gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      className="gap-1 h-7 text-xs"
                      disabled={loadingPeerConfig === peer.id}
                      onClick={() => handleShowPeerConfig(peer)}
                    >
                      {loadingPeerConfig === peer.id
                        ? <Loader2 className="h-3 w-3 animate-spin" />
                        : <RefreshCw className="h-3 w-3" />}
                      Config
                    </Button>
                    <Button
                      variant="ghost"
                      size="sm"
                      className="h-7 w-7 p-0 text-destructive hover:text-destructive"
                      onClick={() => setDeleteConfirmPeer(peer)}
                    >
                      <Trash2 className="h-3.5 w-3.5" />
                    </Button>
                  </div>
                </div>
              ))}
            </div>
          )}
        </CardContent>
      </Card>

      {/* Add peer drawer */}
      <Sheet open={addPeerOpen} onOpenChange={setAddPeerOpen}>
        <SheetContent>
          <SheetHeader>
            <SheetTitle>Add Peer</SheetTitle>
          </SheetHeader>
          <div className="space-y-4 py-6">
            <div>
              <Label htmlFor="peerName">Peer Name</Label>
              <Input
                id="peerName"
                value={newPeerName}
                onChange={(e) => setNewPeerName(e.target.value)}
                placeholder="e.g. my-phone, laptop"
                className="mt-1"
                onKeyDown={(e) => e.key === 'Enter' && handleAddPeer()}
              />
              <p className="text-xs text-muted-foreground mt-1">
                A VPN IP will be assigned automatically from the server subnet.
              </p>
            </div>
            {addPeerError && (
              <Alert variant="error">
                <AlertDescription>{String(addPeerError)}</AlertDescription>
              </Alert>
            )}
          </div>
          <SheetFooter>
            <Button onClick={handleAddPeer} disabled={isAddingPeer || !newPeerName.trim()}>
              {isAddingPeer && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
              Add Peer
            </Button>
            <Button variant="outline" onClick={() => setAddPeerOpen(false)}>Cancel</Button>
          </SheetFooter>
        </SheetContent>
      </Sheet>

      {/* Peer config modal */}
      <Dialog open={!!peerConfigModal} onOpenChange={(open) => !open && setPeerConfigModal(null)}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>{peerConfigModal?.name} — Client Config</DialogTitle>
          </DialogHeader>
          {peerConfigModal && (
            <div className="space-y-4">
              <div className="flex justify-center">
                <QRCodeSVG value={peerConfigModal.config} size={220} />
              </div>
              <p className="text-xs text-center text-muted-foreground">
                Scan with the WireGuard mobile app
              </p>
              <div className="relative">
                <pre className="text-xs font-mono bg-muted rounded-md p-3 overflow-x-auto whitespace-pre-wrap break-all">
                  {peerConfigModal.config}
                </pre>
                <div className="absolute top-2 right-2">
                  <CopyButton text={peerConfigModal.config} />
                </div>
              </div>
            </div>
          )}
          <DialogFooter>
            <Button variant="outline" onClick={() => setPeerConfigModal(null)}>Close</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Generate keypair confirmation */}
      <AlertDialog open={confirmKeygen} onOpenChange={setConfirmKeygen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Regenerate Server Keypair?</AlertDialogTitle>
            <AlertDialogDescription>
              This will generate a new server private and public key. All existing peer configs
              will become invalid — you'll need to regenerate and redistribute them.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleGenerateKeypair}>Generate</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* Delete peer confirmation */}
      <AlertDialog open={!!deleteConfirmPeer} onOpenChange={(open) => !open && setDeleteConfirmPeer(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete peer "{deleteConfirmPeer?.name}"?</AlertDialogTitle>
            <AlertDialogDescription>
              This will remove the peer configuration. The peer will no longer be able to connect
              after you apply the VPN config.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={handleDeletePeer}>Delete</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
