'use client';

import { useState } from 'react';
import { useMutation, useQuery } from 'convex/react';
import { Check, Copy, ExternalLink, Plus, Trash2 } from 'lucide-react';
import { toast } from 'sonner';

import type { Doc } from '@spoon/backend/convex/_generated/dataModel.js';
import { api } from '@spoon/backend/convex/_generated/api.js';
import {
  Button,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
  Input,
  Label,
} from '@spoon/ui';

const RemoteRow = ({
  label,
  url,
  remoteName,
  onRemove,
}: {
  label: string;
  url: string;
  remoteName?: string;
  onRemove?: () => Promise<void>;
}) => {
  const [copied, setCopied] = useState(false);

  const copy = async () => {
    try {
      await navigator.clipboard.writeText(url);
      setCopied(true);
      toast.success(`${label} URL copied.`);
      window.setTimeout(() => setCopied(false), 1800);
    } catch (error) {
      console.error(error);
      toast.error('Could not copy remote URL.');
    }
  };

  return (
    <div className='border-border space-y-2 border-t pt-3 first:border-t-0 first:pt-0'>
      <div className='flex flex-wrap items-center justify-between gap-2'>
        <div>
          <p className='text-sm font-medium'>{label}</p>
          {remoteName ? (
            <p className='text-muted-foreground text-xs'>
              git remote: {remoteName}
            </p>
          ) : null}
        </div>
        <div className='flex gap-2'>
          <Button type='button' variant='outline' size='icon' onClick={copy}>
            {copied ? (
              <Check className='size-4' />
            ) : (
              <Copy className='size-4' />
            )}
          </Button>
          <Button type='button' variant='outline' size='icon' asChild>
            <a
              href={url}
              target='_blank'
              rel='noreferrer'
              aria-label={`Open ${label} repository`}
            >
              <ExternalLink className='size-4' />
            </a>
          </Button>
          {onRemove ? (
            <Button
              type='button'
              variant='outline'
              size='icon'
              onClick={() => void onRemove()}
            >
              <Trash2 className='size-4' />
            </Button>
          ) : null}
        </div>
      </div>
      <Input
        readOnly
        value={url}
        className='font-mono text-xs'
        onFocus={(event) => event.currentTarget.select()}
      />
    </div>
  );
};

export const SpoonClonePanel = ({ spoon }: { spoon: Doc<'spoons'> }) => {
  const remotes =
    useQuery(api.spoonRemotes.listForSpoon, { spoonId: spoon._id }) ?? [];
  const createRemote = useMutation(api.spoonRemotes.create);
  const removeRemote = useMutation(api.spoonRemotes.remove);
  const [label, setLabel] = useState('');
  const [remoteName, setRemoteName] = useState('');
  const [url, setUrl] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const [remoteDialogOpen, setRemoteDialogOpen] = useState(false);
  const cloneUrl = spoon.forkUrl;

  const addRemote = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setSubmitting(true);
    try {
      await createRemote({
        spoonId: spoon._id,
        label,
        url,
        remoteName: remoteName || undefined,
      });
      setLabel('');
      setRemoteName('');
      setUrl('');
      setRemoteDialogOpen(false);
      toast.success('Remote added.');
    } catch (error) {
      console.error(error);
      toast.error('Could not add remote.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Card className='shadow-none'>
      <CardHeader className='flex-row items-center justify-between gap-4 pb-3'>
        <CardTitle className='text-base'>Clone your fork</CardTitle>
        <Dialog open={remoteDialogOpen} onOpenChange={setRemoteDialogOpen}>
          <DialogTrigger asChild>
            <Button type='button' variant='outline' size='sm'>
              <Plus className='size-4' />
              Add remote
            </Button>
          </DialogTrigger>
          <DialogContent className='sm:max-w-lg'>
            <DialogHeader>
              <DialogTitle>Add git remote</DialogTitle>
              <DialogDescription>
                Store another repository URL to copy from this Spoon. GitHub
                remains the source of truth for upstream maintenance.
              </DialogDescription>
            </DialogHeader>
            <form onSubmit={addRemote} className='space-y-4'>
              <div className='grid gap-3 md:grid-cols-[1fr_0.7fr]'>
                <div className='grid gap-2'>
                  <Label htmlFor='remote-label'>Label</Label>
                  <Input
                    id='remote-label'
                    value={label}
                    placeholder='Gitea mirror'
                    required
                    onChange={(event) => setLabel(event.target.value)}
                  />
                </div>
                <div className='grid gap-2'>
                  <Label htmlFor='remote-name'>Git remote name</Label>
                  <Input
                    id='remote-name'
                    value={remoteName}
                    placeholder='gitea'
                    onChange={(event) => setRemoteName(event.target.value)}
                  />
                </div>
              </div>
              <div className='grid gap-2'>
                <Label htmlFor='remote-url'>Repository URL</Label>
                <Input
                  id='remote-url'
                  value={url}
                  placeholder='https://git.example.com/you/project.git'
                  required
                  onChange={(event) => setUrl(event.target.value)}
                />
              </div>
              <DialogFooter className='mt-2'>
                <Button type='submit' disabled={submitting}>
                  <Plus className='size-4' />
                  {submitting ? 'Adding...' : 'Add remote'}
                </Button>
              </DialogFooter>
            </form>
          </DialogContent>
        </Dialog>
      </CardHeader>
      <CardContent className='space-y-3'>
        {cloneUrl ? (
          <>
            <RemoteRow
              label='Primary fork'
              remoteName='origin'
              url={cloneUrl}
            />
            <p className='text-muted-foreground text-xs'>
              This GitHub fork remains Spoon&apos;s source of truth for upstream
              maintenance.
            </p>
          </>
        ) : (
          <p className='text-muted-foreground text-sm'>
            Add fork metadata before Spoon can show a clone URL.
          </p>
        )}
        {remotes.length ? (
          <div className='space-y-3 pt-2'>
            {remotes.map((remote) => (
              <RemoteRow
                key={remote._id}
                label={remote.label}
                remoteName={remote.remoteName}
                url={remote.url}
                onRemove={async () => {
                  await removeRemote({ remoteId: remote._id });
                  toast.success('Remote removed.');
                }}
              />
            ))}
          </div>
        ) : null}
      </CardContent>
    </Card>
  );
};
