import { useState, useEffect, useContext } from "react";
import { apiFetch } from '@/utils/api';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { UserList } from "./UserList";
import { UserForm } from "./UserForm";
import { toast } from "sonner";
import config from "@/config";
import { AuthContext } from "@/contexts/AuthContext";
import { ShieldAlert } from "lucide-react";

interface User {
  id: number;
  username: string;
  email?: string;
  is_admin: boolean;
  is_active: boolean;
  last_login?: string;
  permissions?: Permission[];
}

interface Permission {
  id: number;
  name: string;
  code: string;
  description?: string;
  category?: string;
}

interface PermissionCategory {
  category: string;
  permissions: Permission[];
}

export function UserManagement() {
  const { token, fetchCurrentUser } = useContext(AuthContext);
  const [users, setUsers] = useState<User[]>([]);
  const [selectedUser, setSelectedUser] = useState<User | null>(null);
  const [isAddingUser, setIsAddingUser] = useState(false);
  const [permissions, setPermissions] = useState<PermissionCategory[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  // Fetch users and permissions
  const fetchData = async () => {
    if (!token) {
      setError("Authentication required. Please log in again.");
      setLoading(false);
      return;
    }

    // The PermissionGuard component already handles permission checks,
    // so we don't need to duplicate that logic here
    
    try {
      setLoading(true);
      setError(null);
      
      // Fetch users
      const usersResponse = await apiFetch(`${config.authUrl}/users`, {
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
      
      if (!usersResponse.ok) {
        if (usersResponse.status === 401) {
          throw new Error('Authentication failed. Please log in again.');
        } else if (usersResponse.status === 403) {
          throw new Error('You don\'t have permission to access the user list.');
        } else {
          // Try to get more detailed error message from response
          try {
            const errorData = await usersResponse.json();
            throw new Error(errorData.error || `Failed to fetch users (${usersResponse.status})`);
          } catch (e) {
            throw new Error(`Failed to fetch users (${usersResponse.status})`);
          }
        }
      }
      
      const usersData = await usersResponse.json();
      setUsers(usersData);
      
      // Fetch permissions
      const permissionsResponse = await apiFetch(`${config.authUrl}/permissions/categories`, {
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
      
      if (!permissionsResponse.ok) {
        if (permissionsResponse.status === 401) {
          throw new Error('Authentication failed. Please log in again.');
        } else if (permissionsResponse.status === 403) {
          throw new Error('You don\'t have permission to access permissions.');
        } else {
          // Try to get more detailed error message from response
          try {
            const errorData = await permissionsResponse.json();
            throw new Error(errorData.error || `Failed to fetch permissions (${permissionsResponse.status})`);
          } catch (e) {
            throw new Error(`Failed to fetch permissions (${permissionsResponse.status})`);
          }
        }
      }
      
      const permissionsData = await permissionsResponse.json();
      setPermissions(permissionsData);
      
      setLoading(false);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'An error occurred';
      setError(errorMessage);
      setLoading(false);
      
      // If authentication error, refresh the token
      if (err instanceof Error && err.message.includes('Authentication failed')) {
        fetchCurrentUser().catch(() => {
          // Handle failed token refresh
        });
      }
    }
  };

  useEffect(() => {
    fetchData();
  }, [token]);

  const handleEditUser = async (userId: number) => {
    try {
      const response = await apiFetch(`${config.authUrl}/users/${userId}`, {
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
      
      if (!response.ok) {
        if (response.status === 401) {
          throw new Error('Authentication failed. Please log in again.');
        } else if (response.status === 403) {
          throw new Error('You don\'t have permission to edit users.');
        } else {
          throw new Error(`Failed to fetch user details (${response.status})`);
        }
      }
      
      const userData = await response.json();
      console.log("Fetched user data for editing:", userData);
      
      // Ensure permissions is always an array
      if (!userData.permissions) {
        userData.permissions = [];
      }
      
      // Make sure the permissions are in the right format for the form
      // The server might send either an array of permission objects or just permission codes
      if (userData.permissions && userData.permissions.length > 0) {
        // Check if permissions are objects with id property
        if (typeof userData.permissions[0] === 'string') {
          // If we just have permission codes, we need to convert them to objects with ids
          // by looking them up in the permissions data
          const permissionObjects = [];
          
          // Go through each permission category
          for (const category of permissions) {
            // For each permission in the category
            for (const permission of category.permissions) {
              // If this permission's code is in the user's permission codes
              if (userData.permissions.includes(permission.code)) {
                permissionObjects.push(permission);
              }
            }
          }
          
          userData.permissions = permissionObjects;
        }
      }
      
      setSelectedUser(userData);
      setIsAddingUser(false);
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to load user details';
      setError(errorMessage);
    }
  };

  const handleAddUser = () => {
    setSelectedUser(null);
    setIsAddingUser(true);
  };

  const handleSaveUser = async (userData: any) => {
    console.log("Saving user data:", userData);
    
    // Format permissions for the API - convert from permission objects to IDs
    let formattedUserData = { ...userData };
    
    if (userData.permissions && Array.isArray(userData.permissions)) {
      // Check if permissions are objects (from the form) and convert to IDs for the API
      if (userData.permissions.length > 0 && typeof userData.permissions[0] === 'object') {
        // The backend expects permission IDs, not just the code strings
        formattedUserData.permissions = userData.permissions.map((p: { id: any; }) => p.id);
      }
    }
    
    console.log("Formatted user data for API:", formattedUserData);
    
    setLoading(true);
    
    try {
      // Use PUT for updating, POST for creating
      const method = userData.id ? 'PUT' : 'POST';
      const endpoint = userData.id 
        ? `${config.authUrl}/users/${userData.id}` 
        : `${config.authUrl}/users`;
        
      console.log(`${method} request to ${endpoint}`);
      
      const response = await apiFetch(endpoint, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${token}`
        },
        body: JSON.stringify(formattedUserData)
      });
      
      let responseData;
      
      try {
        responseData = await response.json();
      } catch (e) {
        console.error("Error parsing response JSON:", e);
        throw new Error("Invalid response from server");
      }
      
      if (!response.ok) {
        console.error("Error response from server:", responseData);
        throw new Error(responseData.error || responseData.message || `Failed to save user (${response.status})`);
      }
      
      console.log("Server response after saving user:", responseData);

      // Explicitly confirm whether a password was part of this save — the form
      // silently drops an empty password on edit, so without this there is no
      // way to tell if a password change actually went through.
      toast.success(
        userData.id
          ? (formattedUserData.password ? "User updated — password changed" : "User updated (password not changed)")
          : "User created"
      );

      // Reset the form state
      setSelectedUser(null);
      setIsAddingUser(false);
      
      // Refresh the user list
      fetchData();
      
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to save user';
      setError(errorMessage);
    } finally {
      setLoading(false);
    }
  };

  const handleDeleteUser = async (userId: number) => {
    if (!window.confirm('Are you sure you want to delete this user?')) {
      return;
    }
    
    try {
      setLoading(true);
      
      const response = await apiFetch(`${config.authUrl}/users/${userId}`, {
        method: 'DELETE',
        headers: {
          'Authorization': `Bearer ${token}`
        }
      });
      
      if (!response.ok) {
        throw new Error('Failed to delete user');
      }
      
      // Refresh user list after a successful delete
      await fetchData();
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to delete user';
      setError(errorMessage);
      setLoading(false);
    }
  };

  const handleCancel = () => {
    setSelectedUser(null);
    setIsAddingUser(false);
  };

  if (loading && users.length === 0) {
    return (
      <Card>
        <CardContent className="pt-6">
          <div className="flex items-center justify-center h-40">
            <p>Loading user data...</p>
          </div>
        </CardContent>
      </Card>
    );
  }

  if (error) {
    return (
      <Card>
        <CardContent className="pt-6">
          <Alert variant="destructive" className="mb-4">
            <ShieldAlert className="h-4 w-4" />
            <AlertTitle>Permission Error</AlertTitle>
            <AlertDescription>{error}</AlertDescription>
          </Alert>
          <div className="flex justify-center">
            <Button onClick={fetchData}>Retry</Button>
          </div>
        </CardContent>
      </Card>
    );
  }

  return (
    <Card>
      {(selectedUser || isAddingUser) ? (
        <CardContent className="p-6">
          <UserForm 
            user={selectedUser} 
            permissions={permissions}
            onSave={handleSaveUser}
            onCancel={handleCancel}
          />
        </CardContent>
      ) : (
        <>
          <CardHeader className="flex flex-row items-center justify-between">
            <div>
              <CardTitle>User Management</CardTitle>
            </div>
            <Button onClick={handleAddUser}>
              Add User
            </Button>
          </CardHeader>
          <CardContent>
            <UserList 
              users={users} 
              onEdit={handleEditUser} 
              onDelete={handleDeleteUser} 
            />
          </CardContent>
        </>
      )}
    </Card>
  );
} 
