import { useEffect, useState } from "react";
import { graphql, useMutation } from "react-relay";
import { Dialog } from "./Dialog.tsx";
import { Button } from "./Button.tsx";
import { Input } from "./Input.tsx";
import { Textarea } from "./Textarea.tsx";
import { FormControl } from "./FormControl.tsx";
import { CopyableField } from "./CopyableField.tsx";
import type { OAuthClientModalCreateMutation } from "../__generated__/OAuthClientModalCreateMutation.graphql.ts";
import type { OAuthClientModalUpdateMutation } from "../__generated__/OAuthClientModalUpdateMutation.graphql.ts";

interface OAuthClient {
  clientId: string;
  clientSecret?: string | null;
  clientName: string;
  redirectUris: ReadonlyArray<string>;
  scope?: string | null;
  clientUri?: string | null;
  logoUri?: string | null;
  tosUri?: string | null;
  policyUri?: string | null;
}

interface OAuthClientModalProps {
  sliceUri: string;
  client?: OAuthClient | null;
  onClose: () => void;
  onSuccess: (clientId: string, clientSecret: string | null) => void;
}

export function OAuthClientModal({
  sliceUri,
  client,
  onClose,
  onSuccess,
}: OAuthClientModalProps) {
  const isEditMode = !!client;

  const [clientName, setClientName] = useState("");
  const [redirectUris, setRedirectUris] = useState("");
  const [scope, setScope] = useState("");
  const [clientUri, setClientUri] = useState("");
  const [logoUri, setLogoUri] = useState("");
  const [tosUri, setTosUri] = useState("");
  const [policyUri, setPolicyUri] = useState("");
  const [error, setError] = useState<string | null>(null);

  // Initialize form with client data in edit mode
  useEffect(() => {
    if (client) {
      setClientName(client.clientName);
      setRedirectUris(client.redirectUris.join("\n"));
      setScope(client.scope || "");
      setClientUri(client.clientUri || "");
      setLogoUri(client.logoUri || "");
      setTosUri(client.tosUri || "");
      setPolicyUri(client.policyUri || "");
    }
  }, [client]);

  const [createOAuthClient, isCreating] = useMutation<
    OAuthClientModalCreateMutation
  >(graphql`
    mutation OAuthClientModalCreateMutation(
      $sliceUri: String!
      $clientName: String!
      $redirectUris: [String!]!
      $scope: String!
      $clientUri: String
      $logoUri: String
      $tosUri: String
      $policyUri: String
    ) {
      createOAuthClient(
        sliceUri: $sliceUri
        clientName: $clientName
        redirectUris: $redirectUris
        scope: $scope
        clientUri: $clientUri
        logoUri: $logoUri
        tosUri: $tosUri
        policyUri: $policyUri
      ) {
        clientId
        clientSecret
      }
    }
  `);

  const [updateOAuthClient, isUpdating] = useMutation<
    OAuthClientModalUpdateMutation
  >(graphql`
    mutation OAuthClientModalUpdateMutation(
      $clientId: String!
      $clientName: String
      $redirectUris: [String!]
      $scope: String
      $clientUri: String
      $logoUri: String
      $tosUri: String
      $policyUri: String
    ) {
      updateOAuthClient(
        clientId: $clientId
        clientName: $clientName
        redirectUris: $redirectUris
        scope: $scope
        clientUri: $clientUri
        logoUri: $logoUri
        tosUri: $tosUri
        policyUri: $policyUri
      ) {
        clientId
      }
    }
  `);

  const isSubmitting = isCreating || isUpdating;

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    // Parse redirect URIs
    const uris = redirectUris
      .split("\n")
      .map((uri) => uri.trim())
      .filter((uri) => uri.length > 0);

    if (uris.length === 0) {
      setError("At least one redirect URI is required");
      return;
    }

    // Validate redirect URIs
    for (const uri of uris) {
      if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
        setError(`Invalid redirect URI: ${uri}. Must use HTTP or HTTPS.`);
        return;
      }
    }

    if (isEditMode && client) {
      // Update existing client
      updateOAuthClient({
        variables: {
          clientId: client.clientId,
          clientName: clientName.trim() || null,
          redirectUris: uris,
          scope: scope.trim() || null,
          clientUri: clientUri.trim() || null,
          logoUri: logoUri.trim() || null,
          tosUri: tosUri.trim() || null,
          policyUri: policyUri.trim() || null,
        },
        onCompleted: (response) => {
          onSuccess(response.updateOAuthClient.clientId, null);
        },
        onError: (err) => {
          console.error("Failed to update OAuth client:", err);
          setError(
            err.message || "Failed to update OAuth client. Please try again.",
          );
        },
      });
    } else {
      // Create new client
      createOAuthClient({
        variables: {
          sliceUri,
          clientName,
          redirectUris: uris,
          scope: scope.trim(),
          clientUri: clientUri.trim() || null,
          logoUri: logoUri.trim() || null,
          tosUri: tosUri.trim() || null,
          policyUri: policyUri.trim() || null,
        },
        onCompleted: (response) => {
          onSuccess(
            response.createOAuthClient.clientId,
            response.createOAuthClient.clientSecret ?? null,
          );
        },
        onError: (err) => {
          console.error("Failed to create OAuth client:", err);
          setError(
            err.message || "Failed to create OAuth client. Please try again.",
          );
        },
      });
    }
  };

  return (
    <Dialog
      open
      onClose={onClose}
      title={isEditMode ? "Edit OAuth Client" : "Register OAuth Client"}
      maxWidth="2xl"
      className="max-h-[90vh] overflow-y-auto"
    >
      {isEditMode && client && (
        <div className="mb-4 pb-4 border-b border-zinc-800 space-y-4">
          <CopyableField value={client.clientId} label="Client ID" />
          {client.clientSecret && (
            <CopyableField value={client.clientSecret} label="Client Secret" />
          )}
        </div>
      )}

      <form onSubmit={handleSubmit} className="space-y-4">
        <FormControl label="Client Name" htmlFor="clientName">
          <Input
            id="clientName"
            value={clientName}
            onChange={(e) => setClientName(e.target.value)}
            placeholder="My Application"
            required
            disabled={isSubmitting}
          />
        </FormControl>

        <FormControl
          label="Redirect URIs"
          htmlFor="redirectUris"
        >
          <Textarea
            id="redirectUris"
            value={redirectUris}
            onChange={(e) => setRedirectUris(e.target.value)}
            placeholder="https://example.com/callback&#10;https://localhost:3000/callback"
            required
            disabled={isSubmitting}
            rows={3}
            className="bg-zinc-800 border-zinc-700 focus:border-blue-500 font-mono"
          />
        </FormControl>

        <FormControl
          label="Scope"
          htmlFor="scope"
        >
          <Input
            id="scope"
            value={scope}
            onChange={(e) => setScope(e.target.value)}
            placeholder="atproto"
            required
            disabled={isSubmitting}
          />
        </FormControl>

        {error && (
          <div className="bg-red-500/10 border border-red-500/20 text-red-400 px-3 py-2 rounded text-sm">
            {error}
          </div>
        )}

        <div className="flex justify-end gap-3 pt-4">
          <Button
            type="button"
            onClick={onClose}
            variant="default"
            disabled={isSubmitting}
          >
            Cancel
          </Button>
          <Button
            type="button"
            variant="primary"
            onClick={(e) => {
              e.preventDefault();
              e.stopPropagation();
              handleSubmit(e);
            }}
            disabled={isSubmitting}
          >
            {isEditMode
              ? (isUpdating ? "Updating..." : "Update Client")
              : (isCreating ? "Creating..." : "Register Client")}
          </Button>
        </div>
      </form>
    </Dialog>
  );
}
