import {
    Activity,
    ChevronDown,
    ChevronRight,
    CircleDot,
    GitBranch,
    GitCommitHorizontal,
    GitPullRequest,
    Loader2,
    MessageSquare,
    Plus,
    Settings,
    Star,
    Tag,
    UserMinus,
    UserPlus,
    Users,
    Watch,
} from 'lucide-react';
import {format, formatDistanceToNow, isToday, isYesterday, parseISO} from 'date-fns';
import {enUS, zhCN} from 'date-fns/locale';
import {useNavigate} from 'react-router-dom';
import {useState} from 'react';
import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query';
import {
    projectActivities,
    projectLike,
    projectUnlike,
    projectWatch,
    projectUnwatch,
} from '@/client';
import {useProject} from '@/contexts';
import {Badge} from '@/components/ui/badge';
import {Button} from '@/components/ui/button';
import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card';
import {Spinner} from '@/components/ui/spinner';

/** Activity log item shape (inferred from API response) */
type ActivityLog = {
    id: number;
    actor_uid: string;
    event_type: string;
    title: string;
    content: string | null;
    metadata: Record<string, unknown> | null;
    created_at: string;
};

/** Event type group: same date + same event_type */
type EventGroup = {
    key: string;
    event_type: string;
    items: ActivityLog[];
};

/** Date group: a single date label, contains multiple event type groups */
type DateGroup = {
    date: string;          // "Today", "Yesterday", or "MMM dd"
    groups: EventGroup[];
};

function formatDate(date: Date, _locale: string): string {
    if (isToday(date)) return 'Today';
    if (isYesterday(date)) return 'Yesterday';
    return format(date, 'MMM dd');
}

function groupActivities(logs: ActivityLog[], locale: string): DateGroup[] {
    // Step 1: group by date + event_type
    const eventGroups: Map<string, EventGroup> = new Map();
    const dateOrder: string[] = [];

    for (const log of logs) {
        const date = parseISO(log.created_at);
        const dateKey = format(date, 'yyyy-MM-dd');
        const key = `${dateKey}|${log.event_type}`;

        if (!eventGroups.has(key)) {
            eventGroups.set(key, {key, event_type: log.event_type, items: []});
            dateOrder.push(dateKey);
        }
        eventGroups.get(key)!.items.push(log);
    }

    // Step 2: group by date (dedupe while preserving order)
    const dateGroups: Map<string, DateGroup> = new Map();
    for (const dateKey of dateOrder) {
        if (!dateGroups.has(dateKey)) {
            const d = new Date(dateKey + 'T00:00:00Z');
            dateGroups.set(dateKey, {date: formatDate(d, locale), groups: []});
        }
    }

    for (const eg of eventGroups.values()) {
        const dateKey = eg.key.split('|')[0];
        dateGroups.get(dateKey)!.groups.push(eg);
    }

    return Array.from(dateGroups.values());
}

function EventIcon({type}: { type: string }) {
    const cls = 'h-3.5 w-3.5';
    const stripped = type.replace(/^(project_|repo_)/, '');
    switch (stripped) {
        case 'commit_push':
            return <GitCommitHorizontal className={cls}/>;
        case 'branch_create':
        case 'branch_delete':
        case 'branch_rename':
            return <GitBranch className={cls}/>;
        case 'tag_create':
        case 'tag_delete':
            return <Tag className={cls}/>;
        case 'issue_open':
        case 'issue_reopen':
            return <CircleDot className={cls}/>;
        case 'issue_close':
            return <CircleDot className={`${cls} text-green-500`}/>;
        case 'issue_comment':
            return <MessageSquare className={cls}/>;
        case 'pr_open':
        case 'pr_update':
            return <GitPullRequest className={cls}/>;
        case 'pr_merge':
            return <GitPullRequest className={`${cls} text-purple-500`}/>;
        case 'pr_close':
            return <GitPullRequest className={`${cls} text-red-500`}/>;
        case 'room_message':
            return <MessageSquare className={cls}/>;
        case 'room_create':
            return <Plus className={cls}/>;
        case 'star':
            return <Star className={`${cls} text-yellow-500`}/>;
        case 'member_add':
            return <UserPlus className={cls}/>;
        case 'member_remove':
            return <UserMinus className={cls}/>;
        case 'label_create':
        case 'label_update':
            return <Tag className={cls}/>;
        default:
            return <Activity className={cls}/>;
    }
}

