import { useContext } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
    AlertCircle,
    Building2,
    Calendar,
    FolderGit2,
    Globe,
    Loader2,
    MapPin,
    Settings,
    Star,
    UserPlus,
    UserRoundCheck,
} from 'lucide-react';
import { toast } from 'sonner';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import { getContributionHeatmap, getSubscriberCount, getUserInfo, getUserProjects, getUserRepos, subscribeTarget, unsubscribeTarget } from '@/client';
import { UserContext } from '@/contexts/user-context';

const resolveCount = (payload: unknown): number => {
    if (typeof payload === 'number') return payload;
    if (payload && typeof payload === 'object') {
        const record = payload as Record<string, unknown>;
        const values = [record.count, record.total, record.subscriber_count, record.subscription_count, record.value];
        for (const value of values) {
            if (typeof value === 'number') return value;
            if (typeof value === 'string') {
                const parsed = Number(value);
                if (Number.isFinite(parsed)) return parsed;
            }
        }
    }
    if (typeof payload === 'string') {
        const parsed = Number(payload);
        return Number.isFinite(parsed) ? parsed : 0;
    }
    return 0;
};

const formatDate = (value?: string | null) => {
    if (!value) return '-';
    const date = new Date(value);
    if (Number.isNaN(date.getTime())) return '-';
    return date.toLocaleDateString('en-US', {
        year: 'numeric',
        month: 'short',
        day: 'numeric',
    });
};

const resolveHeatLevel = (count: number, max: number) => {
    if (count <= 0) return 0;
    if (max <= 1) return 4;
    const ratio = count / max;
    if (ratio < 0.25) return 1;
    if (ratio < 0.5) return 2;
    if (ratio < 0.75) return 3;
    return 4;
};

