"use client";
import { useState } from "react";
import { useDomainStatus } from "./useDomainStatus";
import { DotLoader } from "components/utils/DotLoader";
import {
  deleteDomain,
  removeDomainAssignment,
  removeDomainRoute,
} from "actions/domains";
import {
  useIdentityData,
  mutateIdentityData,
} from "components/IdentityProvider";
import { ButtonPrimary, ButtonTertiary } from "components/Buttons";
import { getDomainAssignment } from "./domainAssignment";
import { GoToArrow } from "components/Icons/GoToArrow";
import { useSmoker } from "components/Toast";
import type { CustomDomain } from "./DomainList";
import { UnlinkTiny } from "components/Icons/UnlinkTiny";

export function DomainSettingsView(props: {
  domain: string;
  onBack: () => void;
  onRemoveAssignment?: () => void;
  onDeleteDomain?: () => void;
}) {
  let {
    data,
    pending: needsSetup,
    mutate: mutateDomainStatus,
  } = useDomainStatus(props.domain);
  let { identity, mutate: mutateIdentity } = useIdentityData();
  let isSubdomain = props.domain.split(".").length > 2;

  let domainData = identity?.custom_domains.find(
    (d) => d.domain === props.domain,
  );
  let assignment = domainData ? getDomainAssignment(domainData) : null;
  let isAssigned = assignment && assignment.type !== "unassigned";

  return (
    <div className="flex flex-col gap-[6px] text-sm text-primary max-w-full">
      <div className="w-full flex gap-2 items-center">
        <h3 className="w-full grow min-w-0 truncate">
          {needsSetup ? `Verify ${props.domain}` : props.domain}
        </h3>
        <button
          className="text-accent-contrast rotate-180 shrink-0"
          onMouseDown={() => props.onBack()}
          type="button"
        >
          <GoToArrow />
        </button>
      </div>

      {needsSetup ? (
        <>
          <div>
            To verify this domain, add the following record to your DNS provider
            for <strong>{props.domain}</strong>.
          </div>
          <div>Verfication may take up to a few hours to process.</div>
          <table className="border border-border-light rounded-md text-left mt-2">
            <thead>
              <tr>
                <th className="px-2 pt-1 text-tertiary">Type</th>
                <th className="px-2 pt-1  text-tertiary">Name</th>
                <th className="px-2 pt-1 text-tertiary">Value</th>
              </tr>
            </thead>
            <tbody>
              {data?.verification && (
                <tr>
                  <td className="px-2 pb-1">
                    <div>{data.verification[0].type}</div>
                  </td>
                  <td className="px-2  pb-1">
                    <div style={{ wordBreak: "break-word" }}>
                      {data.verification[0].domain}
                    </div>
                  </td>
                  <td className="px-2 pb-1">
                    <div style={{ wordBreak: "break-word" }}>
                      {data.verification[0].value}
                    </div>
                  </td>
                </tr>
              )}
              {data?.config &&
                (isSubdomain ? (
                  <tr>
                    <td className="px-2 pb-1">
                      <div>CNAME</div>
                    </td>
                    <td className="px-2 pb-1">
                      <div style={{ wordBreak: "break-word" }}>
                        {props.domain.split(".").slice(0, -2).join(".")}
                      </div>
                    </td>
                    <td className="px-2 pb-1">
                      <div style={{ wordBreak: "break-word" }}>
                        {
                          data.config.recommendedCNAME.sort(
                            (a, b) => a.rank - b.rank,
                          )[0].value
                        }
                      </div>
                    </td>
                  </tr>
                ) : (
                  <tr>
                    <td className="px-2 pb-1">
                      <div>A</div>
                    </td>
                    <td className="px-2 pb-1">
                      <div style={{ wordBreak: "break-word" }}>@</div>
                    </td>
                    <td className="px-2 pb-1">
                      <div style={{ wordBreak: "break-word" }}>
                        {
                          data.config.recommendedIPv4.sort(
                            (a, b) => a.rank - b.rank,
                          )[0].value[0]
                        }
                      </div>
                    </td>
                  </tr>
                ))}
            </tbody>
          </table>
          <VerifyButton verify={() => mutateDomainStatus()} />
        </>
      ) : null}
      {/* Assignment list */}
      {!isAssigned && (
        <div className="text-secondary">
          <div className="font-bold">
            You haven't assigned this domain to anything yet!
          </div>
          You can assign it to either a publication from your pub settings, or
          to any leaflet!
        </div>
      )}
      {props.onRemoveAssignment && isAssigned && domainData && (
        <div className="flex flex-col gap-1 mt-1">
          <h4 className="text-tertiary text-sm">
            Assigned{" "}
            {domainData.publication_domains.length > 0
              ? "Publications"
              : "Leaflets"}
          </h4>
          {domainData.publication_domains.length > 0 ? (
            <AssignedPublication
              domainData={domainData}
              domain={props.domain}
              onRemoveAssignment={props.onRemoveAssignment}
              mutateIdentity={mutateIdentity}
              isLastAssignment
            />
          ) : (
            domainData.custom_domain_routes.map((route) => (
              <AssignedLeaflet
                key={route.id}
                route={route}
                domain={props.domain}
                onRemoveAssignment={props.onRemoveAssignment}
                mutateIdentity={mutateIdentity}
                isLastAssignment={domainData.custom_domain_routes.length === 1}
              />
            ))
          )}
        </div>
      )}
      <div className="flex flex-col gap-2 mt-2">
        <hr className="border-border-light" />

        <DeleteDomainButton
          domain={props.domain}
          onDeleteDomain={props.onDeleteDomain}
          mutateIdentity={mutateIdentity}
        />
      </div>
    </div>
  );
}
let containerClassName =
  "flex items-center justify-between px-[6px] py-1 border rounded-md border-border-light";