function EventTypeLabel({type}: { type: string }) {
    const stripped = type.replace(/^(project_|repo_)/, '');
    const map: Record<string, string> = {
        commit_push: 'Commit',
        branch_create: 'Branch',
        branch_delete: 'Branch',
        tag_create: 'Tag',
        issue_open: 'Issue',
        issue_close: 'Issue',
        issue_comment: 'Comment',
        pr_open: 'Pull Request',
        pr_update: 'Pull Request',
        pr_merge: 'Merged',
        pr_close: 'Pull Request',
        room_message: 'Message',
        room_create: 'Room',
        star: 'Starred',
        unstar: 'Unstarred',
        watch: 'Watched',
        unwatch: 'Unwatched',
        member_add: 'Member',
        member_remove: 'Member',
        label_create: 'Label',
        repo_create: 'Repo',
    };
    return <span className="text-xs font-medium">{map[stripped] ?? stripped}</span>;
}

function getEventAccent(type: string): string {
    if (type.includes('commit')) return 'text-blue-500';
    if (type.includes('issue')) return 'text-orange-500';
    if (type.includes('pr') || type.includes('merge')) return 'text-purple-500';
    if (type.includes('star')) return 'text-yellow-500';
    if (type.includes('member')) return 'text-green-500';
    if (type.includes('room')) return 'text-pink-500';
    if (type.includes('branch') || type.includes('tag')) return 'text-indigo-500';
    return 'text-muted-foreground';
}

/** Get actor display name from metadata.username or fall back to actor_uid */
function getActorDisplayName(actorUid: string, metadata: Record<string, unknown> | null): string {
    return (metadata?.username as string | undefined) ?? actorUid;
}

/** Replace uid substring in title with actor display name */
function getActivityTitle(
    title: string,
    actorUid: string,
    actorDisplayName: string,
): string {
    // UUID v4 pattern: 8-4-4-4-12 hex
    const uuidPattern = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
    if (actorUid.match(uuidPattern) && title.includes(actorUid)) {
        return title.replace(actorUid, actorDisplayName);
    }
    return title;
}

