import { AdminVerification } from "../../web/components/admin-verification";
import { useState } from "react";
import { createFileRoute, Link } from "@tanstack/react-router";
import { Exit } from "effect";
import { useAtomValue, useAtomSet } from "@effect/atom-react";
import { trackEvent } from "@executor-js/react/api/analytics";
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
import { useCustomer } from "autumn-js/react";
import { toast } from "sonner";
import { orgDomainWriteKeys, authWriteKeys } from "@executor-js/react/api/reactivity-keys";
import { Button } from "@executor-js/react/components/button";
import { Badge } from "@executor-js/react/components/badge";
import { Input } from "@executor-js/react/components/input";
import { Label } from "@executor-js/react/components/label";
import { CopyButton } from "@executor-js/react/components/copy-button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from "@executor-js/react/components/dialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@executor-js/react/components/dropdown-menu";
import { orgMembersAtom } from "@executor-js/react/api/account-atoms";
import { OrgPage as SharedOrgPage } from "@executor-js/react/pages/org";
import { orgDomainsAtom, getDomainVerificationLink, deleteDomain } from "../../web/org-atoms";
import { deleteOrganization, useAuth } from "../../web/auth";

// ---------------------------------------------------------------------------
// Cloud organization page. The members / roles / invite / org-name surface is
// the SHARED `@executor-js/react` OrgPage over the provider-neutral
// `/account/*` atoms — identical to self-host. Cloud composes its WorkOS-only
// extras AROUND that page:
//   - a seat/billing banner (Autumn member-limit upsell)
//   - the WorkOS domain-verification section (over the surviving cloud-local
//     `/org/domains` endpoints)
// These are cloud additions, not a fork of the shared page.
// ---------------------------------------------------------------------------

export const Route = createFileRoute("/{-$orgSlug}/org")({
  component: OrgPage,
});

type DomainData = {
  id: string;
  domain: string;
  state: string;
  verificationToken?: string;
  verificationPrefix?: string;
};

function OrgPage() {
  return (
    <AdminVerification>
      <OrganizationSettings />
    </AdminVerification>
  );
}

function OrganizationSettings() {
  return (
    <div className="min-h-0 flex-1 overflow-y-auto">
      {/* Shared members / roles / invite / org-name surface. */}
      <SharedOrgPage
        domainsSection={<DomainsSection />}
        upgradeAction={
          <Link to="/{-$orgSlug}/billing/plans">
            <Button size="sm">Upgrade plan</Button>
          </Link>
        }
        dangerZoneSection={<DangerZoneSection />}
      />
    </div>
  );
}