const AssignedPublication = (props: {
  domainData: CustomDomain;
  domain: string;
  onRemoveAssignment?: () => void;
  mutateIdentity: ReturnType<typeof useIdentityData>["mutate"];
  isLastAssignment: boolean;
}) => {
  let [areYouSure, setAreYouSure] = useState(false);

  if (areYouSure) {
    return (
      <UnassignAreYouSure
        {...props}
        closeAreYouSure={() => {
          setAreYouSure(false);
        }}
      />
    );
  }
  return (
    <div className={containerClassName}>
      <span className="text-secondary truncate">
        {props.domainData.publication_domains[0]?.publications?.name ??
          "publication"}
      </span>
      <button
        className="text-tertiary hover:text-accent-contrast text-sm"
        type="button"
        onMouseDown={() => {
          setAreYouSure(true);
        }}
      >
        <UnlinkTiny />
      </button>
    </div>
  );
};

const AssignedLeaflet = (props: {
  route: {
    id: string;
    edit_permission_token: string;
    route: string;
  };
  domain: string;
  onRemoveAssignment?: () => void;
  mutateIdentity: ReturnType<typeof useIdentityData>["mutate"];
  isLastAssignment: boolean;
}) => {
  let [areYouSure, setAreYouSure] = useState(false);

  if (areYouSure) {
    return (
      <UnassignAreYouSure
        {...props}
        routeId={props.route.id}
        closeAreYouSure={() => {
          setAreYouSure(false);
        }}
      />
    );
  }
  return (
    <div className={containerClassName}>
      <a
        href={`/${props.route.edit_permission_token}`}
        className="text-accent-contrast no-underline! truncate"
      >
        {props.route.route}
      </a>
      <button
        className="text-tertiary hover:text-accent-contrast "
        type="button"
        onMouseDown={() => {
          setAreYouSure(true);
        }}
      >
        <UnlinkTiny />
      </button>
    </div>
  );
};

