import React, { useCallback, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { MoreHorizontal, Trash2, UserPlus, Mail } from "lucide-react";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "sonner";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { InputControl } from "@/components/form/control/input.control";
import { SelectControl } from "@/components/form/control/select.control";
import { api } from "@/lib/trpc/client";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuTrigger
} from "@/components/ui/dropdown-menu";
import { Form } from "@/components/ui/form";
import { SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { MemberRole, MemberRoleHelpers } from "@/server/modules/organization/types/member-role.enum";
import { InvitationStatus, InvitationStatusHelpers } from "@/server/modules/organization/types/invitation-status.enum";
import { Badge } from "@/components/ui/badge";

const inviteSchema = z.object({
    email: z.string().email("Indtast en gyldig email"),
    role: z.nativeEnum(MemberRole)
});

type InviteFormValues = z.infer<typeof inviteSchema>;

type MemberListProps = {
    organizationId: string;
};

export const MemberList: React.FC<MemberListProps> = (props) => {
    const { organizationId } = props;

    const utils = api.useUtils();
    const [isInviting, setIsInviting] = useState(false);

    const { data: currentUser } = api.auth.user.useQuery();

    const { isLoading, data: organization } = api.organization.get.useQuery({
        with: ["invitations", "members"],
        id: organizationId
    });

    const inviteMemberMutation = api.organization.member.invite.useMutation({
        async onSuccess() {
            await utils.organization.get.invalidate();
            toast.success("Invitation sendt");
            setIsInviting(false);
            form.reset();
        },
        onError(error) {
            toast.error(error.message || "Der skete en fejl");
        }
    });

    const deleteMemberMutation = api.organization.member.delete.useMutation({
        async onSuccess() {
            await utils.organization.get.invalidate();
            toast.success("Medlem fjernet");
        }
    });

    const cancelInvitationMutation = api.organization.invitation.cancel.useMutation({
        async onSuccess() {
            await utils.organization.get.invalidate();
            toast.success("Invitation annulleret");
        }
    });

    const updateMemberMutation = api.organization.member.update.useMutation({
        async onSuccess() {
            await utils.organization.get.invalidate();
            toast.success("Rolle opdateret");
        }
    });

    const form = useForm<InviteFormValues>({
        resolver: zodResolver(inviteSchema),
        defaultValues: {
            email: "",
            role: MemberRole.MEMBER
        }
    });

    const onInvite = useCallback(
        async (values: InviteFormValues) => {
            await inviteMemberMutation.mutateAsync({
                organizationId,
                email: values.email,
                role: values.role
            });
        },
        [inviteMemberMutation, organizationId]
    );

    const handleDeleteMember = useCallback(
        async (memberId: string) => {
            // TODO: Make modal conformation
            if (confirm("Er du sikker på, at du vil fjerne dette medlem?")) {
                await deleteMemberMutation.mutateAsync({
                    id: memberId
                });
            }
        },
        [deleteMemberMutation]
    );

    const handleDeleteInvitation = useCallback(
        async (invitationId: string) => {
            // TODO: Make modal conformation
            if (confirm("Er du sikker på, at du vil annullere denne invitation?")) {
                await cancelInvitationMutation.mutateAsync({
                    id: invitationId
                });
            }
        },
        [cancelInvitationMutation]
    );

    const handleUpdateRole = useCallback(
        async (memberId: string, role: MemberRole) => {
            await updateMemberMutation.mutateAsync({
                id: memberId,
                data: {
                    role
                }
            });
        },
        [updateMemberMutation]
    );

    const currentMember = useMemo(() => {
        if (!currentUser || !organization?.members) return null;

        return organization.members.find((m) => m.userId === currentUser.id);
    }, [currentUser, organization]);

    const canManage = currentMember && [MemberRole.OWNER, MemberRole.ADMIN].includes(currentMember.role);

    if (isLoading) {
        return <Skeleton className='h-80 w-full' />;
    }

    if (!organization) {
        return null;
    }

    return (
        <Card className='w-full rounded-none border-0 bg-neutral-100 font-serif shadow-none'>
            <CardHeader className='flex flex-row items-center justify-between space-y-0 pb-7'>
                <div>
                    <CardTitle className='text-2xl'>Teammedlemmer</CardTitle>

                    <p className='text-muted-foreground font-sans text-sm'>
                        Administrer hvem der har adgang til denne organisation
                    </p>
                </div>

                {canManage && !isInviting && (
                    <Button size='sm' onClick={() => setIsInviting(true)}>
                        <UserPlus className='mr-2 h-4 w-4' />
                        Inviter
                    </Button>
                )}
            </CardHeader>

            <CardContent className='space-y-6'>
                {isInviting && (
                    <div className='bg-muted/50 rounded-lg p-4 font-sans'>
                        <Form {...form}>
                            <form
                                onSubmit={form.handleSubmit(onInvite)}
                                className='flex flex-col gap-4 md:flex-row md:items-end'
                            >
                                <InputControl containerClassName='flex-1' placeholder='Email adresse' name='email' />

                                <SelectControl containerClassName='w-full md:w-40' name='role'>
                                    <SelectTrigger>
                                        <SelectValue placeholder='Vælg rolle' />
                                    </SelectTrigger>

                                    <SelectContent>
                                        <SelectItem value={MemberRole.MEMBER}>
                                            {MemberRoleHelpers.getLabel(MemberRole.MEMBER)}
                                        </SelectItem>
                                        <SelectItem value={MemberRole.ADMIN}>
                                            {MemberRoleHelpers.getLabel(MemberRole.ADMIN)}
                                        </SelectItem>
                                    </SelectContent>
                                </SelectControl>

                                <div className='flex gap-2'>
                                    <Button type='submit' disabled={inviteMemberMutation.isPending}>
                                        {inviteMemberMutation.isPending ? "Sender..." : "Send invitation"}
                                    </Button>

                                    <Button type='button' variant='ghost' onClick={() => setIsInviting(false)}>
                                        Annuller
                                    </Button>
                                </div>
                            </form>
                        </Form>
                    </div>
                )}

                <div className='font-sans'>
                    <Table>
                        <TableHeader>
                            <TableRow>
                                <TableHead>Bruger</TableHead>
                                <TableHead />
                                <TableHead>Rolle</TableHead>
                                <TableHead className='w-[100px] text-right'>Handlinger</TableHead>
                            </TableRow>
                        </TableHeader>

                        <TableBody>
                            {organization.members.map((member) => {
                                return (
                                    <TableRow key={member.id}>
                                        <TableCell>
                                            <div className='flex flex-col'>
                                                <span className='font-medium'>
                                                    {member.user.name || "Navn mangler"}
                                                </span>
                                                <span className='text-muted-foreground text-xs'>
                                                    {member.user.email}
                                                </span>
                                            </div>
                                        </TableCell>

                                        <TableCell />

                                        <TableCell>
                                            <Badge variant='outline' className='capitalize'>
                                                {MemberRoleHelpers.getLabel(member.role)}
                                            </Badge>
                                        </TableCell>

                                        <TableCell className='text-right'>
                                            {canManage &&
                                                member.userId !== currentUser?.id &&
                                                member.role !== MemberRole.OWNER && (
                                                    <DropdownMenu>
                                                        <DropdownMenuTrigger asChild>
                                                            <Button variant='ghost' size='icon'>
                                                                <MoreHorizontal className='h-4 w-4' />
                                                            </Button>
                                                        </DropdownMenuTrigger>

                                                        <DropdownMenuContent align='end'>
                                                            <DropdownMenuItem
                                                                onClick={() =>
                                                                    handleUpdateRole(
                                                                        member.id,
                                                                        member.role === MemberRole.ADMIN
                                                                            ? MemberRole.MEMBER
                                                                            : MemberRole.ADMIN
                                                                    )
                                                                }
                                                            >
                                                                Gør til{" "}
                                                                {member.role === MemberRole.ADMIN
                                                                    ? "medlem"
                                                                    : "administrator"}
                                                            </DropdownMenuItem>

                                                            <DropdownMenuItem
                                                                className='text-destructive'
                                                                onClick={() => handleDeleteMember(member.id)}
                                                            >
                                                                <Trash2 className='mr-2 h-4 w-4' />
                                                                Fjern medlem
                                                            </DropdownMenuItem>
                                                        </DropdownMenuContent>
                                                    </DropdownMenu>
                                                )}
                                        </TableCell>
                                    </TableRow>
                                );
                            })}

                            {organization.invitations.map((invitation) => (
                                <TableRow key={invitation.id} className='bg-muted/30'>
                                    <TableCell>
                                        <div className='flex items-center gap-2'>
                                            <Mail className='text-muted-foreground h-4 w-4' />

                                            <div className='flex flex-col'>
                                                <span className='font-medium'>{invitation.email}</span>
                                                <span className='text-muted-foreground text-xs'>Afventer...</span>
                                            </div>
                                        </div>
                                    </TableCell>

                                    <TableCell>{InvitationStatusHelpers.getLabel(invitation.status)}</TableCell>

                                    <TableCell>
                                        <Badge variant='secondary' className='capitalize'>
                                            {MemberRoleHelpers.getLabel(invitation.role)} (inviteret)
                                        </Badge>
                                    </TableCell>

                                    <TableCell className='text-right'>
                                        {canManage && invitation.status === InvitationStatus.PENDING && (
                                            <Button
                                                variant='ghost'
                                                size='icon'
                                                className='text-destructive'
                                                onClick={() => handleDeleteInvitation(invitation.id)}
                                            >
                                                <Trash2 className='h-4 w-4' />
                                            </Button>
                                        )}
                                    </TableCell>
                                </TableRow>
                            ))}
                        </TableBody>
                    </Table>
                </div>
            </CardContent>
        </Card>
    );
};