// Destructive org teardown, admin-only. Hidden entirely for non-admins (the
// backend enforces admin + name-confirmation regardless). Deleting the org
// removes the workspace and all of its data for every member, cancels billing,
// and logs the caller out.
function DangerZoneSection() {
  const auth = useAuth();
  const membersResult = useAtomValue(orgMembersAtom);
  const doDelete = useAtomSet(deleteOrganization, { mode: "promiseExit" });
  const [open, setOpen] = useState(false);
  const [confirmText, setConfirmText] = useState("");
  const [deleting, setDeleting] = useState(false);

  const organizationName = auth.status === "authenticated" ? auth.organization?.name : undefined;

  // Only admins may delete. Derive the caller's role from the members list
  // (already loaded for this page); render nothing while it loads or for
  // members, so a delete control never flashes for someone who can't use it.
  const isAdmin = AsyncResult.match(membersResult, {
    onInitial: () => false,
    onFailure: () => false,
    onSuccess: ({ value }) =>
      value.members.some((m) => m.isCurrentUser && m.status === "active" && m.role === "admin"),
  });

  if (!isAdmin || !organizationName) return null;

  const confirmed = confirmText.trim() === organizationName.trim();

  const handleDelete = async () => {
    if (!confirmed || deleting) return;
    setDeleting(true);
    const exit = await doDelete({
      payload: { confirmName: confirmText.trim() },
      reactivityKeys: authWriteKeys,
    });
    trackEvent("org_deleted", { success: Exit.isSuccess(exit) });
    if (Exit.isSuccess(exit)) {
      // The org (and the caller's session) are gone. A full navigation resets
      // all app state and lets the auth gate rehydrate to another membership or
      // the create-org screen.
      toast.success(`Deleted ${organizationName}`);
      window.location.href = "/";
      return;
    }
    setDeleting(false);
    toast.error("Failed to delete organization");
  };

  return (
    <section className="mb-2 border-t border-border pt-8">
      <div className="flex items-center justify-between rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3">
        <div className="min-w-0">
          <h2 className="text-sm font-medium text-destructive">Delete organization</h2>
          <p className="mt-0.5 text-sm text-muted-foreground">
            Permanently delete this organization and all of its data for every member. This cannot
            be undone.
          </p>
        </div>
        <Button
          size="sm"
          variant="destructive"
          className="ml-4 shrink-0"
          onClick={() => {
            setConfirmText("");
            setOpen(true);
          }}
        >
          Delete
        </Button>
      </div>

      <Dialog
        open={open}
        onOpenChange={(v) => {
          if (deleting) return;
          if (!v) setConfirmText("");
          setOpen(v);
        }}
      >
        <DialogContent className="sm:max-w-[440px]">
          <DialogHeader>
            <DialogTitle className="font-display text-xl">Delete organization</DialogTitle>
            <DialogDescription className="text-sm leading-relaxed">
              This permanently deletes{" "}
              <span className="font-medium text-foreground">{organizationName}</span>, including
              every integration, connection, credential, and policy, for all members. Billing is
              canceled and everyone loses access immediately. This cannot be undone.
            </DialogDescription>
          </DialogHeader>

          <div className="grid gap-1.5 py-1">
            <Label
              htmlFor="delete-org-confirm"
              className="text-sm font-medium uppercase tracking-wider text-muted-foreground"
            >
              Type <span className="font-mono normal-case text-foreground">{organizationName}</span>{" "}
              to confirm
            </Label>
            <Input
              id="delete-org-confirm"
              autoComplete="off"
              value={confirmText}
              onChange={(e) => setConfirmText((e.target as HTMLInputElement).value)}
              onKeyDown={(e) => {
                if (e.key === "Enter") handleDelete();
              }}
              className="h-9 text-sm"
            />
          </div>

          <DialogFooter>
            <DialogClose asChild>
              <Button variant="ghost" size="sm" disabled={deleting}>
                Cancel
              </Button>
            </DialogClose>
            <Button
              size="sm"
              variant="destructive"
              onClick={handleDelete}
              disabled={!confirmed || deleting}
            >
              {deleting ? "Deleting…" : "Delete organization"}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </section>
  );
}

function DomainsSection() {
  const domainsResult = useAtomValue(orgDomainsAtom);
  const doDeleteDomain = useAtomSet(deleteDomain, { mode: "promiseExit" });
  const doGetVerificationLink = useAtomSet(getDomainVerificationLink, {
    mode: "promiseExit",
  });
  const { check, isLoading: customerLoading } = useCustomer();
  const canUseDomains = customerLoading
    ? false
    : check({ featureId: "domain-verification" }).allowed;

  const handleDeleteDomain = async (domainId: string, domain: string) => {
    const exit = await doDeleteDomain({
      params: { domainId },
      reactivityKeys: orgDomainWriteKeys,
    });
    trackEvent("org_domain_removed", { success: Exit.isSuccess(exit) });
    toast[Exit.isSuccess(exit) ? "success" : "error"](
      Exit.isSuccess(exit) ? `Removed ${domain}` : "Failed to remove domain",
    );
  };

  const handleAddDomain = async () => {
    const exit = await doGetVerificationLink({
      reactivityKeys: orgDomainWriteKeys,
    });
    trackEvent("org_domain_added", { success: Exit.isSuccess(exit) });
    if (Exit.isSuccess(exit)) {
      window.open(exit.value.link, "_blank");
    } else {
      toast.error("Failed to generate verification link");
    }
  };

  return (
    <section className="mb-2">
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="text-sm font-medium text-foreground">Domains</h2>
          <p className="mt-0.5 text-sm text-muted-foreground">
            Verify a domain to let anyone with a matching email join automatically.
          </p>
        </div>
        <Button size="sm" className="min-w-32" disabled={!canUseDomains} onClick={handleAddDomain}>
          Add domain
        </Button>
      </div>

      {!canUseDomains && (
        <div className="mb-3 flex items-center justify-between rounded-lg border border-border px-4 py-3">
          <p className="text-sm text-muted-foreground">
            Join by domain is available on the Team plan.
          </p>
          <Link to="/{-$orgSlug}/billing/plans">
            <Button size="sm" variant="outline">
              Upgrade
            </Button>
          </Link>
        </div>
      )}

      {AsyncResult.match(domainsResult, {
        onInitial: () => (
          <div className="space-y-3">
            {[1, 2].map((i) => (
              <div key={i} className="h-16 animate-pulse rounded-lg bg-muted/50" />
            ))}
          </div>
        ),
        onFailure: () => (
          <div className="rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-3">
            <p className="text-sm text-destructive">Failed to load domains</p>
          </div>
        ),
        onSuccess: ({ value }) => {
          if (value.domains.length === 0) {
            if (!canUseDomains) return null;
            return (
              <p className="py-6 text-center text-sm text-muted-foreground">
                No domains yet. Add your company domain so members can join without an invite.
              </p>
            );
          }

          return (
            <div className="space-y-2">
              {value.domains.map((d: DomainData) => (
                <DomainCard
                  key={d.id}
                  domain={d}
                  onDelete={() => handleDeleteDomain(d.id, d.domain)}
                />
              ))}
            </div>
          );
        },
      })}
    </section>
  );
}

