import { useEffect, useState } from 'react';
import { useParams } from 'react-router';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Database, ExternalLink, Plus, RefreshCw, Trash2 } from 'lucide-react';
import { toast } from 'sonner';
import { ApiError, api } from '@/lib/api';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

interface ManagedDatabase {
  id: string;
  name: string;
  databaseName: string;
  username: string;
  password: string;
  host: string;
  port: number;
  phpMyAdminUrl: string | null;
  createdAt: string;
  updatedAt: string;
}

function extractApiMessage(error: unknown, fallback: string): string {
  if (error instanceof ApiError && error.data && typeof error.data === 'object') {
    const maybeMessage = (error.data as { message?: unknown }).message;
    if (typeof maybeMessage === 'string' && maybeMessage.trim()) {
      return maybeMessage;
    }
  }

  return fallback;
}

function InfoRow({ label, value }: { label: string; value: string }) {
  return (
    <div className="space-y-1">
      <p className="text-xs uppercase tracking-wide text-muted-foreground">{label}</p>
      <div className="rounded-md border bg-muted/40 px-3 py-2 font-mono text-xs">
        {value}
      </div>
    </div>
  );
}

export function DatabasesPage() {
  const { orgId, serverId } = useParams();
  const queryClient = useQueryClient();

  const [createOpen, setCreateOpen] = useState(false);
  const [createName, setCreateName] = useState('');
  const [createPassword, setCreatePassword] = useState('');
  const [editingDatabase, setEditingDatabase] = useState<ManagedDatabase | null>(null);
  const [editName, setEditName] = useState('');
  const [editPassword, setEditPassword] = useState('');

  const { data, isLoading } = useQuery({
    queryKey: ['server-databases', orgId, serverId],
    queryFn: () =>
      api.get<{ data: ManagedDatabase[] }>(
        `/organizations/${orgId}/servers/${serverId}/databases`,
      ),
  });

  useEffect(() => {
    if (!editingDatabase) return;
    setEditName(editingDatabase.name);
    setEditPassword('');
  }, [editingDatabase]);

  const databases = data?.data ?? [];

  const resetCreateForm = () => {
    setCreateName('');
    setCreatePassword('');
  };

  const createMutation = useMutation({
    mutationFn: (body: { name: string; password?: string }) =>
      api.post<ManagedDatabase>(`/organizations/${orgId}/servers/${serverId}/databases`, body),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['server-databases', orgId, serverId] });
      setCreateOpen(false);
      resetCreateForm();
      toast.success('Database created');
    },
    onError: (error) => {
      toast.error(extractApiMessage(error, 'Failed to create database'));
    },
  });

  const updateMutation = useMutation({
    mutationFn: (body: { name?: string; password?: string }) =>
      api.patch<ManagedDatabase>(
        `/organizations/${orgId}/servers/${serverId}/databases/${editingDatabase!.id}`,
        body,
      ),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['server-databases', orgId, serverId] });
      setEditingDatabase(null);
      setEditPassword('');
      toast.success('Database updated');
    },
    onError: (error) => {
      toast.error(extractApiMessage(error, 'Failed to update database'));
    },
  });

  const deleteMutation = useMutation({
    mutationFn: (databaseId: string) =>
      api.delete(`/organizations/${orgId}/servers/${serverId}/databases/${databaseId}`),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['server-databases', orgId, serverId] });
      toast.success('Database deleted');
    },
    onError: (error) => {
      toast.error(extractApiMessage(error, 'Failed to delete database'));
    },
  });

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between gap-4">
        <div>
          <h2 className="text-xl font-semibold">Databases</h2>
          <p className="text-sm text-muted-foreground">
            Unlimited MySQL databases for this server, with password rotation and phpMyAdmin links.
          </p>
        </div>
        <Dialog
          open={createOpen}
          onOpenChange={(open) => {
            setCreateOpen(open);
            if (!open) resetCreateForm();
          }}
        >
          <DialogTrigger asChild>
            <Button>
              <Plus className="h-4 w-4" /> Create Database
            </Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Create MySQL Database</DialogTitle>
            </DialogHeader>
            <form
              className="space-y-4"
              onSubmit={(event) => {
                event.preventDefault();
                createMutation.mutate({
                  name: createName,
                  password: createPassword.trim() || undefined,
                });
              }}
            >
              <div className="space-y-2">
                <Label>Label</Label>
                <Input
                  value={createName}
                  onChange={(event) => setCreateName(event.target.value)}
                  placeholder="LuckPerms"
                  required
                />
              </div>
              <div className="space-y-2">
                <Label>Password (Optional)</Label>
                <Input
                  value={createPassword}
                  onChange={(event) => setCreatePassword(event.target.value)}
                  minLength={8}
                  placeholder="Leave empty to auto-generate"
                />
                <p className="text-xs text-muted-foreground">
                  If left empty, the panel generates a strong password automatically.
                </p>
              </div>
              <DialogFooter>
                <Button type="submit" disabled={createMutation.isPending}>
                  {createMutation.isPending ? 'Creating...' : 'Create'}
                </Button>
              </DialogFooter>
            </form>
          </DialogContent>
        </Dialog>
      </div>

      <Dialog
        open={Boolean(editingDatabase)}
        onOpenChange={(open) => {
          if (!open) {
            setEditingDatabase(null);
            setEditPassword('');
          }
        }}
      >
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Edit Database</DialogTitle>
          </DialogHeader>
          <form
            className="space-y-4"
            onSubmit={(event) => {
              event.preventDefault();
              updateMutation.mutate({
                name: editName !== editingDatabase?.name ? editName : undefined,
                password: editPassword.trim() || undefined,
              });
            }}
          >
            <div className="space-y-2">
              <Label>Label</Label>
              <Input
                value={editName}
                onChange={(event) => setEditName(event.target.value)}
                required
              />
            </div>
            <div className="space-y-2">
              <Label>New Password (Optional)</Label>
              <Input
                value={editPassword}
                onChange={(event) => setEditPassword(event.target.value)}
                minLength={8}
                placeholder="Leave empty to keep the current password"
              />
              <p className="text-xs text-muted-foreground">
                Entering a value rotates the MySQL user password immediately.
              </p>
            </div>
            <DialogFooter>
              <Button type="submit" disabled={updateMutation.isPending}>
                {updateMutation.isPending ? 'Saving...' : 'Save Changes'}
              </Button>
            </DialogFooter>
          </form>
        </DialogContent>
      </Dialog>

      {isLoading ? (
        <div className="flex items-center justify-center py-12">
          <div className="h-8 w-8 animate-spin rounded-full border-2 border-primary border-t-transparent" />
        </div>
      ) : databases.length === 0 ? (
        <Card>
          <CardContent className="py-12 text-center text-sm text-muted-foreground">
            No databases yet. Create one for plugins, web panels, or server-side data.
          </CardContent>
        </Card>
      ) : (
        <div className="grid gap-4 lg:grid-cols-2">
          {databases.map((database) => (
            <Card key={database.id}>
              <CardHeader className="flex flex-row items-start justify-between gap-4">
                <div className="space-y-1">
                  <div className="flex items-center gap-2">
                    <Database className="h-5 w-5 text-primary" />
                    <CardTitle className="text-base">{database.name}</CardTitle>
                  </div>
                  <p className="text-xs text-muted-foreground">
                    Created {new Date(database.createdAt).toLocaleString()}
                  </p>
                </div>
                <div className="flex gap-2">
                  {database.phpMyAdminUrl ? (
                    <Button asChild size="sm" variant="outline">
                      <a href={database.phpMyAdminUrl} rel="noreferrer" target="_blank">
                        <ExternalLink className="h-4 w-4" /> phpMyAdmin
                      </a>
                    </Button>
                  ) : null}
                  <Button
                    size="sm"
                    variant="outline"
                    onClick={() => setEditingDatabase(database)}
                  >
                    <RefreshCw className="h-4 w-4" /> Edit
                  </Button>
                  <Button
                    size="sm"
                    variant="destructive"
                    disabled={deleteMutation.isPending}
                    onClick={() => {
                      const confirmed = window.confirm(
                        `Delete "${database.name}" and permanently drop ${database.databaseName}?`,
                      );
                      if (!confirmed) return;
                      deleteMutation.mutate(database.id);
                    }}
                  >
                    <Trash2 className="h-4 w-4" /> Delete
                  </Button>
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="grid gap-3 sm:grid-cols-2">
                  <InfoRow label="Host" value={database.host} />
                  <InfoRow label="Port" value={String(database.port)} />
                  <InfoRow label="Database" value={database.databaseName} />
                  <InfoRow label="Username" value={database.username} />
                </div>
                <InfoRow label="Password" value={database.password} />
                <InfoRow
                  label="Connection URI"
                  value={`mysql://${encodeURIComponent(database.username)}:${encodeURIComponent(database.password)}@${database.host}:${database.port}/${encodeURIComponent(database.databaseName)}`}
                />
                {!database.phpMyAdminUrl ? (
                  <p className="text-xs text-muted-foreground">
                    phpMyAdmin link is not configured. Set `managed_mysql.phpmyadmin_url` in the daemon config for this node.
                  </p>
                ) : null}
              </CardContent>
            </Card>
          ))}
        </div>
      )}
    </div>
  );
}
