"use client";

import type { Domain } from "@domainops/shared-types";
import { App, Button, Card, Descriptions, Skeleton, Tabs, Tooltip } from "antd";
import { ArrowLeftOutlined, EditOutlined, ReloadOutlined } from "@ant-design/icons";
import Link from "next/link";
import { useParams, usePathname, useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { getDomain, refreshDomainExpiry } from "@/lib/api/domains";
import { ApiError } from "@/lib/api/client";
import { cloudflareName, purposeName, registrarName } from "@/lib/utils/domainFields";
import { formatShortDate } from "@/lib/utils/date";
import { useAuth } from "@/lib/auth/AuthProvider";
import { DomainStatusTag } from "@/components/features/DomainStatusTag";
import { HeldAtTags } from "@/components/features/HeldAtTags";
import { PageGuide } from "@/components/features/PageGuide";
import { DOMAIN_DETAIL_GUIDES } from "@/lib/guides/domain-detail";
import { EditDomainModal } from "../EditDomainModal";
import { DomainContext } from "./DomainContext";

const TABS = [
  { key: "setup", label: "Setup", path: "" },
  { key: "deploy", label: "Deploy", path: "/deploy" },
  { key: "seo", label: "SEO", path: "/seo" },
  { key: "cloudflare", label: "Cloudflare", path: "/cloudflare" },
  { key: "redirect", label: "Redirect", path: "/redirect" },
  { key: "activity", label: "Activity", path: "/activity" },
];

/**
 * The shared frame of every /domains/{id}/... page: the domain's summary card
 * and the tab bar. Each tab is its own route, so the page you are on stays
 * put when something is saved - only the part that changed is updated.
 */
export default function DomainLayout({ children }: { children: React.ReactNode }) {
  const { message } = App.useApp();
  const { user } = useAuth();
  const params = useParams<{ id: string }>();
  const pathname = usePathname();
  const router = useRouter();
  const domainId = Number(params.id);
  const [domain, setDomain] = useState<Domain | null>(null);
  const [isEditOpen, setIsEditOpen] = useState(false);
  const [isRefreshingExpiry, setIsRefreshingExpiry] = useState(false);
  const infoRef = useRef<HTMLDivElement>(null);

  const reload = useCallback(async () => {
    try {
      setDomain(await getDomain(domainId));
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't load this domain.");
    }
  }, [domainId, message]);

  useEffect(() => {
    // The domain lives on the Laravel API - a client fetch when the page
    // opens, not a state-sync bug.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void reload();
  }, [reload]);

  useEffect(() => {
    infoRef.current?.querySelectorAll<HTMLElement>("[class*='dms_domain_item_']").forEach((item) => {
      const marker = [...item.classList].find((name) => name.startsWith("dms_domain_item_"));
      if (marker) item.id = marker;
    });
  });

  const contextValue = useMemo(() => (domain ? { domain, setDomain, reload } : null), [domain, reload]);

  async function handleRefreshExpiry() {
    setIsRefreshingExpiry(true);
    try {
      const updated = await refreshDomainExpiry(domainId);
      setDomain(updated);
      message.success(`Expiry fetched from ${updated.expiry_source === "whois" ? "WHOIS" : "the registrar"}.`);
    } catch (err) {
      message.error(err instanceof ApiError ? err.message : "Couldn't fetch the expiry date.");
    } finally {
      setIsRefreshingExpiry(false);
    }
  }

  if (!domain || !contextValue) {
    return <Skeleton active />;
  }

  const base = `/domains/${domain.id}`;
  const activeKey = TABS.find((tab) => tab.path !== "" && pathname.startsWith(`${base}${tab.path}`))?.key ?? "setup";
  const canOpenCpanel = user?.is_admin || (user?.action_permissions ?? []).some((a) => a === "*" || a === "domain.open_cpanel");
  const whmHost = domain.server_account?.server_group?.whm_host;

  return (
    <DomainContext.Provider value={contextValue}>
      <div className="flex flex-col gap-4 page page-domain-detail">
        <div className="flex items-center justify-between">
          <Link href="/domains">
            <Button icon={<ArrowLeftOutlined />} className="dms_domain_detail_back_btn">
              Back to Domain Inventory
            </Button>
          </Link>
          <Button icon={<EditOutlined />} onClick={() => setIsEditOpen(true)} className="dms_domain_detail_edit_btn">
            Edit
          </Button>
        </div>
        <Card className="dms_domain_detail_info_card">
          <div className="flex items-center gap-3 mb-3">
            <h1 className="text-xl font-mono font-semibold">{domain.fqdn}</h1>
            <DomainStatusTag status={domain.status} />
            <PageGuide guides={DOMAIN_DETAIL_GUIDES} label="Domain page guide" defaultKey={activeKey} />
          </div>
          <div ref={infoRef}>
            <Descriptions size="small" column={2} className="dms_domain_detail_descriptions">
              <Descriptions.Item label="Project" className="dms_domain_item_brand">
                {domain.brand?.name ?? "—"}
              </Descriptions.Item>
              <Descriptions.Item label="Region" className="dms_domain_item_region">
                {domain.region ? `${domain.region.name} (${domain.region.country_code})` : "—"}
              </Descriptions.Item>
              <Descriptions.Item label="Registrar" className="dms_domain_item_registrar">
                {registrarName(domain)}
              </Descriptions.Item>
              <Descriptions.Item label="Cloudflare" className="dms_domain_item_cloudflare">
                {cloudflareName(domain)}
              </Descriptions.Item>
              <Descriptions.Item label="Held At" className="dms_domain_item_held_at">
                <span className="flex items-center gap-2">
                  <HeldAtTags account={domain.server_account} />
                  {canOpenCpanel && whmHost && (
                    <Button
                      size="small"
                      href={`https://${whmHost}:2083`}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="dms_domain_detail_open_cpanel_btn"
                    >
                      Open cPanel
                    </Button>
                  )}
                </span>
              </Descriptions.Item>
              <Descriptions.Item label="Type" className="dms_domain_item_purpose">
                {purposeName(domain)}
              </Descriptions.Item>
              <Descriptions.Item label="Expires" className="dms_domain_item_expires">
                <span className="flex items-center gap-1">
                  {formatShortDate(domain.expires_at)}
                  <Tooltip title={domain.expires_at ? "Re-fetch the expiry date" : "Fetch the expiry date"}>
                    <Button
                      size="small"
                      type="text"
                      icon={<ReloadOutlined />}
                      loading={isRefreshingExpiry}
                      onClick={() => void handleRefreshExpiry()}
                      className="dms_domain_detail_refresh_expiry_btn"
                    />
                  </Tooltip>
                </span>
              </Descriptions.Item>
              <Descriptions.Item label="Notes" span="filled" className="dms_domain_item_notes">
                {domain.notes || "—"}
              </Descriptions.Item>
            </Descriptions>
          </div>
        </Card>

        <Tabs
          className="dms_domain_detail_tabs"
          activeKey={activeKey}
          onChange={(key) => router.push(`${base}${TABS.find((tab) => tab.key === key)?.path ?? ""}`)}
          items={TABS.map((tab) => ({
            key: tab.key,
            label: (
              <Link
                href={`${base}${tab.path}`}
                onClick={(event) => {
                  if (event.button === 0 && !event.ctrlKey && !event.metaKey && !event.shiftKey) event.preventDefault();
                }}
                className={`dms_domain_tab_link dms_domain_tab_${tab.key}`}
              >
                {tab.label}
              </Link>
            ),
          }))}
        />

        {children}

        <EditDomainModal
          open={isEditOpen}
          domain={domain}
          onClose={() => setIsEditOpen(false)}
          onSaved={() => {
            setIsEditOpen(false);
            void reload();
          }}
        />
      </div>
    </DomainContext.Provider>
  );
}