function DomainCard({ domain: d, onDelete }: { domain: DomainData; onDelete: () => void }) {
  const isVerified = d.state === "verified";
  const isPending = d.state === "pending";

  const recordValue = d.verificationPrefix
    ? `${d.verificationPrefix}=${d.verificationToken}`
    : (d.verificationToken ?? "");

  const copyPromptValue = `Add a DNS TXT record for domain verification:\n\nDomain: ${d.domain}\nRecord name: @\nRecord value: ${recordValue}\n\nPlease add this TXT record to my DNS configuration.`;

  return (
    <div className="rounded-lg border border-border">
      <div className="flex items-center gap-3 px-4 py-3">
        <div className="min-w-0 flex-1">
          <div className="flex items-center gap-2">
            <p className="truncate text-sm font-medium text-foreground">{d.domain}</p>
            <Badge
              className={
                isVerified
                  ? "bg-muted text-foreground"
                  : isPending
                    ? "bg-muted text-muted-foreground"
                    : "bg-destructive/10 text-destructive"
              }
            >
              {isVerified ? "Verified" : isPending ? "Pending" : "Failed"}
            </Badge>
          </div>
        </div>
        <div className="flex shrink-0 items-center gap-1.5">
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="icon" className="size-7">
                <svg viewBox="0 0 16 16" className="size-3">
                  <circle cx="8" cy="3" r="1.2" fill="currentColor" />
                  <circle cx="8" cy="8" r="1.2" fill="currentColor" />
                  <circle cx="8" cy="13" r="1.2" fill="currentColor" />
                </svg>
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-44">
              <DropdownMenuItem
                className="text-destructive focus:text-destructive text-sm"
                onClick={onDelete}
              >
                Remove domain
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>

      {!isVerified && d.verificationToken && (
        <div className="border-t border-border px-4 py-3">
          <div className="flex items-center justify-between">
            <p className="text-sm text-muted-foreground">
              Add this TXT record to your DNS provider to verify ownership.
            </p>
            <CopyButton value={copyPromptValue} label="Copy prompt" />
          </div>
          <div className="mt-3 grid grid-cols-[4rem_3.5rem_1fr] items-center gap-y-2">
            <p className="text-xs font-medium text-muted-foreground">Type</p>
            <p className="text-xs font-medium text-muted-foreground">Name</p>
            <p className="text-xs font-medium text-muted-foreground">Value</p>
            <p className="text-sm font-mono text-foreground">TXT</p>
            <p className="text-sm font-mono text-foreground">@</p>
            <span className="inline-flex min-w-0 items-center gap-1">
              <code className="truncate text-sm font-mono text-foreground">{recordValue}</code>
              <CopyButton value={recordValue} />
            </span>
          </div>
          <p className="mt-3 text-xs text-muted-foreground">
            DNS changes can take up to 72 hours to propagate, but usually complete within a few
            minutes.
          </p>
        </div>
      )}
    </div>
  );
}
