"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import { Avatar } from "@/components/ui/avatar";
import {
  X,
  Loader2,
  UserPlus,
  Trash2,
  Users,
  ChevronDown,
} from "lucide-react";
import type { IJMAPClient } from "@/lib/jmap/client-interface";
import type { Principal } from "@/lib/jmap/types";
import { useSharingStore, type SharedResourceKind } from "@/stores/sharing-store";

export interface ShareFolderDialogProps {
  client: IJMAPClient;
  resourceId: string;
  resourceName: string;
  resourceKind: SharedResourceKind;
  onClose: () => void;
}

const PRESET_OPTIONS: Record<SharedResourceKind, readonly string[]> = {
  mailbox: ["read", "readWrite", "manager"],
  calendar: ["read", "readWrite", "manager"],
  addressBook: ["read", "readWrite", "manager"],
  file: ["read", "readWrite", "manager"],
};

export function ShareFolderDialog({
  client,
  resourceId,
  resourceName,
  resourceKind,
  onClose,
}: ShareFolderDialogProps) {
  const t = useTranslations("sharing");
  const tCommon = useTranslations("common");
  const modalRef = useRef<HTMLDivElement>(null);

  const sharedByMe = useSharingStore((s) => s.sharedByMe);
  const loadPrincipals = useSharingStore((s) => s.loadPrincipals);
  const shareFolder = useSharingStore((s) => s.shareFolder);
  const revokeShare = useSharingStore((s) => s.revokeShare);
  const changeRole = useSharingStore((s) => s.changeRole);

  const [allPrincipals, setAllPrincipals] = useState<Principal[]>([]);
  const [loadingPrincipals, setLoadingPrincipals] = useState(true);
  const [search, setSearch] = useState("");
  const [savingId, setSavingId] = useState<string | null>(null);
  const [showAdd, setShowAdd] = useState(false);
  const [message, setMessage] = useState("");

  useEffect(() => {
    let cancelled = false;
    setLoadingPrincipals(true);
    loadPrincipals(client)
      .then((list) => {
        if (cancelled) return;
        setAllPrincipals(list);
        setLoadingPrincipals(false);
      })
      .catch(() => {
        if (!cancelled) setLoadingPrincipals(false);
      });
    return () => {
      cancelled = true;
    };
  }, [client, loadPrincipals]);

  const ownAccountId = client.getAccountId();

  const allPrincipalsById = useMemo(() => {
    const map = new Map<string, Principal>();
    for (const p of allPrincipals) map.set(p.id, p);
    return map;
  }, [allPrincipals]);

  const currentShares = sharedByMe.filter(
    (f) => f.resourceId === resourceId && f.resourceKind === resourceKind,
  );

  const principals = useMemo(() => {
    const existing = new Set(currentShares.map((s) => s.principalId));
    return allPrincipals.filter(
      (p) => p.id !== ownAccountId && !existing.has(p.id),
    );
  }, [allPrincipals, ownAccountId, currentShares]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, [onClose]);

  const handleRemove = async (principalId: string) => {
    setSavingId(principalId);
    try {
      await revokeShare(client, resourceId, resourceKind, principalId);
    } catch {
      /* error toast comes from store */
    } finally {
      setSavingId(null);
    }
  };

  const handleChangeRole = async (principalId: string, role: string) => {
    setSavingId(principalId);
    try {
      await changeRole(client, resourceId, resourceKind, principalId, role);
    } catch {
      /* error toast comes from store */
    } finally {
      setSavingId(null);
    }
  };

  const handleAdd = async (principal: Principal) => {
    setSavingId(principal.id);
    try {
      await shareFolder(
        client,
        resourceId,
        resourceName,
        resourceKind,
        principal.id,
        "read",
        message || undefined,
      );
      setShowAdd(false);
      setSearch("");
      setMessage("");
    } catch {
      /* error toast comes from store */
    } finally {
      setSavingId(null);
    }
  };

  const filteredPrincipals = useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return principals;
    return principals.filter(
      (p) =>
        p.name.toLowerCase().includes(q) ||
        p.email?.toLowerCase().includes(q) ||
        p.description?.toLowerCase().includes(q),
    );
  }, [principals, search]);

  const presetOptions = PRESET_OPTIONS[resourceKind];

  const kindLabels: Record<SharedResourceKind, string> = {
    mailbox: "Mail folder",
    calendar: "Calendar",
    addressBook: "Address book",
    file: "File folder",
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      <div
        className="absolute inset-0 bg-black/50 backdrop-blur-[1px]"
        onClick={onClose}
        aria-hidden="true"
      />
      <div
        ref={modalRef}
        role="dialog"
        aria-modal="true"
        aria-label={t("title", { name: resourceName })}
        className="relative bg-background border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 animate-in zoom-in-95 duration-200 max-h-[85vh] flex flex-col"
      >
        <div className="flex items-center justify-between px-6 py-4 border-b border-border">
          <div className="flex items-center gap-2">
            <Users className="w-5 h-5 text-primary" />
            <div>
              <h2 className="text-lg font-semibold">
                {t("title", { name: resourceName })}
              </h2>
              <p className="text-xs text-muted-foreground">
                {kindLabels[resourceKind]}
              </p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="p-1.5 rounded-md hover:bg-muted transition-colors duration-150 text-muted-foreground hover:text-foreground"
            aria-label={tCommon("close")}
          >
            <X className="w-5 h-5" />
          </button>
        </div>

        <div className="px-6 py-4 space-y-4 overflow-y-auto">
          <p className="text-sm text-muted-foreground">
            {t("description")}
          </p>

          {currentShares.length === 0 && !showAdd && (
            <div className="text-sm text-muted-foreground italic py-4 text-center">
              {t("no_shares")}
            </div>
          )}

          {currentShares.length > 0 && (
            <ul className="divide-y divide-border rounded-md border border-border overflow-hidden">
              {currentShares.map((share) => {
                const principal = allPrincipalsById.get(share.principalId);
                return (
                  <li
                    key={share.id}
                    className="flex items-center gap-3 px-3 py-2.5"
                  >
                    <Avatar
                      name={principal?.name}
                      email={principal?.email ?? undefined}
                      size="sm"
                      className="shrink-0"
                    />
                    <div className="flex-1 min-w-0">
                      <div className="text-sm font-medium truncate">
                        {principal?.name ||
                          principal?.email ||
                          share.principalId}
                      </div>
                      {principal?.description && (
                        <div className="text-xs text-muted-foreground truncate">
                          {principal.description}
                        </div>
                      )}
                    </div>
                    <div className="relative">
                      <select
                        value={share.role}
                        onChange={(e) =>
                          handleChangeRole(share.principalId, e.target.value)
                        }
                        disabled={savingId === share.principalId}
                        className="appearance-none rounded-md border border-input bg-background ps-3 pe-8 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
                      >
                        {presetOptions.map((p) => (
                          <option key={p} value={p}>
                            {t(`preset.${p}`)}
                          </option>
                        ))}
                        {share.role === "custom" && (
                          <option value="custom">
                            {t("preset.custom")}
                          </option>
                        )}
                      </select>
                      <ChevronDown className="w-3 h-3 absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none text-muted-foreground" />
                    </div>
                    <button
                      onClick={() => handleRemove(share.principalId)}
                      disabled={savingId === share.principalId}
                      className="p-1.5 rounded-md hover:bg-destructive/10 text-muted-foreground hover:text-destructive transition-colors disabled:opacity-50"
                      aria-label={t("remove")}
                      title={t("remove")}
                    >
                      {savingId === share.principalId ? (
                        <Loader2 className="w-4 h-4 animate-spin" />
                      ) : (
                        <Trash2 className="w-4 h-4" />
                      )}
                    </button>
                  </li>
                );
              })}
            </ul>
          )}

          {!showAdd && (
            <Button
              variant="outline"
              onClick={() => setShowAdd(true)}
              className="w-full"
            >
              <UserPlus className="w-4 h-4 me-2" />
              {t("add_person")}
            </Button>
          )}

          {showAdd && (
            <div className="space-y-2 border border-border rounded-md p-3">
              <input
                type="text"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                placeholder={t("search_placeholder")}
                className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
                autoFocus
              />
              <div className="max-h-48 overflow-y-auto -mx-1">
                {loadingPrincipals && (
                  <div className="flex items-center justify-center py-4 text-muted-foreground">
                    <Loader2 className="w-4 h-4 animate-spin me-2" />
                    {t("loading_principals")}
                  </div>
                )}
                {!loadingPrincipals &&
                  filteredPrincipals.length === 0 && (
                    <div className="text-xs text-muted-foreground text-center py-3">
                      {search.trim()
                        ? t("no_match")
                        : t("no_principals")}
                    </div>
                  )}
                {!loadingPrincipals &&
                  filteredPrincipals.map((p) => (
                    <button
                      key={p.id}
                      onClick={() => handleAdd(p)}
                      disabled={savingId === p.id}
                      className="w-full text-start px-3 py-2 rounded-md hover:bg-muted disabled:opacity-50 transition-colors"
                    >
                      <div className="flex items-center gap-2">
                        <Avatar
                          name={p.name}
                          email={p.email ?? undefined}
                          size="sm"
                          className="shrink-0"
                        />
                        <div className="flex-1 min-w-0">
                          <div className="text-sm font-medium truncate flex items-center gap-2">
                            {p.name}
                            {p.type === "group" && (
                              <span className="text-[10px] uppercase font-normal text-muted-foreground bg-muted rounded px-1 py-0.5">
                                {t("group")}
                              </span>
                            )}
                          </div>
                          {p.email && p.email !== p.name && (
                            <div className="text-xs text-muted-foreground truncate">
                              {p.email}
                            </div>
                          )}
                        </div>
                        {savingId === p.id && (
                          <Loader2 className="w-4 h-4 animate-spin" />
                        )}
                      </div>
                    </button>
                  ))}
              </div>
              <textarea
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                placeholder="Optional message…"
                rows={2}
                className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring resize-none"
              />
              <div className="flex justify-end pt-1">
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() => {
                    setShowAdd(false);
                    setSearch("");
                    setMessage("");
                  }}
                >
                  {tCommon("cancel")}
                </Button>
              </div>
            </div>
          )}
        </div>

        <div className="flex items-center justify-end gap-2 px-6 py-4 border-t border-border">
          <Button onClick={onClose}>{tCommon("close")}</Button>
        </div>
      </div>
    </div>
  );
}