const ContributionHeatmap = ({
    totalContributions,
    heatmap,
    isLoading,
    isError,
}: {
    totalContributions: number;
    heatmap: Array<{ date: string; count: number }>;
    isLoading: boolean;
    isError: boolean;
}) => {
    if (isLoading) {
        return (
            <Card className="border-border/40">
                <CardContent className="py-6">
                    <div className="flex items-center justify-between mb-4">
                        <span className="text-sm font-medium">Contribution Activity</span>
                    </div>
                    <div className="flex items-center gap-2 text-sm text-muted-foreground">
                        <Loader2 className="h-4 w-4 animate-spin" />
                        Loading activity data...
                    </div>
                </CardContent>
            </Card>
        );
    }

    if (isError) {
        return (
            <Card className="border-border/40">
                <CardContent className="py-6">
                    <div className="flex items-center justify-between mb-4">
                        <span className="text-sm font-medium">Contribution Activity</span>
                    </div>
                    <p className="text-sm text-muted-foreground">Unable to load contribution data.</p>
                </CardContent>
            </Card>
        );
    }

    const recentHeatmap = heatmap.slice(-52 * 7);

    const firstDate = recentHeatmap[0]?.date ? new Date(recentHeatmap[0].date) : new Date();
    const leadingPadding = firstDate.getDay();
    const paddedHeatmap: Array<{ date: string; count: number }> = [
        ...Array.from({ length: leadingPadding }, () => ({ date: '', count: -1 })),
        ...recentHeatmap,
    ];

    const maxCount = Math.max(
        1,
        recentHeatmap.reduce((max, item) => Math.max(max, item.count), 0),
    );
    const totalWeeks = Math.ceil(paddedHeatmap.length / 7);
    const weeks = Array.from({ length: totalWeeks }, (_, weekIndex) =>
        paddedHeatmap.slice(weekIndex * 7, weekIndex * 7 + 7),
    );

    const months: Array<{ label: string; weekIndex: number }> = [];
    let lastMonth = -1;
    weeks.forEach((week, weekIndex) => {
        const validDay = week.find((d) => d.date);
        if (validDay?.date) {
            const date = new Date(validDay.date);
            const month = date.getMonth();
            if (month !== lastMonth) {
                months.push({
                    label: date.toLocaleDateString('en-US', { month: 'short' }),
                    weekIndex,
                });
                lastMonth = month;
            }
        }
    });

    const dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    const getColorClass = (count: number) => {
        if (count < 0) return 'bg-transparent';
        if (count === 0) return 'bg-muted/80 dark:bg-muted/40';
        const level = resolveHeatLevel(count, maxCount);
        switch (level) {
            case 1:
                return 'bg-emerald-200 dark:bg-emerald-900/60';
            case 2:
                return 'bg-emerald-300 dark:bg-emerald-700/70';
            case 3:
                return 'bg-emerald-400 dark:bg-emerald-600/80';
            case 4:
                return 'bg-emerald-500 dark:bg-emerald-500';
            default:
                return 'bg-muted/80 dark:bg-muted/40';
        }
    };

    return (
        <Card className="border-border/40">
            <CardContent className="py-5 px-4 md:px-6">
                <div className="flex items-center justify-between mb-3">
                    <span className="text-sm font-medium">
                        {totalContributions.toLocaleString()} contributions in the last year
                    </span>
                </div>

                <div className="overflow-hidden">
                    <div className="inline-block min-w-full">
                        <div className="flex mb-1 ml-8 text-xs text-muted-foreground/70 relative h-4">
                            {months.map((month, idx) => (
                                <span
                                    key={`month-${idx}`}
                                    className="absolute"
                                    style={{
                                        left: `${month.weekIndex * 13}px`,
                                    }}
                                >
                                    {month.label}
                                </span>
                            ))}
                        </div>

                        <div className="flex gap-[3px] mt-2">
                            <div className="flex flex-col gap-[3px] pr-2 text-[10px] text-muted-foreground/60">
                                {dayLabels.map((day, idx) => (
                                    <span
                                        key={day}
                                        className="h-[10px] leading-[10px]"
                                        style={{ visibility: idx % 2 === 1 ? 'visible' : 'hidden' }}
                                    >
                                        {day}
                                    </span>
                                ))}
                            </div>
                            <div className="flex gap-[3px]">
                                {weeks.map((week, weekIndex) => (
                                    <div key={`week-${weekIndex}`} className="flex flex-col gap-[3px]">
                                        {week.map((item, dayIndex) => (
                                            <span
                                                key={`day-${weekIndex}-${dayIndex}`}
                                                title={
                                                    item.count >= 0
                                                        ? item.date
                                                            ? `${item.count} contributions on ${item.date}`
                                                            : 'No contributions'
                                                        : undefined
                                                }
                                                className={`h-[10px] w-[10px] rounded-sm ${getColorClass(item.count)} ${
                                                    item.count >= 0 ? 'cursor-pointer hover:ring-1 hover:ring-foreground/20' : ''
                                                }`}
                                            />
                                        ))}
                                    </div>
                                ))}
                            </div>
                        </div>
                    </div>
                </div>

                <div className="flex items-center justify-between mt-3 text-[11px] text-muted-foreground/60">
                    <span className="hover:text-primary hover:underline cursor-pointer">
                        Learn how we count contributions
                    </span>
                    <div className="flex items-center gap-1">
                        <span>Less</span>
                        <span className="h-[10px] w-[10px] rounded-sm bg-muted/80 dark:bg-muted/40" />
                        <span className="h-[10px] w-[10px] rounded-sm bg-emerald-200 dark:bg-emerald-900/60" />
                        <span className="h-[10px] w-[10px] rounded-sm bg-emerald-300 dark:bg-emerald-700/70" />
                        <span className="h-[10px] w-[10px] rounded-sm bg-emerald-400 dark:bg-emerald-600/80" />
                        <span className="h-[10px] w-[10px] rounded-sm bg-emerald-500 dark:bg-emerald-500" />
                        <span>More</span>
                    </div>
                </div>
            </CardContent>
        </Card>
    );
};

