"use client";

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/app/shadcn_components/ui/table";
import { Input } from "@/app/shadcn_components/ui/input";
import { Button } from "@/app/shadcn_components/ui/button";

import { useState } from "react";
import { Role, RoleDropdown, Collaborator } from "@/app/portfolio/[slug]/(portfolio)/settings/roles";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";



async function getPortfolioUsers(portfolioId: string): Promise<Collaborator[]> {
  const res = await fetch(`/api/portfolio/${portfolioId}/colloborators`, {
    method: "GET",
    headers: { "Content-Type": "application/json" },
  });
  if (!res.ok) throw new Error("Failed to fetch users");
  const json = await res.json();
  const users = Array.isArray(json) ? json : json.users; // support both shapes
  // Guard + shape to Collaborator[]
  return Array.isArray(users)
    ? users.map((u: any) => ({
          portfolioUserId: String(u.portfolioUserId),
          userId: String(u.userId),
          name: u.name ?? null,
          email: u.email ?? "",
          role: u.role,
        }))
    : [];
}

async function updatePortfolioUserRole(
  portfolioId: string,
  portfolioUserId: string,
  role: Role
): Promise<void> {
  const res = await fetch(`/api/portfolio/${portfolioId}/colloborators`, {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ portfolioUserId, role }),
  });
  if (!res.ok) {
    const msg = await res.text().catch(() => "");
    throw new Error(msg || "Failed to update role");
  }
}

async function invitePortfolioUser(
  portfolioId: string,
  email: string,
  role: Role,
  name: string
): Promise<void> {
  const res = await fetch(`/api/portfolio/${portfolioId}/colloborators`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ email, role, name }),
  });
  if (!res.ok) {
    const msg = await res.text().catch(() => "");
    throw new Error(msg || "Failed to invite user");
  }
}


