import { NodeRect } from './node-rect';
import { GithubNode, nodeIsConnectable, nodeLabel, useStateStore, useGithubService } from '@/lib/state';
import { useEffect, useMemo, useState } from 'react';
import { z } from "zod";
import { DeepPartial, EventType, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form, FormControl, FormField, FormItem, FormMessage } from './ui/form';
import { Handle, Position } from "@xyflow/react";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select';
import { GitHubRepository } from '../lib/github';
import { useProjectId } from '@/lib/state';
import { Alert, AlertDescription } from './ui/alert';
import { AlertCircle } from 'lucide-react';

export function NodeGithub(node: GithubNode) {
  const { id, selected } = node;
  const isConnectable = useMemo(() => nodeIsConnectable(node, "repository"), [node]);
  return (
    <NodeRect id={id} selected={selected} type={node.type} state={node.data.state}>
      <div style={{ padding: '10px 20px' }}>
        {nodeLabel(node)}
        <Handle
          id="repository"
          type={"source"}
          position={Position.Right}
          isConnectableStart={isConnectable}
          isConnectableEnd={isConnectable}
          isConnectable={isConnectable}
        />
      </div>
    </NodeRect>
  );
}

const schema = z.object({
  repositoryId: z.number().optional(),
});

export function NodeGithubDetails(node: GithubNode) {
  const { id, data } = node;
  const store = useStateStore();
  const projectId = useProjectId();
  const [repos, setRepos] = useState<GitHubRepository[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const githubService = useGithubService();

  useEffect(() => {
    if (data.repository) {
      const { id, sshURL } = data.repository;
      setRepos(prevRepos => {
        if (!prevRepos.some(r => r.id === id)) {
          return [...prevRepos, {
            id,
            name: sshURL.split('/').pop() || '',
            full_name: sshURL.split('/').slice(-2).join('/'),
            html_url: '',
            ssh_url: sshURL,
            description: null,
            private: false,
            default_branch: 'main'
          }];
        }
        return prevRepos;
      });
    }
  }, [data.repository]);

  const form = useForm<z.infer<typeof schema>>({
    resolver: zodResolver(schema),
    mode: "onChange",
    defaultValues: {
      repositoryId: data.repository?.id,
    }
  });

  useEffect(() => {
    const sub = form.watch((value: DeepPartial<z.infer<typeof schema>>, { name, type }: { name?: keyof z.infer<typeof schema> | undefined, type?: EventType | undefined }) => {
      if (type !== "change") {
        return;
      }
      switch (name) {
        case "repositoryId":
          if (value.repositoryId) {
            const repo = repos.find(r => r.id === value.repositoryId);
            if (repo) {
              store.updateNodeData<"github">(id, {
                repository: {
                  id: repo.id,
                  sshURL: repo.ssh_url,
                },
              });
            }
          }
          break;
      }
    });
    return () => sub.unsubscribe();
  }, [form, store, id, repos]);

  useEffect(() => {
    const fetchRepositories = async () => {
      if (!!!githubService) return;

      setLoading(true);
      setError(null);
      try {
        const repositories = await githubService.getRepositories();
        setRepos(repositories);
      } catch (err) {
        setError(err instanceof Error ? err.message : "Failed to fetch repositories");
      } finally {
        setLoading(false);
      }
    };

    fetchRepositories();
  }, [githubService]);

  return (
    <>
      <Form {...form}>
        <form className="space-y-2">
          <FormField
            control={form.control}
            name="repositoryId"
            render={({ field }) => (
              <FormItem>
                <Select
                  onValueChange={(value) => field.onChange(Number(value))}
                  value={field.value?.toString()}
                  disabled={loading || !projectId || !!!githubService}
                >
                  <FormControl>
                    <SelectTrigger>
                      <SelectValue placeholder={!!githubService ? "Select a repository" : "GitHub not configured"} />
                    </SelectTrigger>
                  </FormControl>
                  <SelectContent>
                    {repos.map((repo) => (
                      <SelectItem key={repo.id} value={repo.id.toString()}>
                        {repo.full_name}
                        {repo.description && ` - ${repo.description}`}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <FormMessage />
                {error && <p className="text-sm text-red-500">{error}</p>}
                {loading && <p className="text-sm text-gray-500">Loading repositories...</p>}
                {!!!githubService && (
                  <Alert variant="destructive" className="mt-2">
                    <AlertCircle className="h-4 w-4" />
                    <AlertDescription>
                      GitHub access token is not configured. Please configure it in the Integrations tab.
                    </AlertDescription>
                  </Alert>
                )}
              </FormItem>
            )}
          />
        </form>
      </Form>
    </>);
}