// BotsManagement.tsx
"use client";
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Label } from '@/components/ui/label';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { DRB_BASE_API_URL } from '@/constants/api';
import { DiscordId, System, ErrorResponse, ActiveClient } from '@/types';
import { authAwareFetch } from '@/utils/AuthAwareFetch';

interface BotsManagementProps {
  token: string | null; // Allow token to be null initially
  logoutUser: () => void;
}

const BotsManagement: React.FC<BotsManagementProps> = ({ token, logoutUser }) => {
  const [bots, setBots] = useState<ActiveClient[]>([]);
  const [discordIds, setDiscordIds] = useState<DiscordId[]>([]);
  const [systems, setSystems] = useState<System[]>([]);
  const [loading, setLoading] = useState<boolean>(true); // Set to true initially
  const [error, setError] = useState<string>('');

  const [isAddIdDialogOpen, setIsAddIdDialogOpen] = useState<boolean>(false);
  const [newIdData, setNewIdData] = useState<Omit<DiscordId, '_id' | 'guild_ids'> & { guild_ids: string }>({
    discord_id: '',
    name: '',
    token: '',
    active: false,
    guild_ids: '',
  });
  const [editingId, setEditingId] = useState<DiscordId | null>(null);

  const [isAssignDismissDialogOpen, setIsAssignDismissDialogOpen] = useState<boolean>(false);
  const [selectedBotClientId, setSelectedBotClientId] = useState<string>('');
  const [selectedSystemId, setSelectedSystemId] = useState<string>('');
  const [assignDismissAction, setAssignDismissAction] = useState<'assign' | 'dismiss'>('assign');

  const fetchData = async (): Promise<void> => {
    // Only attempt to fetch if a token is present
    if (!token) {
      setLoading(false); // Stop loading if no token
      setError('Authentication token is missing. Please log in.');
      return;
    }

    setLoading(true);
    setError('');
    let accumulatedError = '';

    try {
      const [nodesRes, discordIdsRes, systemsRes] = await Promise.all([
        authAwareFetch('/nodes/', { token }, logoutUser),
        authAwareFetch('/bots/tokens/', { token }, logoutUser),
        authAwareFetch('/systems/', { token }, logoutUser),
      ]);

      if (nodesRes.ok) {
        const botsData: ActiveClient[] = await nodesRes.json();
        setBots(botsData);
      } else {
        let errorMsg = `Failed to fetch bots (${nodesRes.status})`;
        try {
          const errorData: ErrorResponse = await nodesRes.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || nodesRes.statusText}`;
        } catch (e) { errorMsg += `: ${nodesRes.statusText}`; }
        accumulatedError += errorMsg + '\n';
      }

      if (discordIdsRes.ok) {
        const discordIdsData: DiscordId[] = await discordIdsRes.json();
        setDiscordIds(discordIdsData);
      } else {
        let errorMsg = `Failed to fetch Discord IDs (${discordIdsRes.status})`;
        try {
          const errorData: ErrorResponse = await discordIdsRes.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || discordIdsRes.statusText}`;
        } catch (e) { errorMsg += `: ${discordIdsRes.statusText}`; }
        accumulatedError += errorMsg + '\n';
      }

      if (systemsRes.ok) {
        const systemsData: System[] = await systemsRes.json();
        setSystems(systemsData);
      } else {
        let errorMsg = `Failed to fetch systems (${systemsRes.status})`;
        try {
          const errorData: ErrorResponse = await systemsRes.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || systemsRes.statusText}`;
        } catch (e) { errorMsg += `: ${systemsRes.statusText}`; }
        accumulatedError += errorMsg + '\n';
      }

      if (accumulatedError) {
        setError(accumulatedError.trim());
      }

    } catch (err: any) {
      // Catch specific unauthorized errors and let authAwareFetch handle logout
      if (err.message === 'Unauthorized: Session expired or invalid token.') {
        setLoading(false); // already handled by authAwareFetch
        return;
      }
      setError('Failed to fetch data. Check server connection or console.');
      console.error(err);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    // This effect runs whenever 'token' changes.
    // If token becomes available, it triggers fetchData.
    if (token) {
      fetchData();
    } else {
      // If token is explicitly null (e.g., after logout or initial load without a token)
      setLoading(false);
      // No need to set error "Please log in" here, as AppContent handles the redirect
      // This is a component internal message if it somehow renders without a token when it shouldn't
      setError('Authentication required to load data.');
      setBots([]); // Clear data if token is gone
      setDiscordIds([]);
      setSystems([]);
    }
  }, [token]); // Dependency on token ensures fetchData is called when token becomes available


  const handleAddId = async (): Promise<void> => {
    setError('');
    if (!token) {
      setError('Authentication token is missing. Please log in.');
      return;
    }
    try {
      const payload: Omit<DiscordId, '_id'> = {
        ...newIdData,
        guild_ids: newIdData.guild_ids.split(',').map(id => id.trim()).filter(id => id),
      };
      const method = editingId ? 'PUT' : 'POST';
      const url = editingId ? `/bots/token/${editingId._id}` : `/bots/token`;

      const response = await authAwareFetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
        token,
      }, logoutUser);

      if (response.ok) {
        fetchData();
        setIsAddIdDialogOpen(false);
        setNewIdData({ discord_id: '', name: '', token: '', active: false, guild_ids: '' });
        setEditingId(null);
      } else {
        let errorMsg = `Failed to ${editingId ? 'update' : 'add'} Discord ID (${response.status})`;
        try {
          const errorData: ErrorResponse = await response.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || response.statusText}`;
        } catch (e) { errorMsg += `: ${response.statusText}`; }
        setError(errorMsg);
      }
    } catch (err: any) {
        if (err.message === 'Unauthorized: Session expired or invalid token.') {
            setLoading(false); // already handled by authAwareFetch
            return;
        }
      setError(`Network error during ${editingId ? 'update' : 'add'} Discord ID.`);
      console.error(err);
    }
  };

  const handleDeleteId = async (id: string): Promise<void> => {
    if (!window.confirm('Are you sure you want to delete this Discord ID?')) return;
    setError('');
    if (!token) {
      setError('Authentication token is missing. Please log in.');
      return;
    }
    try {
      const response = await authAwareFetch(`/bots/token/${id}`, { method: 'DELETE', token }, logoutUser);
      if (response.ok) {
        fetchData();
      } else {
        let errorMsg = `Failed to delete Discord ID (${response.status})`;
        try {
          const errorData: ErrorResponse = await response.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || response.statusText}`;
        } catch (e) { errorMsg += `: ${response.statusText}`; }
        setError(errorMsg);
      }
    } catch (err: any) {
        if (err.message === 'Unauthorized: Session expired or invalid token.') {
            setLoading(false); // already handled by authAwareFetch
            return;
        }
      setError('Network error during delete Discord ID.');
      console.error(err);
    }
  };

  const handleAssignDismiss = async (): Promise<void> => {
    setError('');
    if (!selectedBotClientId || !selectedSystemId) {
        setError("Bot Client ID and System must be selected.");
        return;
    }
    if (!token) {
      setError('Authentication token is missing. Please log in.');
      return;
    }
    try {
      const endpoint = assignDismissAction === 'assign' ? 'assign' : 'dismiss';
      const response = await authAwareFetch(`/systems/${selectedSystemId}/${endpoint}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ client_id: selectedBotClientId }),
        token,
      }, logoutUser);
      if (response.ok) {
        fetchData();
        setIsAssignDismissDialogOpen(false);
        setSelectedBotClientId('');
        setSelectedSystemId('');
      } else {
        let errorMsg = `Failed to ${assignDismissAction} bot (${response.status})`;
        try {
          const errorData: ErrorResponse = await response.json();
          errorMsg += `: ${errorData.message || (typeof errorData.detail === 'string' ? errorData.detail : JSON.stringify(errorData.detail)) || response.statusText}`;
        } catch (e) { errorMsg += `: ${response.statusText}`; }
        setError(errorMsg);
      }
    } catch (err: any) {
        if (err.message === 'Unauthorized: Session expired or invalid token.') {
            setLoading(false); // already handled by authAwareFetch
            return;
        }
      setError(`Network error during ${assignDismissAction} bot.`);
      console.error(err);
    }
  };

  // Only show loading if actively fetching or waiting for token
  if (loading && token) return <p>Loading bots and Discord IDs...</p>;
  // Show error if there's an error
  if (error) return <p className="text-red-500 whitespace-pre-line">{error}</p>;
  // If not loading and no token, it implies no action can be taken or a login is needed
  if (!loading && !token) return <p className="text-orange-500">Please log in to view and manage bots.</p>;


  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle>Bots Management</CardTitle>
      </CardHeader>
      <CardContent className="space-y-6">
        {error && <p className="text-red-500 whitespace-pre-line">{error}</p>}
        <div>
          <h3 className="text-lg font-semibold mb-2">Online Bots (Clients)</h3>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Client ID</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {bots.length > 0 ? (
                bots.map((active_bot) => {
                  return (
                    <TableRow key={active_bot.client_id}>
                      <TableCell className="font-medium">
                        <Link href={`/nodes/${active_bot.client_id}`} className="text-blue-600 hover:underline">
                          {active_bot.nickname} ({active_bot.client_id})
                        </Link>
                        </TableCell>
                    </TableRow>
                  );
                })
              ) : (
                <TableRow>
                  <TableCell colSpan={2} className="text-center">No bots currently online or reported by /bots.</TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>

        <div>
          <h3 className="text-lg font-semibold mb-2">Manage Discord IDs</h3>
          <Button onClick={() => { setEditingId(null); setNewIdData({ discord_id: '', name: '', token: '', active: false, guild_ids: '' }); setIsAddIdDialogOpen(true);}} className="mb-4" disabled={!token}>Add New Discord ID</Button>
          <Button onClick={() => setIsAssignDismissDialogOpen(true)} className="mb-4 ml-2" disabled={!token}>Assign/Dismiss Bot System</Button>

          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>Name</TableHead>
                <TableHead>Discord ID</TableHead>
                <TableHead>Token (Partial)</TableHead>
                <TableHead>Active</TableHead>
                <TableHead>Guilds</TableHead>
                <TableHead>Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {discordIds.length > 0 ? (
                discordIds.map((dId) => (
                  <TableRow key={dId._id}>
                    <TableCell className="font-medium">{dId.name}</TableCell>
                    <TableCell>{dId.discord_id}</TableCell>
                    <TableCell className="truncate max-w-xs">{dId.token ? dId.token.substring(0, 8) + '...' : 'N/A'}</TableCell>
                    <TableCell>{dId.active ? 'Yes' : 'No'}</TableCell>
                    <TableCell>{dId.guild_ids?.join(', ')}</TableCell>
                    <TableCell>
                      <Button variant="outline" size="sm" className="mr-2"
                        onClick={() => {
                          setEditingId(dId);
                          setNewIdData({
                            discord_id: dId.discord_id,
                            name: dId.name,
                            token: dId.token,
                            active: dId.active,
                            guild_ids: dId.guild_ids?.join(', '),
                          });
                          setIsAddIdDialogOpen(true);
                        }}
                        disabled={!token}>
                        Edit
                      </Button>
                      <Button variant="destructive" size="sm" onClick={() => handleDeleteId(dId._id)} disabled={!token}>
                        Delete
                      </Button>
                    </TableCell>
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={6} className="text-center">No Discord IDs found.</TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>

      <Dialog open={isAddIdDialogOpen} onOpenChange={setIsAddIdDialogOpen}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>{editingId ? 'Edit Discord ID' : 'Add New Discord ID'}</DialogTitle>
          </DialogHeader>
          <div className="grid gap-4 py-4">
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="name" className="text-right">Name</Label>
              <Input
                id="name"
                value={newIdData.name}
                onChange={(e) => setNewIdData({ ...newIdData, name: e.target.value })}
                className="col-span-3"
              />
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="discord_id" className="text-right">Discord ID</Label>
              <Input
                id="discord_id"
                value={newIdData.discord_id}
                onChange={(e) => setNewIdData({ ...newIdData, discord_id: e.target.value })}
                className="col-span-3"
              />
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="token" className="text-right">Token</Label>
              <Input
                id="token"
                value={newIdData.token}
                onChange={(e) => setNewIdData({ ...newIdData, token: e.target.value })}
                className="col-span-3"
                placeholder={editingId ? "Token hidden for security, re-enter to change" : ""}
              />
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="guild_ids" className="text-right">Guild IDs (comma-separated)</Label>
              <Input
                id="guild_ids"
                value={newIdData.guild_ids}
                onChange={(e) => setNewIdData({ ...newIdData, guild_ids: e.target.value })}
                className="col-span-3"
              />
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="active" className="text-right">Active</Label>
              <Checkbox
                id="active"
                checked={newIdData.active}
                onCheckedChange={(checked) => setNewIdData({ ...newIdData, active: checked === true })}
                className="col-span-3"
              />
            </div>
          </div>
          <DialogFooter>
            <Button onClick={handleAddId} disabled={!token}>
              {editingId ? 'Save Changes' : 'Add Discord ID'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={isAssignDismissDialogOpen} onOpenChange={setIsAssignDismissDialogOpen}>
        <DialogContent className="sm:max-w-[425px]">
          <DialogHeader>
            <DialogTitle>Assign/Dismiss Bot to System</DialogTitle>
          </DialogHeader>
          <div className="grid gap-4 py-4">
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="bot-client-id" className="text-right">Bot Client ID</Label>
              <Select onValueChange={setSelectedBotClientId} value={selectedBotClientId}>
                <SelectTrigger className="col-span-3">
                  <SelectValue placeholder="Select a bot client ID" />
                </SelectTrigger>
                <SelectContent>
                  {bots.map((active_bot) => (
                    <SelectItem key={active_bot.client_id} value={active_bot.client_id}>{active_bot.client_id}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="system-id" className="text-right">System</Label>
              <Select onValueChange={setSelectedSystemId} value={selectedSystemId}>
                <SelectTrigger className="col-span-3">
                  <SelectValue placeholder="Select a system" />
                </SelectTrigger>
                <SelectContent>
                  {systems.map((system) => (
                    <SelectItem key={system._id} value={system._id}>{system.name} ({system._id})</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="grid grid-cols-4 items-center gap-4">
              <Label htmlFor="action" className="text-right">Action</Label>
              <Select
                onValueChange={(value: string) => setAssignDismissAction(value as 'assign' | 'dismiss')}
                value={assignDismissAction}
              >
                <SelectTrigger className="col-span-3">
                  <SelectValue placeholder="Select action" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="assign">Assign</SelectItem>
                  <SelectItem value="dismiss">Dismiss</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>
          <DialogFooter>
            <Button onClick={handleAssignDismiss} disabled={!selectedBotClientId || !selectedSystemId || !token}>Perform Action</Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
      </CardContent>
    </Card>
  );
};

export default BotsManagement;