export function UserProfile() {
    const { user: routeUser } = useParams<{ user?: string }>();
    const targetUser = (routeUser ?? '').trim();
    const currentUser = useContext(UserContext);
    const isAuth = currentUser !== null;
    const queryClient = useQueryClient();
    const nav = useNavigate();

    const userInfoKey = ['user-info', targetUser] as const;
    const subscriberCountKey = ['user-subscriber-count', targetUser] as const;
    const contributionHeatmapKey = ['user-contribution-heatmap', targetUser] as const;
    const userProjectsKey = ['user-projects', targetUser] as const;
    const userReposKey = ['user-repos', targetUser] as const;

    const invalidateProfileQueries = () => {
        queryClient.invalidateQueries({ queryKey: userInfoKey });
        queryClient.invalidateQueries({ queryKey: subscriberCountKey });
        queryClient.invalidateQueries({ queryKey: contributionHeatmapKey });
    };

    const {
        data: userInfo,
        isLoading: userLoading,
        error,
        isError,
    } = useQuery({
        queryKey: userInfoKey,
        enabled: Boolean(targetUser),
        queryFn: async () => {
            const resp = await getUserInfo({ path: { username: targetUser } });
            return resp.data?.data ?? null;
        },
        retry: false,
    });

    const { data: subscriberCount, isLoading: subscriberLoading } = useQuery({
        queryKey: subscriberCountKey,
        enabled: Boolean(targetUser) && Boolean(userInfo),
        queryFn: async () => {
            const result = await getSubscriberCount({ path: { username: targetUser } });
            return resolveCount(result.data);
        },
        retry: false,
    });

    const {
        data: contributionHeatmap,
        isLoading: contributionHeatmapLoading,
        isError: isContributionHeatmapError,
    } = useQuery({
        queryKey: contributionHeatmapKey,
        enabled: Boolean(targetUser) && Boolean(userInfo),
        queryFn: async () => {
            const resp = await getContributionHeatmap({ path: { username: targetUser } });
            return resp.data?.data ?? null;
        },
        retry: false,
    });

    const { data: userProjects } = useQuery({
        queryKey: userProjectsKey,
        enabled: Boolean(targetUser) && Boolean(userInfo),
        queryFn: async () => {
            const resp = await getUserProjects({ path: { username: targetUser } });
            return resp.data?.data ?? null;
        },
        retry: false,
    });

    const { data: userRepos } = useQuery({
        queryKey: userReposKey,
        enabled: Boolean(targetUser) && Boolean(userInfo),
        queryFn: async () => {
            const resp = await getUserRepos({ path: { username: targetUser } });
            return resp.data?.data ?? null;
        },
        retry: false,
    });

    const followMutation = useMutation({
        mutationFn: async () => {
            await subscribeTarget({ path: { username: targetUser } });
        },
        onSuccess: () => {
            toast.success(`You are now following @${targetUser}`);
            invalidateProfileQueries();
        },
        onError: () => toast.error('Failed to follow this user'),
    });

    const unfollowMutation = useMutation({
        mutationFn: async () => {
            await unsubscribeTarget({ path: { username: targetUser } });
        },
        onSuccess: () => {
            toast.success(`You unfollowed @${targetUser}`);
            invalidateProfileQueries();
        },
        onError: () => toast.error('Failed to unfollow this user'),
    });

    const notFound = isError && (error as { status?: number })?.status === 404;
    const failed = isError && !notFound;

    if (targetUser == null || targetUser.trim() === '') {
        return (
            <div className="min-h-screen bg-gradient-to-b from-muted/20 to-background">
                <main className="mx-auto min-h-[60vh] max-w-3xl px-6 py-20">
                    <Card className="border-border/40">
                        <CardHeader>
                            <CardTitle>User not found</CardTitle>
                        </CardHeader>
                        <CardContent>
                            <p className="text-sm text-muted-foreground">The profile link is incomplete.</p>
                        </CardContent>
                    </Card>
                </main>
            </div>
        );
    }

    if (notFound) {
        return (
            <div className="min-h-screen bg-gradient-to-b from-muted/20 to-background">
                <main className="mx-auto flex min-h-[60vh] max-w-4xl items-center px-6 py-20">
                    <Card className="w-full border-border/40">
                        <CardHeader className="text-center">
                            <div className="mx-auto mb-4 rounded-full bg-muted/50 p-4 w-fit">
                                <AlertCircle className="h-8 w-8 text-muted-foreground" />
                            </div>
                            <CardTitle>User not found</CardTitle>
                            <p className="text-sm text-muted-foreground mt-2">
                                The account <span className="font-medium">@{targetUser}</span> does not exist or has been removed.
                            </p>
                        </CardHeader>
                        <CardContent className="text-center">
                            <Link
                                to="/"
                                className="inline-flex items-center justify-center gap-1.5 rounded-lg border border-border bg-background px-2.5 py-1 text-sm font-medium whitespace-nowrap transition-all outline-none select-none hover:bg-muted hover:text-foreground"
                            >
                                Back to home
                            </Link>
                        </CardContent>
                    </Card>
                </main>
            </div>
        );
    }

    if (failed) {
        return (
            <div className="min-h-screen bg-gradient-to-b from-muted/20 to-background">
                <main className="mx-auto min-h-[60vh] max-w-3xl px-6 py-20">
                    <Card className="border-border/40">
                        <CardHeader>
                            <CardTitle>Unable to load profile</CardTitle>
                        </CardHeader>
                        <CardContent>
                            <p className="text-sm text-muted-foreground">Please refresh the page and try again.</p>
                        </CardContent>
                    </Card>
                </main>
            </div>
        );
    }

    if (userLoading || !userInfo) {
        return (
            <div className="min-h-screen bg-gradient-to-b from-muted/20 to-background">
                <main className="mx-auto min-h-[60vh] max-w-5xl px-6 py-20">
                    <div className="flex items-center gap-2 text-sm text-muted-foreground">
                        <Loader2 className="h-4 w-4 animate-spin" />
                        Loading profile...
                    </div>
                </main>
            </div>
        );
    }

    const isMutating = followMutation.isPending || unfollowMutation.isPending;

    const handleFollowToggle = () => {
        if (userInfo.is_subscribe) {
            unfollowMutation.mutate();
            return;
        }
        followMutation.mutate();
    };

    const projects = userProjects?.projects ?? [];
    const repos = userRepos?.repos ?? [];

    return (
        <div className="min-h-screen bg-gradient-to-b from-muted/20 to-background">
            <main className="mx-auto flex w-full max-w-5xl flex-col gap-6 px-6 pb-16 pt-8 md:pt-12">
                {/* Profile Header */}
                <section className="rounded-xl border border-border/40 bg-card/80 backdrop-blur-sm">
                    <div className="p-6 md:p-8">
                        <div className="flex flex-col gap-6 md:flex-row md:items-start md:justify-between">
                            <div className="flex items-start gap-5">
                                <Avatar className="h-16 w-16 border-2 border-border/60 shadow-sm">
                                    <AvatarImage src={userInfo.avatar_url ?? undefined} alt={userInfo.username} />
                                    <AvatarFallback className="bg-muted text-lg font-medium">
                                        {userInfo.display_name.charAt(0).toUpperCase()}
                                    </AvatarFallback>
                                </Avatar>
                                <div className="space-y-1.5">
                                    <div className="flex flex-wrap items-center gap-2">
                                        <h1 className="text-xl font-semibold tracking-tight md:text-2xl">{userInfo.display_name}</h1>
                                        {userInfo.is_owner && (
                                            <Badge variant="secondary" className="font-normal">
                                                You
                                            </Badge>
                                        )}
                                    </div>
                                    <p className="text-sm text-muted-foreground">@{userInfo.username}</p>

                                    <div className="flex flex-wrap items-center gap-x-4 gap-y-1 pt-1 text-sm">
                                        <span className="text-muted-foreground">
                                            <strong className="font-semibold text-foreground">
                                                {subscriberLoading ? '-' : subscriberCount || 0}
                                            </strong>{' '}
                                            followers
                                        </span>
                                        <span className="text-muted-foreground">
                                            <strong className="font-semibold text-foreground">{userInfo.total_projects}</strong> projects
                                        </span>
                                        <span className="text-muted-foreground">
                                            <strong className="font-semibold text-foreground">{userInfo.total_repos}</strong> repos
                                        </span>
                                    </div>
                                </div>
                            </div>

                            <div className="flex items-center gap-2">
                                {userInfo.is_owner ? (
                                    <Button variant="outline" size="sm" onClick={() => nav('/settings/profile')}>
                                        <Settings className="mr-2 h-4 w-4" />
                                        Edit Profile
                                    </Button>
                                ) : isAuth ? (
                                    <Button
                                        onClick={handleFollowToggle}
                                        disabled={isMutating}
                                        variant={userInfo.is_subscribe ? 'outline' : 'default'}
                                        size="sm"
                                    >
                                        {isMutating ? (
                                            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                                        ) : userInfo.is_subscribe ? (
                                            <UserRoundCheck className="mr-2 h-4 w-4" />
                                        ) : (
                                            <UserPlus className="mr-2 h-4 w-4" />
                                        )}
                                        {userInfo.is_subscribe ? 'Following' : 'Follow'}
                                    </Button>
                                ) : (
                                    <Link
                                    to="/auth/login"
                                    className="inline-flex items-center justify-center gap-1 rounded-[min(var(--radius-md,0.375rem),12px)] h-7 px-2.5 text-[0.8rem] whitespace-nowrap bg-primary text-primary-foreground hover:bg-primary/80"
                                >
                                    Sign in to follow
                                </Link>
                                )}
                            </div>
                        </div>
                    </div>

                    <Separator className="bg-border/40" />
                    <div className="flex flex-wrap items-center gap-x-6 gap-y-2 px-6 py-3 text-sm text-muted-foreground md:px-8">
                        {userInfo.organization && (
                            <span className="flex items-center gap-1.5">
                                <Building2 className="h-4 w-4" />
                                {userInfo.organization}
                            </span>
                        )}
                        <span className="flex items-center gap-1.5">
                            <MapPin className="h-4 w-4" />
                            {userInfo.timezone}
                        </span>
                        {userInfo.website_url && (
                            <a
                                href={userInfo.website_url}
                                target="_blank"
                                rel="noreferrer"
                                className="flex items-center gap-1.5 transition-colors hover:text-foreground"
                            >
                                <Globe className="h-4 w-4" />
                                {userInfo.website_url.replace(/^https?:\/\//, '')}
                            </a>
                        )}
                        <span className="flex items-center gap-1.5">
                            <Calendar className="h-4 w-4" />
                            Active {formatDate(userInfo.last_sign_in_at)}
                        </span>
                    </div>
                </section>

                {/* Contribution Heatmap */}
                <ContributionHeatmap
                    totalContributions={contributionHeatmap?.total_contributions ?? 0}
                    heatmap={contributionHeatmap?.heatmap ?? []}
                    isLoading={contributionHeatmapLoading}
                    isError={isContributionHeatmapError}
                />

                {/* Projects & Repositories */}
                <section className="grid gap-6 lg:grid-cols-2">
                    <Card className="border-border/40 bg-card/50">
                        <CardHeader className="pb-4">
                            <CardTitle className="text-sm font-medium">Top Projects</CardTitle>
                        </CardHeader>
                        <CardContent>
                            {projects.length === 0 ? (
                                <div className="rounded-lg border border-dashed border-border/60 p-6 text-center">
                                    <FolderGit2 className="mx-auto h-8 w-8 text-muted-foreground/40" />
                                    <p className="mt-2 text-sm text-muted-foreground">No public projects</p>
                                </div>
                            ) : (
                                <div className="space-y-3">
                                    {projects.slice(0, 5).map((project) => (
                                        <Link
                                            key={project.uid}
                                            to={`/project/${project.name}`}
                                            className="block rounded-lg border border-border/40 p-4 transition-all hover:border-border hover:bg-muted/30"
                                        >
                                            <div className="flex items-start justify-between gap-3">
                                                <div className="min-w-0 flex-1">
                                                    <p className="truncate font-medium">{project.display_name}</p>
                                                    <p className="mt-1 truncate text-sm text-muted-foreground">
                                                        {project.description || project.name}
                                                    </p>
                                                </div>
                                            </div>
                                            <div className="mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground/70">
                                                <span>{project.member_count} members</span>
                                                <span>·</span>
                                                <span>{project.is_public ? 'Public' : 'Private'}</span>
                                                <span>·</span>
                                                <span>Updated {formatDate(project.updated_at)}</span>
                                            </div>
                                        </Link>
                                    ))}
                                </div>
                            )}
                        </CardContent>
                    </Card>

                    <Card className="border-border/40 bg-card/50">
                        <CardHeader className="pb-4">
                            <CardTitle className="text-sm font-medium">Top Repositories</CardTitle>
                        </CardHeader>
                        <CardContent>
                            {repos.length === 0 ? (
                                <div className="rounded-lg border border-dashed border-border/60 p-6 text-center">
                                    <Star className="mx-auto h-8 w-8 text-muted-foreground/40" />
                                    <p className="mt-2 text-sm text-muted-foreground">No public repositories</p>
                                </div>
                            ) : (
                                <div className="space-y-3">
                                    {repos.slice(0, 5).map((repo) => (
                                        <Link
                                            key={repo.uid}
                                            to={`/repository/${userInfo.username}/${repo.repo_name}`}
                                            className="block rounded-lg border border-border/40 p-4 transition-all hover:border-border hover:bg-muted/30"
                                        >
                                            <div className="flex items-start justify-between gap-3">
                                                <div className="min-w-0 flex-1">
                                                    <p className="truncate font-medium">
                                                        {userInfo.username}/{repo.repo_name}
                                                    </p>
                                                    <p className="mt-1 truncate text-sm text-muted-foreground">
                                                        {repo.description || `Branch: ${repo.default_branch}`}
                                                    </p>
                                                </div>
                                                <div className="flex items-center gap-1 text-xs text-muted-foreground">
                                                    <Star className="h-3.5 w-3.5" />
                                                    0
                                                </div>
                                            </div>
                                            <div className="mt-3 flex flex-wrap items-center gap-2 text-xs text-muted-foreground/70">
                                                <span>{repo.is_private ? 'Private' : 'Public'}</span>
                                                <span>·</span>
                                                <span>Updated {formatDate(repo.updated_at)}</span>
                                            </div>
                                        </Link>
                                    ))}
                                </div>
                            )}
                        </CardContent>
                    </Card>
                </section>
            </main>
        </div>
    );
}
