import {useCallback, useEffect, useState} from 'react';
import {useNavigate, useSearchParams} from 'react-router-dom';
import { CheckCircle2, Loader2, Plus, XCircle } from 'lucide-react';
import { toast } from 'sonner';
import {getCurrentUserProjects, gitIsRepo, projectRepoCreate} from '@/client';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import { validateName } from '@/lib/validation';
import {getApiErrorMessage} from '@/lib/api-error';

type MyProject = {
    uid: string;
    name: string;
    display_name: string;
    avatar_url?: string | null;
    description: string | null;
    is_public: boolean;
};

export function InitRepository() {
    const navigate = useNavigate();
    const [searchParams] = useSearchParams();
    const [isLoading, setIsLoading] = useState(false);
    const [projects, setProjects] = useState<MyProject[]>([]);
    const [loadingProjects, setLoadingProjects] = useState(true);
    const [selectedProject, setSelectedProject] = useState<string>('');

    const [repoName, setRepoName] = useState('');
    const [description, setDescription] = useState('');
    const [initRepo, setInitRepo] = useState(true);
    const [defaultBranch, setDefaultBranch] = useState('main');
    const [isPrivate, setIsPrivate] = useState(false);

    const [checkingAvailability, setCheckingAvailability] = useState(false);
    const [repoAvailable, setRepoAvailable] = useState<boolean | null>(null);
    const [availabilityMessage, setAvailabilityMessage] = useState('');

    const selectedProj = projects.find((p) => p.name === selectedProject);

    useEffect(() => {
        const fetchProjects = async () => {
            try {
                const resp = await getCurrentUserProjects();
                const data = resp.data?.data;
                if (data?.projects) {
                    setProjects(data.projects as MyProject[]);
                }
            } catch (err) {
                console.error('Failed to load projects:', err);
                toast.error('Failed to load projects');
            } finally {
                setLoadingProjects(false);
            }
        };
        fetchProjects();
    }, []);

    // Pre-select project from ?project= query param
    useEffect(() => {
        const param = searchParams.get('project');
        if (param && projects.some((p) => p.name === param)) {
            setSelectedProject(param);
        }
    }, [projects, searchParams]);

    const checkRepoAvailability = useCallback(async () => {
        if (!selectedProject || !repoName.trim()) {
            setRepoAvailable(null);
            setAvailabilityMessage('');
            return;
        }

        const result = validateName(repoName.trim());
        if (!result.valid) {
            setRepoAvailable(false);
            setAvailabilityMessage(result.message);
            return;
        }

        setCheckingAvailability(true);
        try {
            const repoPath = `${selectedProject}/${repoName.trim().toLowerCase()}`;
            const response = await gitIsRepo({
                path: { path: repoPath },
            });

            const isRepo = response.data?.data;
            if (isRepo) {
                setRepoAvailable(false);
                setAvailabilityMessage('Repository name already exists');
            } else {
                setRepoAvailable(true);
                setAvailabilityMessage('Repository name is available');
            }
        } catch {
            setRepoAvailable(false);
            setAvailabilityMessage('Failed to check availability');
        } finally {
            setCheckingAvailability(false);
        }
    }, [selectedProject, repoName]);

    useEffect(() => {
        const timer = setTimeout(() => {
            checkRepoAvailability();
        }, 500);
        return () => clearTimeout(timer);
    }, [checkRepoAvailability]);

    // Auto-set private if project is private
    useEffect(() => {
        if (selectedProj && !selectedProj.is_public) {
            setIsPrivate(true);
        }
    }, [selectedProj]);

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!selectedProject) {
            toast.error('Please select a project');
            return;
        }
        if (!repoName.trim()) {
            toast.error('Repository name is required');
            return;
        }
        const result = validateName(repoName.trim());
        if (!result.valid) {
            toast.error(result.message);
            return;
        }

        setIsLoading(true);
        try {
            const resp = await projectRepoCreate({
                path: {project_name: selectedProject},
                body: {
                    repo_name: repoName.trim().toLowerCase(),
                    description: description.trim() || null,
                    init_repo: initRepo,
                    default_branch: initRepo ? (defaultBranch.trim() || 'main') : 'main',
                    is_private: isPrivate,
                },
            });

            const data = resp.data?.data;
            if (data?.repo_name) {
                toast.success(`Repository "${data.repo_name}" created successfully`);
                navigate(`/project/${selectedProject}/repositories`);
            } else {
                toast.error('Repository created but failed to load details');
            }
        } catch (err: unknown) {
            toast.error(getApiErrorMessage(err, 'Failed to create repository'));
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <div className="flex min-h-screen items-center justify-center bg-zinc-50 px-4 py-16 dark:bg-transparent">
            <div className="relative w-full max-w-2xl rounded-[calc(var(--radius)+.125rem)] border bg-card p-0.5 shadow-md">
                <form onSubmit={handleSubmit} className="p-8">
                    <div>
                        <h1 className="mb-1 mt-4 text-2xl font-semibold">Create New Repository</h1>
                        <p className="text-sm text-muted-foreground">
                            Create a new Git repository in your project
                        </p>
                    </div>

                    <hr className="my-6 border-dashed" />

                    <div className="space-y-6">
                        {/* Project */}
                        <div className="space-y-2">
                            <Label htmlFor="project" className="block text-sm">
                                Project <span className="text-destructive">*</span>
                            </Label>
                            {projects.length === 0 && !loadingProjects ? (
                                <div className="flex flex-col gap-3 rounded-lg border border-dashed p-4 text-center">
                                    <p className="text-sm text-muted-foreground">
                                        You have no projects yet.
                                    </p>
                                    <Button
                                        type="button"
                                        variant="outline"
                                        size="sm"
                                        onClick={() => navigate('/init/project')}
                                    >
                                        <Plus className="mr-2 h-4 w-4" />
                                        Create a Project
                                    </Button>
                                </div>
                            ) : (
                                <Select value={selectedProject} onValueChange={(v) => v && setSelectedProject(v)} disabled={loadingProjects}>
                                    <SelectTrigger className="w-full">
                                        <SelectValue placeholder="Select a project" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {loadingProjects ? (
                                            <SelectItem value="loading" disabled>
                                                Loading projects...
                                            </SelectItem>
                                        ) : (
                                            projects.map((proj) => (
                                                <SelectItem key={proj.name} value={proj.name}>
                                                    <div className="flex items-center gap-2">
                                                        <Avatar className="h-5 w-5">
                                                            <AvatarImage src={proj.avatar_url || ''} />
                                                            <AvatarFallback className="text-xs">
                                                                {proj.name.charAt(0).toUpperCase()}
                                                            </AvatarFallback>
                                                        </Avatar>
                                                        {proj.display_name || proj.name}
                                                    </div>
                                                </SelectItem>
                                            ))
                                        )}
                                    </SelectContent>
                                </Select>
                            )}
                        </div>

                        {/* Repo name */}
                        <div className="space-y-2">
                            <Label htmlFor="repo_name" className="block text-sm">
                                Repository Name <span className="text-destructive">*</span>
                            </Label>
                            <div className="relative">
                                <Input
                                    type="text"
                                    id="repo_name"
                                    placeholder="my-awesome-repo"
                                    value={repoName}
                                    onChange={(e) => setRepoName(e.target.value)}
                                    className="pr-10"
                                    maxLength={100}
                                />
                                <div className="absolute right-3 top-1/2 -translate-y-1/2">
                                    {checkingAvailability && (
                                        <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                                    )}
                                    {!checkingAvailability && repoAvailable === true && (
                                        <CheckCircle2 className="h-4 w-4 text-green-500" />
                                    )}
                                    {!checkingAvailability && repoAvailable === false && (
                                        <XCircle className="h-4 w-4 text-destructive" />
                                    )}
                                </div>
                            </div>
                            {availabilityMessage && (
                                <p
                                    className={`text-sm ${
                                        repoAvailable ? 'text-green-600 dark:text-green-400' : 'text-destructive'
                                    }`}
                                >
                                    {availabilityMessage}
                                </p>
                            )}
                        </div>

                        {/* Description */}
                        <div className="space-y-2">
                            <Label htmlFor="description" className="block text-sm">
                                Description
                            </Label>
                            <Textarea
                                id="description"
                                placeholder="A brief description of your repository..."
                                rows={4}
                                value={description}
                                onChange={(e) => setDescription(e.target.value)}
                                className="resize-none"
                            />
                        </div>

                        {/* Default branch */}
                        {initRepo && (
                            <div className="space-y-2">
                                <Label htmlFor="default_branch" className="block text-sm">
                                    Default Branch
                                </Label>
                                <Input
                                    type="text"
                                    id="default_branch"
                                    placeholder="main"
                                    value={defaultBranch}
                                    onChange={(e) => setDefaultBranch(e.target.value)}
                                />
                            </div>
                        )}

                        {/* Initialize Repository */}
                        <div className="flex items-center justify-between rounded-lg border p-4">
                            <div className="space-y-0.5">
                                <Label htmlFor="init_repo" className="text-sm font-medium">
                                    Initialize Repository
                                </Label>
                                <p className="text-sm text-muted-foreground">
                                    {initRepo
                                        ? 'Create a bare git repository now. Set the default branch below.'
                                        : 'Skip initialization. The default branch will be set automatically when you push.'}
                                </p>
                            </div>
                            <Switch
                                id="init_repo"
                                checked={initRepo}
                                onCheckedChange={setInitRepo}
                            />
                        </div>

                        {/* Private */}
                        <div className="flex items-center justify-between rounded-lg border p-4">
                            <div className="space-y-0.5">
                                <Label htmlFor="is_private" className="text-sm font-medium">
                                    Private Repository
                                </Label>
                                <p className="text-sm text-muted-foreground">
                                    {selectedProj && !selectedProj.is_public
                                        ? 'This repository must be private because the project is private'
                                        : 'Make this repository private and restrict access'}
                                </p>
                            </div>
                            <Switch
                                id="is_private"
                                checked={isPrivate}
                                onCheckedChange={setIsPrivate}
                                disabled={!!(selectedProj && !selectedProj.is_public)}
                            />
                        </div>

                        <div className="flex gap-4 pt-4">
                            <Button
                                type="submit"
                                className="flex-1"
                                disabled={
                                    isLoading ||
                                    !selectedProject ||
                                    !repoAvailable ||
                                    checkingAvailability ||
                                    !repoName.trim()
                                }
                            >
                                {isLoading ? 'Creating...' : 'Create Repository'}
                            </Button>
                            <Button
                                type="button"
                                variant="outline"
                                onClick={() => navigate(-1)}
                                disabled={isLoading}
                            >
                                Cancel
                            </Button>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    );
}
