import AdminLayout from "@/components/AdminLayout";
import FileUploadField from "@/components/admin/FileUploadField";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Textarea } from "@/components/ui/textarea";
import { assetUrl } from "@/lib/asset";
import { trpc } from "@/lib/trpc";
import type { PodcastEpisodio } from "@shared/types";
import { useEffect, useState } from "react";
import { toast } from "sonner";

const NONE = "none";

type TipoMidia = "audio" | "video" | "audio_video";

type EpisodioForm = {
  titulo: string;
  slug: string;
  descricao: string;
  arquivo: string;
  tipoMidia: TipoMidia;
  videoUrl: string;
  capa: string;
  duracao: string;
  numeroEpisodio: string;
  ordem: string;
  tags: string;
  transcricao: string;
  apresentadorId: string;
  programaId: string;
  status: "rascunho" | "publicado" | "agendado";
  ativo: boolean;
};

const emptyForm: EpisodioForm = {
  titulo: "",
  slug: "",
  descricao: "",
  arquivo: "",
  tipoMidia: "audio",
  videoUrl: "",
  capa: "",
  duracao: "",
  numeroEpisodio: "",
  ordem: "",
  tags: "",
  transcricao: "",
  apresentadorId: NONE,
  programaId: NONE,
  status: "publicado",
  ativo: true,
};

function episodioToForm(ep: PodcastEpisodio): EpisodioForm {
  return {
    titulo: ep.titulo,
    slug: ep.slug ?? "",
    descricao: ep.descricao ?? "",
    arquivo: ep.arquivo ?? "",
    tipoMidia: (ep.tipoMidia as TipoMidia) ?? "audio",
    videoUrl: ep.videoUrl ?? "",
    capa: ep.capa ?? "",
    duracao: ep.duracao != null ? String(ep.duracao) : "",
    numeroEpisodio: ep.numeroEpisodio != null ? String(ep.numeroEpisodio) : "",
    ordem: ep.ordem != null ? String(ep.ordem) : "",
    tags: ep.tags ?? "",
    transcricao: ep.transcricao ?? "",
    apresentadorId: ep.apresentadorId != null ? String(ep.apresentadorId) : NONE,
    programaId: ep.programaId != null ? String(ep.programaId) : NONE,
    status: ep.status ?? "publicado",
    ativo: ep.ativo === 1,
  };
}

// Detecta se uma URL é do YouTube ou Vimeo para exibir preview no admin
function getVideoEmbedUrl(url: string): string | null {
  if (!url) return null;
  // YouTube
  const ytMatch = url.match(
    /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
  );
  if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}`;
  // Vimeo
  const vimeoMatch = url.match(/vimeo\.com\/(\d+)/);
  if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}`;
  return null;
}

// Detecção automática de duração — mesma técnica já usada no admin de
// Faixas (Música). Cria um <audio> temporário só para ler os metadados
// (preload="metadata" evita baixar o arquivo inteiro); quando o
// navegador expõe a duração real, preenche o campo sozinho — sem isso o
// administrador precisava digitar a duração manualmente pra cada episódio.
function detectarDuracao(arquivoUrl: string, onDetected: (segundos: number) => void) {
  const url = assetUrl(arquivoUrl);
  if (!url) return;
  const audio = new Audio();
  audio.preload = "metadata";
  audio.addEventListener("loadedmetadata", () => {
    if (isFinite(audio.duration) && audio.duration > 0) {
      onDetected(Math.round(audio.duration));
    }
  });
  audio.addEventListener("error", () => {
    // Falha silenciosa: se não der pra detectar, o campo continua editável
    // manualmente — nunca bloqueia o cadastro por causa disso.
  });
  audio.src = url;
}

