import { useMutation, useQueryClient } from '@tanstack/react-query';
import { ArrowRight, Globe, Lock, Shield, Trash2 } from 'lucide-react';
import { type FormEvent, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { ReposService } from '@/client/services/ReposService';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Spinner } from '@/components/ui/spinner';
import { useRepo } from '@/hooks/repo/useRepo';
import { useRepoBranches } from '@/hooks/repo/useRepoBranches';
import { useRepoProtectionRules } from '@/hooks/repo/useRepoProtectionRules';
import { cn } from '@/lib/utils';

export function RepoSettingsPage() {
  const { workspaceName = '', repoName = '' } = useParams();
  const qc = useQueryClient();
  const navigate = useNavigate();
  const { data: repo, isLoading } = useRepo(workspaceName, repoName);
  const { data: branches } = useRepoBranches(workspaceName, repoName);
  const { data: protects } = useRepoProtectionRules(workspaceName, repoName);

  const [visibility, setVisibility] = useState(repo?.visibility ?? 'Private');
  const [defaultBranch, setDefaultBranch] = useState(repo?.default_branch ?? '');
  const [error, setError] = useState('');

  const [newProtectPattern, setNewProtectPattern] = useState('');
  const [transferTarget, setTransferTarget] = useState('');

  const updateRepo = useMutation({
    mutationFn: (formData: { name: string; description: string }) =>
      ReposService.repoUpdate({
        workspaceName,
        repoName,
        requestBody: {
          name: formData.name,
          description: formData.description,
          visibility,
          default_branch: defaultBranch,
        },
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName] });
    },
    onError: (err) => {
      setError(err instanceof Error ? err.message : 'Failed to update');
    },
  });

  const deleteRepo = useMutation({
    mutationFn: () => ReposService.repoDelete({ workspaceName, repoName }),
    onSuccess: () => navigate(`/${workspaceName}/repos`),
  });

  const archiveRepo = useMutation({
    mutationFn: () => ReposService.repoArchive({ workspaceName, repoName }),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName] }),
  });

  const unarchiveRepo = useMutation({
    mutationFn: () => ReposService.repoUnarchive({ workspaceName, repoName }),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName] }),
  });

  const createProtect = useMutation({
    mutationFn: (pattern: string) =>
      ReposService.repoCreateProtectionRule({
        workspaceName,
        repoName,
        requestBody: { pattern, require_approvals: 1 },
      }),
    onSuccess: () =>
      qc.invalidateQueries({
        queryKey: ['repo', workspaceName, repoName, 'protection-rules'],
      }),
  });

  const deleteProtect = useMutation({
    mutationFn: (ruleId: string) =>
      ReposService.repoDeleteProtectionRule({ workspaceName, repoName, ruleId }),
    onSuccess: () =>
      qc.invalidateQueries({
        queryKey: ['repo', workspaceName, repoName, 'protection-rules'],
      }),
  });

  const transferRepo = useMutation({
    mutationFn: () =>
      ReposService.repoTransferOwner({
        workspaceName,
        repoName,
        requestBody: { new_owner_id: transferTarget },
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['repo', workspaceName, repoName] });
      setTransferTarget('');
    },
  });

  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setError('');
    const form = new FormData(e.currentTarget);
    updateRepo.mutate({
      name: (form.get('name') as string) || '',
      description: (form.get('description') as string) || '',
    });
  };

  if (isLoading || !repo) {
    return (
      <div className="flex items-center gap-2 p-4 text-[13px] text-muted-foreground">
        <Spinner />
      </div>
    );
  }

  return (
    <div className="max-w-2xl space-y-8">
      <form className="space-y-5" onSubmit={handleSubmit}>
        <h2 className="text-[15px] font-bold text-foreground">General</h2>
        <div>
          <label htmlFor="repo-name" className="text-[13px] font-medium text-foreground">
            Repository name
          </label>
          <Input
            id="repo-name"
            className="mt-1 h-9 text-[13px]"
            name="name"
            defaultValue={repo.name}
          />
        </div>
        <div>
          <label htmlFor="repo-desc" className="text-[13px] font-medium text-foreground">
            Description <span className="text-muted-foreground">(optional)</span>
          </label>
          <Input
            id="repo-desc"
            className="mt-1 h-9 text-[13px]"
            name="description"
            defaultValue={repo.description ?? ''}
          />
        </div>
        <div>
          <label htmlFor="repo-branch" className="text-[13px] font-medium text-foreground">
            Default branch
          </label>
          {branches && branches.length > 0 ? (
            <select
              id="repo-branch"
              className="mt-1 h-9 w-48 rounded-lg border border-input bg-transparent px-2.5 text-[13px] text-foreground"
              value={defaultBranch}
              onChange={(e) => setDefaultBranch(e.target.value)}
            >
              {branches.map((b: { name: string }) => (
                <option key={b.name} value={b.name}>
                  {b.name}
                </option>
              ))}
            </select>
          ) : (
            <Input
              id="repo-branch"
              className="mt-1 h-9 w-48 text-[13px]"
              defaultValue={repo.default_branch}
              onChange={(e) => setDefaultBranch(e.target.value)}
            />
          )}
        </div>
        <div>
          <span className="text-[13px] font-medium text-foreground">Visibility</span>
          <div className="mt-1 flex gap-2">
            {(['Private', 'Public'] as const).map((opt) => (
              <button
                key={opt}
                type="button"
                className={cn(
                  'flex items-start gap-2 rounded-lg border p-3 text-left transition-colors',
                  visibility === opt
                    ? 'border-primary bg-primary/5'
                    : 'border-border hover:border-muted-foreground/30',
                )}
                onClick={() => setVisibility(opt)}
              >
                <span
                  className={cn(
                    'mt-0.5',
                    visibility === opt ? 'text-primary' : 'text-muted-foreground',
                  )}
                >
                  {opt === 'Private' ? (
                    <Lock className="size-3.5" />
                  ) : (
                    <Globe className="size-3.5" />
                  )}
                </span>
                <div>
                  <span
                    className={cn(
                      'text-[13px] font-medium',
                      visibility === opt ? 'text-foreground' : 'text-muted-foreground',
                    )}
                  >
                    {opt}
                  </span>
                  <p className="text-[11px] text-muted-foreground">
                    {opt === 'Private'
                      ? 'Only members can see this repository'
                      : 'Anyone can see this repository'}
                  </p>
                </div>
              </button>
            ))}
          </div>
        </div>
        {error && <p className="text-[12px] text-destructive">{error}</p>}
        <Button type="submit" disabled={updateRepo.isPending}>
          {updateRepo.isPending ? 'Saving...' : 'Save changes'}
        </Button>
      </form>

      <div className="space-y-3">
        <h2 className="flex items-center gap-2 text-[15px] font-bold text-foreground">
          <Shield className="size-4" />
          Branch protection rules
        </h2>
        {(protects ?? []).length > 0 && (
          <div className="overflow-hidden rounded-lg border border-border">
            {(protects ?? []).map((p) => (
              <div
                key={p.id}
                className="flex items-center gap-3 border-b border-border px-4 py-2.5 last:border-b-0"
              >
                <Shield className="size-4 text-primary shrink-0" />
                <span className="text-[13px] font-semibold text-foreground">{p.pattern}</span>
                {p.require_approvals > 0 && (
                  <span className="text-[10px] text-muted-foreground">
                    {p.require_approvals} approval(s)
                  </span>
                )}
                <Button
                  size="icon-sm"
                  variant="ghost"
                  className="ml-auto text-muted-foreground hover:text-destructive"
                  onClick={() => deleteProtect.mutate(p.id)}
                >
                  <Trash2 className="size-3.5" />
                </Button>
              </div>
            ))}
          </div>
        )}
        <div className="flex items-center gap-2">
          <Input
            className="h-9 flex-1 text-[13px]"
            placeholder="Branch pattern (e.g. main, release/*)"
            value={newProtectPattern}
            onChange={(e) => setNewProtectPattern(e.target.value)}
          />
          <Button
            disabled={!newProtectPattern.trim() || createProtect.isPending}
            onClick={() => {
              createProtect.mutate(newProtectPattern.trim());
              setNewProtectPattern('');
            }}
          >
            Add rule
          </Button>
        </div>
      </div>

      <div className="space-y-3 rounded-lg border border-red-900/30 p-4">
        <h2 className="flex items-center gap-2 text-[15px] font-bold text-destructive">
          <Trash2 className="size-4" />
          Danger Zone
        </h2>

        <div className="flex items-center justify-between">
          <div>
            <p className="text-[13px] font-medium text-foreground">
              {repo.archived_at ? 'Unarchive repository' : 'Archive repository'}
            </p>
            <p className="text-[11px] text-muted-foreground">
              {repo.archived_at
                ? 'Restore write access to this repository'
                : 'Make this repository read-only'}
            </p>
          </div>
          <Button
            variant="outline"
            disabled={archiveRepo.isPending || unarchiveRepo.isPending}
            onClick={() => {
              if (repo.archived_at) unarchiveRepo.mutate();
              else archiveRepo.mutate();
            }}
          >
            {repo.archived_at ? 'Unarchive' : 'Archive'}
          </Button>
        </div>

        <div className="flex items-center justify-between border-t border-red-900/30 pt-3">
          <div>
            <p className="text-[13px] font-medium text-foreground">Transfer ownership</p>
            <p className="text-[11px] text-muted-foreground">
              Move this repository to another user
            </p>
          </div>
          <div className="flex items-center gap-2">
            <Input
              className="h-8 w-40 text-[12px]"
              placeholder="New owner ID"
              value={transferTarget}
              onChange={(e) => setTransferTarget(e.target.value)}
            />
            <Button
              variant="outline"
              disabled={!transferTarget.trim() || transferRepo.isPending}
              onClick={() => {
                if (confirm(`Transfer to ${transferTarget}?`)) transferRepo.mutate();
              }}
            >
              <ArrowRight className="size-3" />
              Transfer
            </Button>
          </div>
        </div>

        <div className="flex items-center justify-between border-t border-red-900/30 pt-3">
          <div>
            <p className="text-[13px] font-medium text-foreground">Delete this repository</p>
            <p className="text-[11px] text-muted-foreground">
              Once deleted, it cannot be recovered
            </p>
          </div>
          <Button
            variant="outline"
            disabled={deleteRepo.isPending}
            onClick={() => {
              if (confirm(`Permanently delete "${repoName}"? This cannot be undone.`))
                deleteRepo.mutate();
            }}
          >
            <Trash2 className="size-3" />
            Delete
          </Button>
        </div>
      </div>
    </div>
  );
}