export function UsersPermissionsCard({ portfolioId }: { portfolioId: string }) {
  const [inviteEmail, setInviteEmail] = useState("");
  const [inviteRole, setInviteRole] = useState<Role>("read");
  const [inviteName, setInviteName] = useState("");

  const queryClient = useQueryClient();

  const {
    data: collaborators = [],
    isLoading,
    isFetching,
    refetch,
  } = useQuery({
    queryKey: ["portfolioUsers", portfolioId],
    queryFn: () => getPortfolioUsers(portfolioId),
    enabled: !!portfolioId,             // only run when id is present
    refetchOnWindowFocus: false,        // optional: avoid surprise refetch logs
    onSuccess: (data) => {
      console.log("Fetched users for portfolio:", data);
    },
    onError: (err) => {
      console.error("Error fetching users:", err);
    },
  });

  const changeRoleMutation = useMutation({
    mutationFn: ({ portfolioUserId, role }: { portfolioUserId: string; role: Role }) =>
      updatePortfolioUserRole(portfolioId, portfolioUserId, role),

    // Optimistic update
    onMutate: async ({ portfolioUserId, role }) => {
      await queryClient.cancelQueries({ queryKey: ["portfolioUsers", portfolioId] });
      const previous = queryClient.getQueryData<Collaborator[]>(["portfolioUsers", portfolioId]);

      // Optimistically update cache
      queryClient.setQueryData<Collaborator[]>(
        ["portfolioUsers", portfolioId],
        (old) =>
          (old ?? []).map((c) =>
            c.portfolioUserId === portfolioUserId ? { ...c, role } : c
          )
      );

      // Return context to rollback on error
      return { previous };
    },

    // Rollback on error
    onError: (err, _vars, context) => {
      if (context?.previous) {
        queryClient.setQueryData(["portfolioUsers", portfolioId], context.previous);
      }
      console.error("Failed to update role:", err);
    },

    // Always revalidate after success/error
    onSettled: () => {
      queryClient.invalidateQueries({ queryKey: ["portfolioUsers", portfolioId] });
    },
  });

  // ADD: mutation for inviting a user
  const inviteUserMutation = useMutation({
    mutationFn: ({ email, role, name }: { email: string; role: Role; name: string }) =>
      invitePortfolioUser(portfolioId, email, role, name),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["portfolioUsers", portfolioId] });
      setInviteEmail("");
      setInviteName("");  // clear name after success
      // setInviteRole("read");
    },
    onError: (err) => {
      console.error("Invite failed:", err);
    },
  });


  function handleInvite() {
    inviteUserMutation.mutate({ email: inviteEmail, role: inviteRole, name: inviteName });
  }

  function onChangeRole(portfolioUserId: string, role: Role) {
    console.log(`Change portfolioUserId ${portfolioUserId} to ${role}`);
    changeRoleMutation.mutate({ portfolioUserId, role });
  }

  function onRemove(portfolioUserId: string) {
    console.log(`This button will delete the row portoflioUserId ${portfolioUserId}`);
    console.log("This was not implemented as Jun-te wanted to avoid Delete via drizzle before Database integrirty")
    // TODO: DELETE user -> then refetch()
  }

  return (
    <div className="rounded-md border border-gray-700 mt-2">
      <Table>
        <TableBody>
          <TableRow>
            <TableHead className="text-brandblue">
              Users Permission:
              <p className="text-xs text-gray-500">Add users and manage roles</p>
            </TableHead>
            <TableCell className="text-right">
              <Button variant="outline" onClick={() => refetch()} disabled={isFetching || isLoading}>
                {isFetching || isLoading ? "Loading..." : "Refresh Users"}
              </Button>
            </TableCell>
          </TableRow>

          {/* Invite row */}
          <TableRow>
            <TableHead className="text-brandblue">
              Add a user
              <p className="text-xs text-gray-500">
                Invite by email and choose a role
              </p>
            </TableHead>
            <TableCell className="flex gap-2 items-center">
              <Input
                type="text"
                placeholder="Full name"
                value={inviteName}
                onChange={(e) => setInviteName(e.target.value)}
              />
              <Input
                type="email"
                placeholder="email@example.com"
                value={inviteEmail}
                onChange={(e) => setInviteEmail(e.target.value)}
              />
              <div className="min-w-40">
                <RoleDropdown value={inviteRole} onChange={setInviteRole} />
              </div>
            </TableCell>
            <TableCell className="text-right">
            <Button
              className="w-28"
              onClick={handleInvite}
              disabled={!inviteEmail || !inviteName || inviteUserMutation.isPending}
            >
              {inviteUserMutation.isPending ? "Inviting..." : "Invite"}
            </Button>
            </TableCell>
          </TableRow>

          {/* Current collaborators list */}
          <TableRow>
            <TableHead className="text-brandblue">
              Current users
              <p className="text-xs text-gray-500">Update roles or remove access</p>
            </TableHead>
            <TableCell colSpan={2}>
              <div className="rounded-md border border-gray-200">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Name</TableHead>
                      <TableHead>Email</TableHead>
                      <TableHead>Role</TableHead>
                      <TableHead className="text-right">Actions</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {isLoading ? (
                      <TableRow>
                        <TableCell colSpan={4} className="text-sm text-gray-500">Loading…</TableCell>
                      </TableRow>
                    ) : collaborators.length === 0 ? (
                      <TableRow>
                        <TableCell colSpan={4} className="text-sm text-gray-500">
                          No users yet.
                        </TableCell>
                      </TableRow>
                    ) : (
                      collaborators.map((c) => (
                        <TableRow key={c.email}>
                          <TableCell>{c.name || "—"}</TableCell>
                          <TableCell>{c.email}</TableCell>
                          <TableCell className="min-w-40">
                            {c.role === "creator" || c.role === "admin" ? (
                              <span className="text-xs font-medium text-gray-500 px-2 py-1 bg-gray-100 rounded-md capitalize">
                                {c.role}
                              </span>
                            ) : (
                              <RoleDropdown value={c.role as "read" | "write"} onChange={(r) => onChangeRole(c.portfolioUserId, r)} />
                            )}
                          </TableCell>
                          <TableCell className="text-right">
                            {c.role !== "creator" && (
                              <Button variant="destructive" className="bg-red-700" onClick={() => onRemove(c.portfolioUserId)}>
                                Remove
                              </Button>
                            )}
                          </TableCell>
                        </TableRow>
                      ))
                    )}
                  </TableBody>
                </Table>
              </div>
            </TableCell>
          </TableRow>
        </TableBody>
      </Table>
    </div>
  );
}