export default function AdminEpisodios() {
  const [page, setPage] = useState(1);
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editing, setEditing] = useState<PodcastEpisodio | null>(null);
  const [form, setForm] = useState<EpisodioForm>(emptyForm);

  const utils = trpc.useUtils();
  const { data, isLoading } = trpc.podcast.admin.episodios.listar.useQuery({ page, limit: 20 });
  const apresentadoresQuery = trpc.podcast.admin.apresentadores.listar.useQuery({ page: 1, limit: 60 });
  const programasQuery = trpc.podcast.admin.programas.listar.useQuery({ page: 1, limit: 60 });

  const invalidate = () => {
    utils.podcast.admin.episodios.listar.invalidate();
    utils.podcast.admin.stats.invalidate();
  };

  const criarMutation = trpc.podcast.admin.episodios.criar.useMutation({
    onSuccess: () => {
      toast.success("Episódio criado.");
      invalidate();
      setDialogOpen(false);
    },
    onError: error => toast.error(error.message),
  });

  const atualizarMutation = trpc.podcast.admin.episodios.atualizar.useMutation({
    onSuccess: () => {
      toast.success("Episódio atualizado.");
      invalidate();
      setDialogOpen(false);
    },
    onError: error => toast.error(error.message),
  });

  const deletarMutation = trpc.podcast.admin.episodios.deletar.useMutation({
    onSuccess: () => {
      toast.success("Episódio removido.");
      invalidate();
    },
    onError: error => toast.error(error.message),
  });

  useEffect(() => {
    if (!dialogOpen) {
      setEditing(null);
      setForm(emptyForm);
    }
  }, [dialogOpen]);

  const handleEdit = (ep: PodcastEpisodio) => {
    setEditing(ep);
    setForm(episodioToForm(ep));
    setDialogOpen(true);
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Validação: se tipoMidia inclui vídeo, videoUrl é obrigatória
    if ((form.tipoMidia === "video" || form.tipoMidia === "audio_video") && !form.videoUrl.trim()) {
      toast.error("Informe a URL do vídeo (YouTube ou Vimeo).");
      return;
    }

    const payload = {
      titulo: form.titulo.trim(),
      slug: form.slug.trim() || undefined,
      descricao: form.descricao.trim() || null,
      arquivo: form.arquivo.trim() || null,
      tipoMidia: form.tipoMidia,
      videoUrl: form.videoUrl.trim() || null,
      capa: form.capa.trim() || null,
      duracao: form.duracao ? Number(form.duracao) : null,
      numeroEpisodio: form.numeroEpisodio ? Number(form.numeroEpisodio) : null,
      ordem: form.ordem ? Number(form.ordem) : null,
      tags: form.tags.trim() || null,
      transcricao: form.transcricao.trim() || null,
      apresentadorId: form.apresentadorId === NONE ? null : Number(form.apresentadorId),
      programaId: form.programaId === NONE ? null : Number(form.programaId),
      status: form.status,
      ativo: form.ativo ? 1 : 0,
    };

    if (editing) {
      atualizarMutation.mutate({ id: editing.id, ...payload });
    } else {
      criarMutation.mutate(payload);
    }
  };

  const handleDelete = (ep: PodcastEpisodio) => {
    if (!window.confirm(`Excluir o episódio "${ep.titulo}"? Esta ação não pode ser desfeita.`)) return;
    deletarMutation.mutate({ id: ep.id });
  };

  const isSaving = criarMutation.isPending || atualizarMutation.isPending;

  // Label do tipo de mídia para exibição na tabela
  const tipoMidiaLabel: Record<TipoMidia, string> = {
    audio: "🎵 Áudio",
    video: "🎬 Vídeo",
    audio_video: "🎬🎵 Áudio+Vídeo",
  };

  // Preview do vídeo no formulário
  const videoEmbedUrl = getVideoEmbedUrl(form.videoUrl);
  const mostraVideoUrl = form.tipoMidia === "video" || form.tipoMidia === "audio_video";
  const mostraArquivoAudio = form.tipoMidia === "audio" || form.tipoMidia === "audio_video";

  return (
    <AdminLayout>
      <div className="p-6 space-y-6">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-2xl font-bold font-display text-sof-gold">Episódios</h1>
            <p className="text-sm text-sof-text-3 mt-1">
              {data?.total ?? 0} episódios cadastrados
            </p>
          </div>
          <Button
            onClick={() => setDialogOpen(true)}
            className="bg-sof-gold text-sof-borgonha hover:bg-sof-gold-light font-bold"
          >
            + Novo Episódio
          </Button>
        </div>

        {isLoading ? (
          <p className="text-sof-text-3">Carregando...</p>
        ) : (
          <Table>
            <TableHeader>
              <TableRow className="border-sof-border">
                <TableHead className="text-sof-text-3">Título</TableHead>
                <TableHead className="text-sof-text-3">Tipo</TableHead>
                <TableHead className="text-sof-text-3">Série</TableHead>
                <TableHead className="text-sof-text-3">Status</TableHead>
                <TableHead className="text-sof-text-3">Ativo</TableHead>
                <TableHead className="text-sof-text-3 text-right">Ações</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {data?.episodios.length ? (
                data.episodios.map(ep => (
                  <TableRow key={ep.id} className="border-sof-border hover:bg-sof-surface">
                    <TableCell className="text-sof-text font-medium max-w-xs truncate">
                      {ep.titulo}
                    </TableCell>
                    <TableCell className="text-sof-text-3 text-sm">
                      {tipoMidiaLabel[(ep.tipoMidia as TipoMidia) ?? "audio"]}
                    </TableCell>
                    <TableCell className="text-sof-text-3 text-sm">
                      {programasQuery.data?.programas.find(p => p.id === ep.programaId)?.titulo ?? "—"}
                    </TableCell>
                    <TableCell className="text-sof-text-3 text-sm capitalize">{ep.status}</TableCell>
                    <TableCell className="text-sof-text-3 text-sm">
                      {ep.ativo === 1 ? "✓" : "✗"}
                    </TableCell>
                    <TableCell className="text-right">
                      <div className="flex justify-end gap-2">
                        <Button
                          size="sm"
                          variant="outline"
                          className="border-sof-border text-sof-text hover:bg-sof-surface"
                          onClick={() => handleEdit(ep)}
                        >
                          Editar
                        </Button>
                        <Button
                          size="sm"
                          variant="destructive"
                          onClick={() => handleDelete(ep)}
                        >
                          Excluir
                        </Button>
                      </div>
                    </TableCell>
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={6} className="text-center text-sof-text-3">
                    Nenhum episódio cadastrado.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        )}

        {!!data && data.pages > 1 && (
          <div className="flex items-center justify-center gap-4 mt-6">
            <Button
              variant="outline"
              size="sm"
              disabled={page <= 1}
              onClick={() => setPage(p => p - 1)}
              className="border-sof-border text-sof-text hover:bg-sof-surface"
            >
              ← Anterior
            </Button>
            <span className="text-sm text-sof-text-3">
              Página {data.page} de {data.pages}
            </span>
            <Button
              variant="outline"
              size="sm"
              disabled={page >= data.pages}
              onClick={() => setPage(p => p + 1)}
              className="border-sof-border text-sof-text hover:bg-sof-surface"
            >
              Próxima →
            </Button>
          </div>
        )}

        <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
          <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
            <DialogHeader>
              <DialogTitle>{editing ? "Editar episódio" : "Novo episódio"}</DialogTitle>
            </DialogHeader>

            <div className="space-y-4">
              <div className="grid grid-cols-2 gap-4">

                {/* Título */}
                <div className="col-span-2 space-y-2">
                  <Label>Título *</Label>
                  <Input
                    required
                    value={form.titulo}
                    onChange={e => setForm(f => ({ ...f, titulo: e.target.value }))}
                  />
                </div>

                {/* Slug */}
                <div className="space-y-2">
                  <Label>Slug</Label>
                  <Input
                    value={form.slug}
                    onChange={e => setForm(f => ({ ...f, slug: e.target.value }))}
                    placeholder="gerado automaticamente se vazio"
                  />
                </div>

                {/* Status */}
                <div className="space-y-2">
                  <Label>Status</Label>
                  <Select
                    value={form.status}
                    onValueChange={v => setForm(f => ({ ...f, status: v as EpisodioForm["status"] }))}
                  >
                    <SelectTrigger className="w-full">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="publicado">Publicado</SelectItem>
                      <SelectItem value="rascunho">Rascunho</SelectItem>
                      <SelectItem value="agendado">Agendado</SelectItem>
                    </SelectContent>
                  </Select>
                </div>

                {/* Descrição */}
                <div className="col-span-2 space-y-2">
                  <Label>Descrição</Label>
                  <Textarea
                    rows={3}
                    value={form.descricao}
                    onChange={e => setForm(f => ({ ...f, descricao: e.target.value }))}
                  />
                </div>

                {/* ── TIPO DE MÍDIA ─────────────────────────────────────── */}
                <div className="col-span-2 space-y-2">
                  <Label>Tipo de mídia *</Label>
                  <Select
                    value={form.tipoMidia}
                    onValueChange={v => setForm(f => ({ ...f, tipoMidia: v as TipoMidia }))}
                  >
                    <SelectTrigger className="w-full">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="audio">🎵 Somente Áudio</SelectItem>
                      <SelectItem value="video">🎬 Somente Vídeo (YouTube/Vimeo)</SelectItem>
                      <SelectItem value="audio_video">🎬🎵 Áudio + Vídeo</SelectItem>
                    </SelectContent>
                  </Select>
                  <p className="text-xs text-sof-text-3">
                    {form.tipoMidia === "audio" && "Upload de arquivo MP3 ou outro formato de áudio."}
                    {form.tipoMidia === "video" && "Cole o link do YouTube ou Vimeo. Não é necessário fazer upload."}
                    {form.tipoMidia === "audio_video" && "Este episódio tem versão em áudio e vídeo. Faça o upload do áudio e informe o link do vídeo."}
                  </p>
                </div>

                {/* URL do vídeo — exibido se tipoMidia inclui vídeo */}
                {mostraVideoUrl && (
                  <div className="col-span-2 space-y-2">
                    <Label>URL do vídeo (YouTube ou Vimeo) *</Label>
                    <Input
                      type="url"
                      placeholder="https://www.youtube.com/watch?v=..."
                      value={form.videoUrl}
                      onChange={e => setForm(f => ({ ...f, videoUrl: e.target.value }))}
                    />
                    {/* Preview do vídeo */}
                    {videoEmbedUrl && (
                      <div className="mt-2 rounded-lg overflow-hidden aspect-video bg-black">
                        <iframe
                          src={videoEmbedUrl}
                          className="w-full h-full"
                          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                          allowFullScreen
                          title="Preview do vídeo"
                        />
                      </div>
                    )}
                  </div>
                )}

                {/* Upload de áudio — exibido se tipoMidia inclui áudio */}
                {mostraArquivoAudio && (
                  <div className="col-span-2">
                    <FileUploadField
                      label={form.tipoMidia === "audio_video" ? "Arquivo de áudio (versão só áudio)" : "Arquivo de áudio (MP3)"}
                      type="audio"
                      value={form.arquivo}
                      onChange={url => {
                        setForm(f => ({ ...f, arquivo: url }));
                        if (url) {
                          detectarDuracao(url, segundos =>
                            setForm(f => ({ ...f, duracao: String(segundos) }))
                          );
                        }
                      }}
                    />
                  </div>
                )}

                {/* Capa */}
                <div className="col-span-2">
                  <FileUploadField
                    label="Capa"
                    type="image"
                    value={form.capa}
                    onChange={url => setForm(f => ({ ...f, capa: url }))}
                  />
                </div>

                {/* Duração */}
                <div className="space-y-2">
                  <Label>Duração (segundos) — detectada automaticamente</Label>
                  <Input
                    type="number"
                    min={0}
                    value={form.duracao}
                    onChange={e => setForm(f => ({ ...f, duracao: e.target.value }))}
                  />
                </div>

                {/* Número do episódio */}
                <div className="space-y-2">
                  <Label>Número do episódio</Label>
                  <Input
                    type="number"
                    min={0}
                    value={form.numeroEpisodio}
                    onChange={e => setForm(f => ({ ...f, numeroEpisodio: e.target.value }))}
                  />
                </div>

                {/* Apresentador */}
                <div className="space-y-2">
                  <Label>Apresentador</Label>
                  <Select
                    value={form.apresentadorId}
                    onValueChange={v => setForm(f => ({ ...f, apresentadorId: v }))}
                  >
                    <SelectTrigger className="w-full">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={NONE}>Nenhum</SelectItem>
                      {apresentadoresQuery.data?.apresentadores.map(a => (
                        <SelectItem key={a.id} value={String(a.id)}>
                          {a.nome}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Série/Programa */}
                <div className="space-y-2">
                  <Label>Série/Programa</Label>
                  <Select
                    value={form.programaId}
                    onValueChange={v => setForm(f => ({ ...f, programaId: v }))}
                  >
                    <SelectTrigger className="w-full">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value={NONE}>Nenhuma</SelectItem>
                      {programasQuery.data?.programas.map(p => (
                        <SelectItem key={p.id} value={String(p.id)}>
                          {p.titulo}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>

                {/* Ordem */}
                <div className="space-y-2">
                  <Label>Ordem</Label>
                  <Input
                    type="number"
                    value={form.ordem}
                    onChange={e => setForm(f => ({ ...f, ordem: e.target.value }))}
                  />
                </div>

                {/* Tags */}
                <div className="space-y-2">
                  <Label>Tags (separadas por vírgula)</Label>
                  <Input
                    value={form.tags}
                    onChange={e => setForm(f => ({ ...f, tags: e.target.value }))}
                  />
                </div>

                {/* Transcrição */}
                <div className="col-span-2 space-y-2">
                  <Label>Transcrição</Label>
                  <Textarea
                    rows={4}
                    value={form.transcricao}
                    onChange={e => setForm(f => ({ ...f, transcricao: e.target.value }))}
                  />
                </div>

                {/* Ativo */}
                <div className="col-span-2 flex items-center gap-3">
                  <Switch
                    checked={form.ativo}
                    onCheckedChange={checked => setForm(f => ({ ...f, ativo: checked }))}
                  />
                  <Label>Ativo (visível no site)</Label>
                </div>
              </div>

              <DialogFooter>
                <Button
                  type="button"
                  variant="outline"
                  onClick={() => setDialogOpen(false)}
                  className="border-sof-border text-sof-text hover:bg-sof-surface"
                >
                  Cancelar
                </Button>
                <Button
                  onClick={handleSubmit}
                  disabled={isSaving}
                  className="bg-sof-gold text-sof-borgonha hover:bg-sof-gold-light font-bold"
                >
                  {isSaving ? "Salvando..." : "Salvar"}
                </Button>
              </DialogFooter>
            </div>
          </DialogContent>
        </Dialog>
      </div>
    </AdminLayout>
  );
}
