import { useEffect, useMemo, useState } from "react";
import type { ReactNode } from "react";

import { ScopeId } from "@executor-js/sdk/shared";

import { useScope, useUserScope } from "../api/scope-context";
import {
  CardStack,
  CardStackContent,
  CardStackEntry,
  CardStackEntryContent,
  CardStackEntryDescription,
  CardStackEntryTitle,
} from "../components/card-stack";
import { FilterTabs } from "../components/filter-tabs";
import { FieldLabel } from "../components/field";
import { HelpTooltip } from "../components/help-tooltip";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "../components/select";

export interface CredentialTargetScopeOption {
  readonly scopeId: ScopeId;
  readonly label: string;
  readonly description: string;
}

export const credentialTargetScopeOptions = (input: {
  readonly sourceScope: ScopeId;
  readonly userScope: ScopeId;
  readonly sourceScopeLabel?: string;
}): readonly CredentialTargetScopeOption[] => {
  if (input.sourceScope === input.userScope) {
    return [
      {
        scopeId: input.userScope,
        label: "Personal",
        description: "Saved only for your account.",
      },
    ];
  }

  return [
    {
      scopeId: input.userScope,
      label: "Personal",
      description: "Saved only for your account.",
    },
    {
      scopeId: input.sourceScope,
      label: input.sourceScopeLabel ?? "Organization",
      description: "Shared with everyone who can use this source.",
    },
  ];
};

export const normalizeCredentialTargetScope = (
  value: ScopeId,
  options: readonly CredentialTargetScopeOption[],
): ScopeId => options.find((option) => option.scopeId === value)?.scopeId ?? options[0]!.scopeId;

export function useCredentialTargetScope(input?: {
  readonly sourceScope?: ScopeId;
  readonly sourceScopeLabel?: string;
  readonly initialTargetScope?: ScopeId;
}): {
  readonly credentialTargetScope: ScopeId;
  readonly setCredentialTargetScope: (scope: ScopeId) => void;
  readonly credentialScopeOptions: readonly CredentialTargetScopeOption[];
} {
  const routeScope = useScope();
  const sourceScope = input?.sourceScope ?? routeScope;
  const userScope = useUserScope();
  const credentialScopeOptions = useMemo(
    () =>
      credentialTargetScopeOptions({
        sourceScope,
        userScope,
        sourceScopeLabel: input?.sourceScopeLabel,
      }),
    [sourceScope, userScope, input?.sourceScopeLabel],
  );
  const initialTargetScope = input?.initialTargetScope ?? credentialScopeOptions[0]!.scopeId;
  const [credentialTargetScope, setCredentialTargetScope] = useState<ScopeId>(
    normalizeCredentialTargetScope(initialTargetScope, credentialScopeOptions),
  );

  useEffect(() => {
    setCredentialTargetScope((current) =>
      normalizeCredentialTargetScope(
        current === routeScope && input?.sourceScope !== undefined ? initialTargetScope : current,
        credentialScopeOptions,
      ),
    );
  }, [credentialScopeOptions, initialTargetScope, input?.sourceScope, routeScope]);

  return {
    credentialTargetScope,
    setCredentialTargetScope,
    credentialScopeOptions,
  };
}

export function CredentialTargetScopeSelector(props: {
  readonly value: ScopeId;
  readonly options: readonly CredentialTargetScopeOption[];
  readonly onChange: (scope: ScopeId) => void;
  readonly title?: string;
  readonly description?: string;
}) {
  if (props.options.length <= 1) return null;

  const active = props.options.find((option) => option.scopeId === props.value);

  return (
    <CardStack>
      <CardStackContent className="border-t-0">
        <CardStackEntry>
          <CardStackEntryContent>
            <CardStackEntryTitle>{props.title ?? "Credentials"}</CardStackEntryTitle>
            <CardStackEntryDescription>
              {props.description ??
                active?.description ??
                "Choose where new credentials are saved."}
            </CardStackEntryDescription>
          </CardStackEntryContent>
          <FilterTabs<ScopeId>
            tabs={props.options.map((option) => ({
              value: option.scopeId,
              label: option.label,
            }))}
            value={props.value}
            onChange={props.onChange}
          />
        </CardStackEntry>
      </CardStackContent>
    </CardStack>
  );
}

export function CredentialScopeSection(props: {
  readonly value: ScopeId;
  readonly options: readonly CredentialTargetScopeOption[];
  readonly onChange: (scope: ScopeId) => void;
  readonly children: ReactNode;
  readonly title?: string;
  readonly description?: string;
}) {
  return (
    <div className="space-y-3">
      <CredentialTargetScopeSelector
        value={props.value}
        options={props.options}
        onChange={props.onChange}
        title={props.title ?? "Used by"}
        description={props.description ?? "Choose who can use these credentials."}
      />
      {props.children}
    </div>
  );
}

export function CredentialScopeDropdown(props: {
  readonly value: ScopeId;
  readonly options: readonly CredentialTargetScopeOption[];
  readonly onChange: (scope: ScopeId) => void;
  readonly label?: string;
  readonly help?: ReactNode;
  readonly className?: string;
  readonly triggerClassName?: string;
  readonly size?: "sm" | "default";
}) {
  const label = props.label ?? "Used by";
  if (props.options.length <= 1) return null;

  return (
    <div className={props.className ?? "space-y-1.5"}>
      <div className="flex items-center gap-1.5">
        <FieldLabel className="text-[11px]">{label}</FieldLabel>
        <HelpTooltip label={label}>
          {props.help ?? "Choose who can use these credentials."}
        </HelpTooltip>
      </div>
      <Select
        value={String(props.value)}
        onValueChange={(value) => props.onChange(ScopeId.make(value))}
      >
        <SelectTrigger className={props.triggerClassName ?? "w-full"} size={props.size}>
          <SelectValue placeholder={label} />
        </SelectTrigger>
        <SelectContent>
          {props.options.map((option) => (
            <SelectItem key={option.scopeId} value={option.scopeId}>
              {option.label}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>
    </div>
  );
}

export function CredentialControlField(props: {
  readonly label: string;
  readonly children: ReactNode;
  readonly help?: ReactNode;
}) {
  return (
    <div className="space-y-1.5">
      <div className="flex items-center gap-1.5">
        <FieldLabel className="text-[11px]">{props.label}</FieldLabel>
        {props.help ? <HelpTooltip label={props.label}>{props.help}</HelpTooltip> : null}
      </div>
      {props.children}
    </div>
  );
}

export function CredentialUsageRow(props: {
  readonly value: ScopeId;
  readonly options: readonly CredentialTargetScopeOption[];
  readonly onChange: (scope: ScopeId) => void;
  readonly children: ReactNode;
  readonly label?: string;
  readonly help?: ReactNode;
}) {
  if (props.options.length <= 1) {
    return <div className="space-y-2.5">{props.children}</div>;
  }

  return (
    <div className="grid items-stretch gap-2 md:grid-cols-2">
      <div className="min-w-0 space-y-2.5">{props.children}</div>
      <CredentialScopeDropdown
        value={props.value}
        options={props.options}
        onChange={props.onChange}
        label={props.label}
        help={props.help}
        className="flex h-full flex-col space-y-1.5"
        triggerClassName="w-full min-h-9 flex-1 data-[size=default]:h-full"
      />
    </div>
  );
}