export function ProjectOverview() {
    const {project, isLoading} = useProject();
    const navigate = useNavigate();
    const locale: string = 'en';
    const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());

    const canManage = project?.role === 'Owner' || project?.role === 'Admin';

    const {data: activityData, isLoading: activityLoading} = useQuery({
        queryKey: ['projectActivities', project?.name],
        queryFn: async () => {
            const resp = await projectActivities({
                path: {project_name: project!.name},
                query: {page: 1, per_page: 15},
            });
            return resp.data?.data ?? null;
        },
        enabled: !!project?.name,
    });

    const queryClient = useQueryClient();

    // Read like/watch state directly from React Query cache (for optimistic update support)
    const cachedProject = queryClient.getQueryData<typeof project>(['projectInfo', project?.name]);
    const is_like = cachedProject?.is_like ?? project?.is_like ?? false;
    const is_watch = cachedProject?.is_watch ?? project?.is_watch ?? false;

    const likeMutation = useMutation({
        mutationFn: async () => {
            if (is_like) {
                await projectUnlike({path: {project_name: project!.name}});
            } else {
                await projectLike({path: {project_name: project!.name}});
            }
        },
        onMutate: async () => {
            await queryClient.cancelQueries({queryKey: ['projectInfo', project?.name]});
            const previous = queryClient.getQueryData<typeof project>(['projectInfo', project?.name]);
            queryClient.setQueryData(['projectInfo', project?.name], (old: typeof project) => {
                if (!old) return old;
                return {
                    ...old,
                    is_like: !old.is_like,
                    like_count: old.is_like ? old.like_count - 1 : old.like_count + 1,
                };
            });
            return {previous};
        },
        onError: (_err, _vars, context) => {
            queryClient.setQueryData(['projectInfo', project?.name], context?.previous);
        },
        onSettled: () => {
            queryClient.invalidateQueries({queryKey: ['projectInfo', project?.name]});
            queryClient.invalidateQueries({queryKey: ['projectActivities', project?.name]});
        },
    });

    const watchMutation = useMutation({
        mutationFn: async () => {
            if (is_watch) {
                await projectUnwatch({path: {project_name: project!.name}});
            } else {
                await projectWatch({path: {project_name: project!.name}});
            }
        },
        onMutate: async () => {
            await queryClient.cancelQueries({queryKey: ['projectInfo', project?.name]});
            const previous = queryClient.getQueryData<typeof project>(['projectInfo', project?.name]);
            queryClient.setQueryData(['projectInfo', project?.name], (old: typeof project) => {
                if (!old) return old;
                return {
                    ...old,
                    is_watch: !old.is_watch,
                    watch_count: old.is_watch ? old.watch_count - 1 : old.watch_count + 1,
                };
            });
            return {previous};
        },
        onError: (_err, _vars, context) => {
            queryClient.setQueryData(['projectInfo', project?.name], context?.previous);
        },
        onSettled: () => {
            queryClient.invalidateQueries({queryKey: ['projectInfo', project?.name]});
            queryClient.invalidateQueries({queryKey: ['projectActivities', project?.name]});
        },
    });

    if (isLoading) {
        return (
            <div className="flex items-center justify-center h-64">
                <Spinner/>
            </div>
        );
    }

    if (!project) {
        return (
            <div className="p-6 text-center text-muted-foreground">
                Project not found.
            </div>
        );
    }

    return (
        <div className="flex-1 p-6">
            <div className="flex items-start justify-between gap-4 mb-4">
                <div className="flex items-center gap-3">
                    <div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10">
                        <span className="text-xl font-bold text-primary">
                            {project.display_name?.charAt(0)?.toUpperCase() ||
                                project.name?.charAt(0)?.toUpperCase() ||
                                'P'}
                        </span>
                    </div>
                    <div>
                        <h1 className="text-2xl font-bold">
                            {project.display_name || project.name}
                        </h1>
                        <p className="text-sm text-muted-foreground">
                            {project.description || 'No description provided'}
                        </p>
                    </div>
                </div>
                <div className="flex gap-2 shrink-0">
                    {canManage && (
                        <Button
                            variant="outline"
                            size="sm"
                            onClick={() => navigate(`/project/${project.name}/settings`)}
                        >
                            <Settings className="mr-2 h-4 w-4"/>
                            Settings
                        </Button>
                    )}
                </div>
            </div>

            {/* Stats */}
            <div className="flex items-center gap-4 text-sm mb-6">
                <span className="text-muted-foreground">
                    <strong className="font-semibold text-foreground">{project.member_count}</strong> members
                </span>
                <Button
                    variant="outline"
                    size="sm"
                    className="gap-1.5"
                    onClick={() => likeMutation.mutate()}
                    disabled={likeMutation.isPending}
                >
                    {is_like ? (
                        <Star className="h-4 w-4 fill-yellow-400 text-yellow-400"/>
                    ) : (
                        <Star className="h-4 w-4"/>
                    )}
                    <strong className="font-semibold">{cachedProject?.like_count ?? project?.like_count ?? 0}</strong>
                    likes
                </Button>
                <Button
                    variant="outline"
                    size="sm"
                    className="gap-1.5"
                    onClick={() => watchMutation.mutate()}
                    disabled={watchMutation.isPending}
                >
                    <Watch className={`h-4 w-4 ${is_watch ? 'fill-blue-400 text-blue-400' : ''}`}/>
                    <strong className="font-semibold">{cachedProject?.watch_count ?? project?.watch_count ?? 0}</strong>
                    watches
                </Button>
                <Badge variant={project.is_public ? 'default' : 'secondary'}>
                    {project.is_public ? 'Public' : 'Private'}
                </Badge>
            </div>

            {/* Main 2-col layout */}
            <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
                <Card className="lg:col-span-2">
                    <CardHeader>
                        <div className="flex items-center justify-between">
                            <CardTitle className="flex items-center gap-2">
                                <Activity className="h-5 w-5"/>
                                Activity
                            </CardTitle>
                            <Button
                                variant="ghost"
                                size="sm"
                                className="text-xs h-5 px-1.5"
                                onClick={() => navigate(`/project/${project.name}/activity`)}
                            >
                                View all
                            </Button>
                        </div>
                    </CardHeader>
                    <CardContent>
                        <p className="text-xs text-muted-foreground mb-3">Recent events in this project</p>
                        {activityLoading ? (
                            <div className="flex items-center justify-center py-12">
                                <Loader2 className="h-6 w-6 animate-spin text-muted-foreground"/>
                            </div>
                        ) : activityData?.logs.length === 0 ? (
                            <div className="flex flex-col items-center justify-center py-12 text-center">
                                <Activity className="h-8 w-8 text-muted-foreground/30 mb-2"/>
                                <p className="text-sm text-muted-foreground">No activity yet.</p>
                            </div>
                        ) : (
                            (() => {
                                const dateGroups = groupActivities((activityData?.logs as unknown as ActivityLog[] ?? []), locale);
                                return (
                                    <div className="space-y-6">
                                        {dateGroups.map((dateGroup) => (
                                            <div key={dateGroup.date}>
                                                {/* Date label — once per date */}
                                                <p className="text-xs font-semibold text-muted-foreground mb-3 uppercase tracking-wide">
                                                    {dateGroup.date}
                                                </p>

                                                <div className="space-y-3">
                                                    {dateGroup.groups.map((group) => {
                                                        const isExpanded = expandedGroups.has(group.key);
                                                        const count = group.items.length;
                                                        const first = group.items[0];

                                                        return (
                                                            <div key={group.key}>
                                                                <div className="divide-y">
                                                                    {isExpanded
                                                                        ? group.items.map((log) => (
                                                                              <div
                                                                                  key={log.id}
                                                                                  className="flex items-start gap-3 py-2.5 hover:bg-muted/30 -mx-3 px-3 rounded-md transition-colors"
                                                                              >
                                                                                  <div className={`mt-0.5 shrink-0 ${getEventAccent(log.event_type)}`}>
                                                                                      <EventIcon type={log.event_type}/>
                                                                                  </div>
                                                                                  <div className="flex-1 min-w-0">
                                                                                      <div className="flex items-center gap-2">
                                                                                          <EventTypeLabel type={log.event_type}/>
                                                                                          <p className="text-sm font-medium truncate">
                                                                                              {getActivityTitle(
                                                                                                  log.title,
                                                                                                  log.actor_uid,
                                                                                                  getActorDisplayName(log.actor_uid, log.metadata),
                                                                                              )}
                                                                                          </p>
                                                                                      </div>
                                                                                      {log.content && (
                                                                                          <p className="text-xs text-muted-foreground mt-0.5 truncate">
                                                                                              {log.content}
                                                                                          </p>
                                                                                      )}
                                                                                  </div>
                                                                                  <span className="text-xs text-muted-foreground shrink-0 mt-0.5">
                                                                                      {formatDistanceToNow(parseISO(log.created_at), {
                                                                                          addSuffix: true,
                                                                                          locale: locale === 'zh' ? zhCN : enUS,
                                                                                      })}
                                                                                  </span>
                                                                              </div>
                                                                          ))
                                                                        : (
                                                                              <div className="flex items-start gap-3 py-2.5">
                                                                                  <div className={`mt-0.5 shrink-0 ${getEventAccent(group.event_type)}`}>
                                                                                      <EventIcon type={group.event_type}/>
                                                                                  </div>
                                                                                  <div className="flex-1 min-w-0">
                                                                                      <div className="flex items-center gap-2">
                                                                                          <EventTypeLabel type={group.event_type}/>
                                                                                          <p className="text-sm font-medium truncate">
                                                                                              {getActivityTitle(
                                                                                                  first.title,
                                                                                                  first.actor_uid,
                                                                                                  getActorDisplayName(first.actor_uid, first.metadata),
                                                                                              )}
                                                                                          </p>
                                                                                          {count > 1 && (
                                                                                              <Badge variant="secondary" className="text-xs shrink-0">
                                                                                                  ×{count}
                                                                                              </Badge>
                                                                                          )}
                                                                                      </div>
                                                                                      {first.content && (
                                                                                          <p className="text-xs text-muted-foreground mt-0.5 truncate">
                                                                                              {first.content}
                                                                                          </p>
                                                                                      )}
                                                                                  </div>
                                                                                  <button
                                                                                      className="shrink-0 text-xs text-muted-foreground hover:text-primary transition-colors flex items-center gap-0.5"
                                                                                      onClick={() => setExpandedGroups((prev) => {
                                                                                          const next = new Set(prev);
                                                                                          next.add(group.key);
                                                                                          return next;
                                                                                      })}
                                                                                  >
                                                                                      <ChevronRight className="h-3 w-3"/>
                                                                                      Expand
                                                                                  </button>
                                                                              </div>
                                                                          )
                                                                    }
                                                                </div>

                                                                {isExpanded && count > 1 && (
                                                                    <button
                                                                        className="mt-1 text-xs text-muted-foreground hover:text-primary transition-colors flex items-center gap-0.5 pl-1"
                                                                        onClick={() => setExpandedGroups((prev) => {
                                                                            const next = new Set(prev);
                                                                            next.delete(group.key);
                                                                            return next;
                                                                        })}
                                                                    >
                                                                        <ChevronDown className="h-3 w-3"/>
                                                                        Collapse
                                                                    </button>
                                                                )}
                                                            </div>
                                                        );
                                                    })}
                                                </div>
                                            </div>
                                        ))}
                                    </div>
                                );
                            })()
                        )}
                    </CardContent>
                </Card>

                {/* Right: Project Info + Quick Actions */}
                <div className="space-y-4">
                    <Card>
                        <CardHeader>
                            <CardTitle className="flex items-center gap-2 text-sm">
                                <GitBranch className="h-4 w-4"/>
                                Project Info
                            </CardTitle>
                        </CardHeader>
                        <CardContent>
                            <div className="space-y-2">
                                <div className="flex items-center gap-2 text-sm">
                                    <span className="text-muted-foreground w-24 shrink-0">Project name</span>
                                    <span className="font-medium truncate">{project.name}</span>
                                </div>
                                <div className="flex items-center gap-2 text-sm">
                                    <span className="text-muted-foreground w-24 shrink-0">Your role</span>
                                    <Badge variant="outline" className="text-xs">{project.role || 'Guest'}</Badge>
                                </div>
                                <div className="flex items-center gap-2 text-sm">
                                    <span className="text-muted-foreground w-24 shrink-0">Created</span>
                                    <span>
                                        {formatDistanceToNow(new Date(project.created_at), {
                                            addSuffix: true,
                                        })}
                                    </span>
                                </div>
                                <div className="flex items-center gap-2 text-sm">
                                    <span className="text-muted-foreground w-24 shrink-0">Visibility</span>
                                    <Badge variant={project.is_public ? 'default' : 'secondary'} className="text-xs">
                                        {project.is_public ? 'Public' : 'Private'}
                                    </Badge>
                                </div>
                            </div>
                        </CardContent>
                    </Card>

                    <Card>
                        <CardHeader>
                            <CardTitle className="flex items-center gap-2 text-sm">
                                <Plus className="h-4 w-4"/>
                                Quick Actions
                            </CardTitle>
                        </CardHeader>
                        <CardContent>
                            <div className="space-y-1.5">
                            <Button
                                variant="outline"
                                className="w-full justify-start text-sm h-9"
                                onClick={() => navigate(`/project/${project.name}/issues/new`)}
                            >
                                <Plus className="mr-2 h-4 w-4"/>
                                New Issue
                            </Button>
                            <Button
                                variant="outline"
                                className="w-full justify-start text-sm h-9"
                                onClick={() => navigate(`/project/${project.name}/activity`)}
                            >
                                <Activity className="mr-2 h-4 w-4"/>
                                View Activity
                            </Button>
                            <Button
                                variant="outline"
                                className="w-full justify-start text-sm h-9"
                                onClick={() => navigate(`/project/${project.name}/members`)}
                            >
                                <Users className="mr-2 h-4 w-4"/>
                                Members
                            </Button>
                            {canManage && (
                                <Button
                                    variant="outline"
                                    className="w-full justify-start text-sm h-9"
                                    onClick={() => navigate(`/init/repository?project=${project?.name}`)}
                                >
                                    <Plus className="mr-2 h-4 w-4"/>
                                    Create Repository
                                </Button>
                            )}
                        </div>
                        </CardContent>
                    </Card>
                </div>
            </div>
        </div>
    );
}