const UnassignAreYouSure = (props: {
  domain: string;
  routeId?: string;
  isLastAssignment: boolean;
  onRemoveAssignment?: () => void;
  mutateIdentity: ReturnType<typeof useIdentityData>["mutate"];
  closeAreYouSure: () => void;
}) => {
  let {
    domain,
    routeId,
    isLastAssignment,
    onRemoveAssignment,
    mutateIdentity,
  } = props;
  return (
    <div className={`${containerClassName}`}>
      <p className="text-secondary text-sm font-bold">Are You Sure?</p>
      <div className="flex gap-2 items-center">
        <ButtonPrimary
          compact
          type="button"
          className="text-sm -my-px"
          onMouseDown={async () => {
            if (routeId) {
              mutateIdentityData(mutateIdentity, (draft) => {
                let domainData = draft.custom_domains.find(
                  (d) => d.domain === domain,
                );
                if (domainData) {
                  domainData.custom_domain_routes =
                    domainData.custom_domain_routes.filter(
                      (r) => r.id !== routeId,
                    );
                }
              });
              if (isLastAssignment) onRemoveAssignment?.();
              await removeDomainRoute({ routeId });
            } else {
              mutateIdentityData(mutateIdentity, (draft) => {
                let domainData = draft.custom_domains.find(
                  (d) => d.domain === domain,
                );
                if (domainData) {
                  domainData.publication_domains = [];
                }
              });
              onRemoveAssignment?.();
              await removeDomainAssignment({ domain });
            }
          }}
        >
          Confirm
        </ButtonPrimary>
        <button
          className="text-accent-contrast font-bold"
          type="button"
          onMouseDown={() => props.closeAreYouSure()}
        >
          Nevermind
        </button>
      </div>
    </div>
  );
};

function DeleteDomainButton(props: {
  domain: string;
  onDeleteDomain?: () => void;
  mutateIdentity: ReturnType<typeof useIdentityData>["mutate"];
}) {
  let [confirming, setConfirming] = useState(false);
  let [loading, setLoading] = useState(false);

  if (!props.onDeleteDomain) return null;

  if (!confirming) {
    return (
      <ButtonTertiary
        fullWidth
        compact
        type="button"
        onMouseDown={() => setConfirming(true)}
      >
        Delete Domain
      </ButtonTertiary>
    );
  }

  return (
    <div className="flex flex-col gap-1 text-sm accent-container rounded-md p-2">
      <p className="text-secondary text-center">
        Are you sure you want to delete <strong>{props.domain}</strong>? This
        will remove all assignments and cannot be undone.
      </p>
      <div className="flex gap-2 justify-center">
        <button
          className="text-accent-contrast font-bold"
          onMouseDown={() => setConfirming(false)}
          type="button"
        >
          Cancel
        </button>
        <ButtonPrimary
          compact
          className="text-sm"
          disabled={loading}
          onMouseDown={async () => {
            setLoading(true);
            mutateIdentityData(props.mutateIdentity, (draft) => {
              draft.custom_domains = draft.custom_domains.filter(
                (d) => d.domain !== props.domain,
              );
            });
            props.onDeleteDomain?.();
            await deleteDomain({ domain: props.domain });
          }}
        >
          {loading ? <DotLoader /> : "Delete"}
        </ButtonPrimary>
      </div>
    </div>
  );
}

function VerifyButton(props: { verify: () => Promise<any> }) {
  let [loading, setLoading] = useState(false);
  let smoker = useSmoker();
  return (
    <ButtonPrimary
      fullWidth
      className="mt-2"
      type="button"
      onClick={async (e) => {
        e.preventDefault();
        setLoading(true);
        let result = await props.verify();
        setLoading(false);
        let stillPending =
          result?.config?.misconfigured || result?.verification;
        if (stillPending) {
          smoker({
            position: {
              x: e.clientX,
              y: e.clientY - 5,
            },
            text: "Still processing",
          });
        }
      }}
    >
      {loading ? <DotLoader /> : "Check Status"}
    </ButtonPrimary>
  );
}
