import { useState } from 'react';
import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Checkbox } from '@/components/ui/checkbox';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Separator } from '@/components/ui/separator';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { CheckCircle2, Copy, Key, Plus, Trash2, XCircle } from 'lucide-react';
import { toast } from 'sonner';
import { createAccessKey, deleteAccessKey, listAccessKeys } from '@/client';
import {getApiErrorMessage} from '@/lib/api-error';

const AVAILABLE_SCOPES = [
    { value: 'repo', label: 'Repository Access', description: 'Full access to repositories' },
    { value: 'repo:read', label: 'Repository Read', description: 'Read-only access to repositories' },
    { value: 'user', label: 'User Access', description: 'Access to user profile and settings' },
    { value: 'project', label: 'Project Access', description: 'Full access to projects' },
    { value: 'project:read', label: 'Project Read', description: 'Read-only access to projects' },
];

export function SettingsTokens() {
    const queryClient = useQueryClient();
    const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
    const [deleteKeyId, setDeleteKeyId] = useState<number | null>(null);
    const [revokeKeyId, setRevokeKeyId] = useState<number | null>(null);
    const [newTokenName, setNewTokenName] = useState('');
    const [newTokenScopes, setNewTokenScopes] = useState<string[]>([]);
    const [newTokenExpiry, setNewTokenExpiry] = useState('');
    const [createdToken, setCreatedToken] = useState<string | null>(null);
    const [copiedToken, setCopiedToken] = useState(false);

    // Fetch access keys
    const { data: accessKeysData, isLoading } = useQuery({
        queryKey: ['accessKeys'],
        queryFn: async () => {
            const resp = await listAccessKeys();
            return resp.data?.data ?? null;
        },
    });

    const createKeyMutation = useMutation({
        mutationFn: async () => {
            const resp = await createAccessKey({
                body: {
                    name: newTokenName,
                    scopes: newTokenScopes,
                    expires_at: newTokenExpiry || null,
                },
            });
            return resp.data?.data ?? null;
        },
        onSuccess: (data) => {
            toast.success('Access token created successfully');
            queryClient.invalidateQueries({ queryKey: ['accessKeys'] });
            setCreatedToken(data?.access_key || null);
            setNewTokenName('');
            setNewTokenScopes([]);
            setNewTokenExpiry('');
        },
        onError: (err: unknown) => {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            toast.error(getApiErrorMessage(err, 'Failed to create access token'));
        },
    });

    const deleteKeyMutation = useMutation({
        mutationFn: async (keyId: number) => {
            await deleteAccessKey({ path: { access_key_id: keyId } });
        },
        onSuccess: () => {
            toast.success('Access token deleted successfully');
            queryClient.invalidateQueries({ queryKey: ['accessKeys'] });
            setDeleteKeyId(null);
        },
        onError: (err: unknown) => {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            toast.error(getApiErrorMessage(err, 'Failed to delete access token'));
        },
    });

    const handleCreateToken = () => {
        if (!newTokenName.trim()) {
            toast.error('Please enter a name for the access token');
            return;
        }
        if (newTokenScopes.length === 0) {
            toast.error('Please select at least one scope');
            return;
        }
        createKeyMutation.mutate();
    };

    const handleCopyToken = (token: string) => {
        navigator.clipboard.writeText(token);
        setCopiedToken(true);
        toast.success('Token copied to clipboard');
        setTimeout(() => setCopiedToken(false), 2000);
    };

    const handleCloseCreatedTokenDialog = () => {
        setCreatedToken(null);
        setIsCreateDialogOpen(false);
    };

    const formatDate = (dateString: string) => {
        return new Date(dateString).toLocaleDateString('en-US', {
            year: 'numeric',
            month: 'short',
            day: 'numeric',
        });
    };

    const toggleScope = (scope: string) => {
        setNewTokenScopes((prev) => (prev.includes(scope) ? prev.filter((s) => s !== scope) : [...prev, scope]));
    };

    const accessKeys = accessKeysData?.access_keys || [];

    return (
        <div className="flex-1 lg:max-w-4xl space-y-6 p-4 md:p-8 pt-6">
            <div className="flex flex-col space-y-8 lg:flex-row lg:items-center lg:justify-between lg:space-y-0">
                <div className="space-y-0.5">
                    <h2 className="text-2xl font-bold tracking-tight">Tokens</h2>
                    <p className="text-muted-foreground">Manage your personal access tokens for API access.</p>
                </div>
                <Button onClick={() => setIsCreateDialogOpen(true)}>
                    <Plus className="h-4 w-4 mr-2" />
                    Create Token
                </Button>
            </div>
            <Separator className="my-6" />

            <Card>
                <CardHeader>
                    <CardTitle>Personal Access Tokens</CardTitle>
                    <p className="text-sm text-muted-foreground">
                        {accessKeys.length === 0
                            ? 'No tokens found. Create a new token to get started.'
                            : `You have ${accessKeys.length} access token${accessKeys.length > 1 ? 's' : ''} configured.`}
                    </p>
                </CardHeader>
                <CardContent className="px-0 md:px-6">
                    {isLoading ? (
                        <div className="text-center py-8">
                            <p className="text-muted-foreground">Loading access tokens...</p>
                        </div>
                    ) : accessKeys.length === 0 ? (
                        <div className="text-center py-12 border-t border-dashed">
                            <div className="bg-muted/50 rounded-full p-4 w-fit mx-auto mb-4">
                                <Key className="h-8 w-8 text-muted-foreground" />
                            </div>
                            <h3 className="text-lg font-medium mb-2">No Access Tokens</h3>
                            <p className="text-muted-foreground mb-6 max-w-sm mx-auto">
                                Create a personal access token to authenticate API requests and access Git repositories
                                over HTTPS.
                            </p>
                            <Button onClick={() => setIsCreateDialogOpen(true)}>
                                <Plus className="h-4 w-4 mr-2" />
                                Create Your First Token
                            </Button>
                        </div>
                    ) : (
                        <div className="space-y-1">
                            {accessKeys.map((key, index) => {
                                const keyId = key.id || index;
                                return (
                                    <div key={keyId}>
                                        {index > 0 && <Separator />}
                                        <div className="py-4 px-4 hover:bg-muted/30 transition-colors flex flex-col md:flex-row md:items-start justify-between gap-4 group">
                                            <div className="flex items-start gap-4">
                                                <div className="mt-1">
                                                    <Key className="h-6 w-6 text-muted-foreground/70" />
                                                </div>
                                                <div className="space-y-1.5 flex-1">
                                                    <div className="flex items-center gap-2">
                                                        <h3 className="font-semibold text-base">{key.name || 'Untitled'}</h3>
                                                        {key.is_revoked && <Badge variant="destructive">Revoked</Badge>}
                                                    </div>
                                                    <div className="flex flex-wrap gap-2 py-1">
                                                        <span className="text-xs text-muted-foreground self-center">Scopes:</span>
                                                        {(key.scopes || []).map((scope) => (
                                                            <Badge key={scope} variant="secondary" className="text-xs font-mono font-normal">
                                                                {scope}
                                                            </Badge>
                                                        ))}
                                                    </div>
                                                    <div className="flex items-center gap-4 text-xs text-muted-foreground">
                                                        <span className="flex items-center gap-1">
                                                            Created{' '}
                                                            <span className="font-medium text-foreground">
                                                                {key.created_at ? formatDate(key.created_at) : 'Unknown'}
                                                            </span>
                                                        </span>
                                                        {key.expires_at ? (
                                                            <>
                                                                <span>•</span>
                                                                <span className="flex items-center gap-1">
                                                                    Expires{' '}
                                                                    <span className="font-medium text-foreground">
                                                                        {formatDate(key.expires_at)}
                                                                    </span>
                                                                </span>
                                                            </>
                                                        ) : (
                                                            <>
                                                                <span>•</span>
                                                                <span className="text-green-600 dark:text-green-400">Never expires</span>
                                                            </>
                                                        )}
                                                    </div>
                                                </div>
                                            </div>
                                            <div className="flex items-center gap-2 self-end md:self-center opacity-0 group-hover:opacity-100 transition-opacity">
                                                {!key.is_revoked && (
                                                    <Button
                                                        variant="ghost"
                                                        size="sm"
                                                        className="h-8"
                                                        onClick={() => setRevokeKeyId(keyId)}
                                                    >
                                                        <XCircle className="h-4 w-4 mr-1 text-orange-500" />
                                                        Revoke
                                                    </Button>
                                                )}
                                                <Button
                                                    variant="ghost"
                                                    size="sm"
                                                    className="h-8 text-destructive hover:text-destructive hover:bg-destructive/10"
                                                    onClick={() => setDeleteKeyId(keyId)}
                                                    disabled={deleteKeyMutation.isPending}
                                                >
                                                    <Trash2 className="h-4 w-4" />
                                                </Button>
                                            </div>
                                        </div>
                                    </div>
                                );
                            })}
                        </div>
                    )}
                </CardContent>
            </Card>

            {/* Create Token Dialog */}
            <Dialog open={isCreateDialogOpen && !createdToken} onOpenChange={setIsCreateDialogOpen}>
                <DialogContent className="sm:max-w-[600px]">
                    <DialogHeader>
                        <DialogTitle>Create Access Token</DialogTitle>
                        <DialogDescription>Create a new personal access token for API authentication.</DialogDescription>
                    </DialogHeader>
                    <div className="space-y-4">
                        <div className="space-y-2">
                            <Label htmlFor="token-name">Token Name</Label>
                            <Input
                                id="token-name"
                                placeholder="e.g., CI/CD Pipeline, Development Environment"
                                value={newTokenName}
                                onChange={(e) => setNewTokenName(e.target.value)}
                            />
                            <p className="text-xs text-muted-foreground">Choose a descriptive name for this token</p>
                        </div>
                        <div className="space-y-2">
                            <Label>Scopes</Label>
                            <div className="space-y-3 border rounded-md p-4">
                                {AVAILABLE_SCOPES.map((scope) => (
                                    <div key={scope.value} className="flex items-start space-x-3">
                                        <Checkbox
                                            id={scope.value}
                                            checked={newTokenScopes.includes(scope.value)}
                                            onCheckedChange={() => toggleScope(scope.value)}
                                        />
                                        <div className="space-y-1 leading-none">
                                            <Label htmlFor={scope.value} className="text-sm font-medium cursor-pointer">
                                                {scope.label}
                                            </Label>
                                            <p className="text-xs text-muted-foreground">{scope.description}</p>
                                        </div>
                                    </div>
                                ))}
                            </div>
                            <p className="text-xs text-muted-foreground">Select the permissions this token will have</p>
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="token-expiry">Expiration Date (Optional)</Label>
                            <Input
                                id="token-expiry"
                                type="date"
                                value={newTokenExpiry}
                                onChange={(e) => setNewTokenExpiry(e.target.value)}
                                min={new Date().toISOString().split('T')[0]}
                            />
                            <p className="text-xs text-muted-foreground">Leave empty for no expiration</p>
                        </div>
                    </div>
                    <DialogFooter>
                        <Button
                            variant="outline"
                            onClick={() => setIsCreateDialogOpen(false)}
                            disabled={createKeyMutation.isPending}
                        >
                            Cancel
                        </Button>
                        <Button onClick={handleCreateToken} disabled={createKeyMutation.isPending}>
                            {createKeyMutation.isPending ? 'Creating...' : 'Create Token'}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>

            {/* Show Created Token Dialog */}
            <Dialog open={!!createdToken} onOpenChange={handleCloseCreatedTokenDialog}>
                <DialogContent className="sm:max-w-[600px]">
                    <DialogHeader>
                        <DialogTitle className="flex items-center gap-2">
                            <CheckCircle2 className="h-5 w-5 text-green-500" />
                            Token Created Successfully
                        </DialogTitle>
                        <DialogDescription>
                            Make sure to copy your access token now. You won't be able to see it again!
                        </DialogDescription>
                    </DialogHeader>
                    <div className="space-y-4">
                        <div className="space-y-2">
                            <Label>Your Access Token</Label>
                            <div className="flex gap-2">
                                <Input value={createdToken || ''} readOnly className="font-mono text-sm" />
                                <Button
                                    size="icon"
                                    variant="outline"
                                    onClick={() => createdToken && handleCopyToken(createdToken)}
                                >
                                    {copiedToken ? (
                                        <CheckCircle2 className="h-4 w-4 text-green-500" />
                                    ) : (
                                        <Copy className="h-4 w-4" />
                                    )}
                                </Button>
                            </div>
                            <div className="bg-yellow-50 dark:bg-yellow-950 border border-yellow-200 dark:border-yellow-800 rounded-md p-3">
                                <p className="text-sm text-yellow-800 dark:text-yellow-200">
                                    <strong>Important:</strong> This token will only be shown once. Store it securely.
                                </p>
                            </div>
                        </div>
                    </div>
                    <DialogFooter>
                        <Button onClick={handleCloseCreatedTokenDialog}>I've Saved My Token</Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>

            {/* Delete Confirmation Dialog */}
            <AlertDialog open={deleteKeyId !== null} onOpenChange={(open) => !open && setDeleteKeyId(null)}>
                <AlertDialogContent>
                    <AlertDialogHeader>
                        <AlertDialogTitle>Delete Access Token</AlertDialogTitle>
                        <AlertDialogDescription>
                            Are you sure you want to delete this access token? This action cannot be undone and any
                            applications using this token will lose access immediately.
                        </AlertDialogDescription>
                    </AlertDialogHeader>
                    <AlertDialogFooter>
                        <AlertDialogCancel disabled={deleteKeyMutation.isPending}>Cancel</AlertDialogCancel>
                        <AlertDialogAction
                            onClick={() => deleteKeyId && deleteKeyMutation.mutate(deleteKeyId)}
                            disabled={deleteKeyMutation.isPending}
                            className="bg-destructive hover:bg-destructive/90"
                        >
                            {deleteKeyMutation.isPending ? 'Deleting...' : 'Delete'}
                        </AlertDialogAction>
                    </AlertDialogFooter>
                </AlertDialogContent>
            </AlertDialog>

            {/* Revoke Confirmation Dialog */}
            <AlertDialog open={revokeKeyId !== null} onOpenChange={(open) => !open && setRevokeKeyId(null)}>
                <AlertDialogContent>
                    <AlertDialogHeader>
                        <AlertDialogTitle>Revoke Access Token</AlertDialogTitle>
                        <AlertDialogDescription>
                            Are you sure you want to revoke this access token? The token will be disabled immediately
                            and can no longer be used for authentication.
                        </AlertDialogDescription>
                    </AlertDialogHeader>
                    <AlertDialogFooter>
                        <AlertDialogCancel>Cancel</AlertDialogCancel>
                        <AlertDialogAction className="bg-destructive hover:bg-destructive/90">Revoke</AlertDialogAction>
                    </AlertDialogFooter>
                </AlertDialogContent>
            </AlertDialog>
        </div>
    );
}
