'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useAction, useQuery } from 'convex/react';
import { makeFunctionReference } from 'convex/server';
import { GitFork } from 'lucide-react';
import { toast } from 'sonner';

import { api } from '@spoon/backend/convex/_generated/api.js';
import { Button, Card, CardContent, Input, Label, Textarea } from '@spoon/ui';

type FormState = {
  upstreamOwner: string;
  upstreamRepo: string;
  forkName: string;
  organization: string;
  description: string;
};

const initialState: FormState = {
  upstreamOwner: '',
  upstreamRepo: '',
  forkName: '',
  organization: '',
  description: '',
};

const createForkRef = makeFunctionReference<
  'action',
  {
    upstreamOwner: string;
    upstreamRepo: string;
    name?: string;
    description?: string;
    organization?: string;
  },
  string
>('githubNode:createFork');

const TextField = ({
  id,
  label,
  value,
  onChange,
  required,
  placeholder,
}: {
  id: keyof FormState;
  label: string;
  value: string;
  onChange: (value: string) => void;
  required?: boolean;
  placeholder?: string;
}) => (
  <div className='grid gap-2'>
    <Label htmlFor={id}>{label}</Label>
    <Input
      id={id}
      value={value}
      required={required}
      placeholder={placeholder}
      onChange={(event) => onChange(event.target.value)}
    />
  </div>
);

export const GitHubForkForm = () => {
  const router = useRouter();
  const connection = useQuery(api.github.getConnection, {});
  const createFork = useAction(createForkRef);
  const [form, setForm] = useState<FormState>(initialState);
  const [submitting, setSubmitting] = useState(false);

  const update = <K extends keyof FormState>(key: K, value: FormState[K]) => {
    setForm((current) => ({ ...current, [key]: value }));
  };

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setSubmitting(true);
    try {
      await createFork({
        upstreamOwner: form.upstreamOwner,
        upstreamRepo: form.upstreamRepo,
        name: form.forkName || undefined,
        organization: form.organization || undefined,
        description: form.description || undefined,
      });
      toast.success('Fork created and added as a Spoon.');
      router.push('/spoons');
    } catch (error) {
      console.error(error);
      toast.error('Could not create the GitHub fork.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Card className='shadow-none'>
      <CardContent className='p-5'>
        <div className='mb-5 flex gap-3'>
          <div className='bg-primary/10 text-primary flex size-10 shrink-0 items-center justify-center rounded-lg'>
            <GitFork className='size-5' />
          </div>
          <div>
            <p className='font-medium'>Fork with GitHub</p>
            <p className='text-muted-foreground mt-1 text-sm'>
              Create a real GitHub fork through the connected GitHub App and
              record it as a Spoon.
            </p>
          </div>
        </div>
        <form onSubmit={handleSubmit} className='grid gap-5'>
          <div className='grid gap-4 md:grid-cols-2'>
            <TextField
              id='upstreamOwner'
              label='Upstream owner'
              value={form.upstreamOwner}
              required
              placeholder='vercel'
              onChange={(value) => update('upstreamOwner', value)}
            />
            <TextField
              id='upstreamRepo'
              label='Upstream repository'
              value={form.upstreamRepo}
              required
              placeholder='next.js'
              onChange={(value) => update('upstreamRepo', value)}
            />
            <TextField
              id='forkName'
              label='Fork name'
              value={form.forkName}
              placeholder='Optional custom repository name'
              onChange={(value) => update('forkName', value)}
            />
            <TextField
              id='organization'
              label='Organization'
              value={form.organization}
              placeholder='Optional org target'
              onChange={(value) => update('organization', value)}
            />
          </div>
          <div className='grid gap-2'>
            <Label htmlFor='description'>Description</Label>
            <Textarea
              id='description'
              value={form.description}
              placeholder='Optional Spoon note'
              onChange={(event) => update('description', event.target.value)}
            />
          </div>
          <div className='flex justify-end'>
            <Button type='submit' disabled={!connection || submitting}>
              {submitting ? 'Forking...' : 'Create GitHub fork'}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  );
};
