'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useMutation } from 'convex/react';
import { toast } from 'sonner';

import { api } from '@spoon/backend/convex/_generated/api.js';
import {
  Button,
  Input,
  Label,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Textarea,
} from '@spoon/ui';

const options = {
  provider: ['github', 'gitea', 'gitlab', 'other'],
  visibility: ['unknown', 'public', 'private', 'internal'],
  maintenanceMode: ['watch', 'auto_pr', 'paused'],
  syncCadence: ['daily', 'weekly', 'manual'],
  productionRefStrategy: ['default_branch', 'latest_release', 'tag_pattern'],
} as const;

type FormState = {
  name: string;
  description: string;
  provider: (typeof options.provider)[number];
  upstreamOwner: string;
  upstreamRepo: string;
  upstreamDefaultBranch: string;
  upstreamUrl: string;
  forkOwner: string;
  forkRepo: string;
  forkUrl: string;
  visibility: (typeof options.visibility)[number];
  maintenanceMode: (typeof options.maintenanceMode)[number];
  syncCadence: (typeof options.syncCadence)[number];
  productionRefStrategy: (typeof options.productionRefStrategy)[number];
};

const initialState: FormState = {
  name: '',
  description: '',
  provider: 'github',
  upstreamOwner: '',
  upstreamRepo: '',
  upstreamDefaultBranch: 'main',
  upstreamUrl: '',
  forkOwner: '',
  forkRepo: '',
  forkUrl: '',
  visibility: 'unknown',
  maintenanceMode: 'watch',
  syncCadence: 'daily',
  productionRefStrategy: 'default_branch',
};

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

export const NewSpoonForm = () => {
  const router = useRouter();
  const createManual = useMutation(api.spoons.createManual);
  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 createManual({
        ...form,
        description: form.description || undefined,
        forkOwner: form.forkOwner || undefined,
        forkRepo: form.forkRepo || undefined,
        forkUrl: form.forkUrl || undefined,
      });
      toast.success('Spoon created.');
      router.push('/spoons');
    } catch (error) {
      console.error(error);
      toast.error('Could not create Spoon.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <form
      onSubmit={handleSubmit}
      className='border-border bg-card grid gap-6 border p-5'
    >
      <div className='grid gap-4 md:grid-cols-2'>
        <TextField
          id='name'
          label='Spoon name'
          value={form.name}
          required
          onChange={(value) => update('name', value)}
        />
        <Select
          value={form.provider}
          onValueChange={(value) =>
            update('provider', value as FormState['provider'])
          }
        >
          <div className='grid gap-2'>
            <Label>Provider</Label>
            <SelectTrigger className='w-full'>
              <SelectValue />
            </SelectTrigger>
          </div>
          <SelectContent>
            {options.provider.map((value) => (
              <SelectItem key={value} value={value}>
                {value}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      </div>
      <div className='grid gap-2'>
        <Label htmlFor='description'>Description</Label>
        <Textarea
          id='description'
          value={form.description}
          onChange={(event) => update('description', event.target.value)}
        />
      </div>
      <div className='grid gap-4 md:grid-cols-2'>
        <TextField
          id='upstreamOwner'
          label='Upstream owner'
          value={form.upstreamOwner}
          required
          onChange={(value) => update('upstreamOwner', value)}
        />
        <TextField
          id='upstreamRepo'
          label='Upstream repository'
          value={form.upstreamRepo}
          required
          onChange={(value) => update('upstreamRepo', value)}
        />
        <TextField
          id='upstreamDefaultBranch'
          label='Upstream default branch'
          value={form.upstreamDefaultBranch}
          required
          onChange={(value) => update('upstreamDefaultBranch', value)}
        />
        <TextField
          id='upstreamUrl'
          label='Upstream URL'
          value={form.upstreamUrl}
          required
          onChange={(value) => update('upstreamUrl', value)}
        />
        <TextField
          id='forkOwner'
          label='Fork owner'
          value={form.forkOwner}
          onChange={(value) => update('forkOwner', value)}
        />
        <TextField
          id='forkRepo'
          label='Fork repository'
          value={form.forkRepo}
          onChange={(value) => update('forkRepo', value)}
        />
        <TextField
          id='forkUrl'
          label='Fork URL'
          value={form.forkUrl}
          onChange={(value) => update('forkUrl', value)}
        />
      </div>
      <div className='grid gap-4 md:grid-cols-4'>
        {(
          [
            'visibility',
            'maintenanceMode',
            'syncCadence',
            'productionRefStrategy',
          ] as const
        ).map((key) => (
          <Select
            key={key}
            value={form[key]}
            onValueChange={(value) => update(key, value as never)}
          >
            <div className='grid gap-2'>
              <Label>{key.replace(/([A-Z])/g, ' $1')}</Label>
              <SelectTrigger className='w-full'>
                <SelectValue />
              </SelectTrigger>
            </div>
            <SelectContent>
              {options[key].map((value) => (
                <SelectItem key={value} value={value}>
                  {value.replaceAll('_', ' ')}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        ))}
      </div>
      <div className='flex justify-end'>
        <Button type='submit' disabled={submitting}>
          {submitting ? 'Creating...' : 'Create Spoon'}
        </Button>
      </div>
    </form>
  );
};
