"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { Loader2, MapPin, Pencil, Plus, Store, Trash2 } from "lucide-react";
import { getSupabaseClient } from "@/lib/supabase";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog";
import { Aviso } from "@/components/ui/aviso";
import { FIO_DA_LINHA, FolhaDeAjustes, SecaoDeAjustes } from "@/components/ui/folha-de-ajustes";

export type CompanyAddress = {
  zip: string;
  street: string;
  number: string;
  complement: string;
  neighborhood: string;
  city: string;
  state: string;
};

type PickupLocation = {
  id: string;
  name: string;
  price: number;
  ready_in_days: number;
  zip: string | null;
  street: string | null;
  number: string | null;
  complement: string | null;
  neighborhood: string | null;
  city: string | null;
  state: string | null;
  instructions: string | null;
  source: string;
  position: number;
  active: boolean;
};

type PickupDraft = {
  name: string;
  price: string;
  ready_in_days: string;
  zip: string;
  street: string;
  number: string;
  complement: string;
  neighborhood: string;
  city: string;
  state: string;
  instructions: string;
};

const SELECT_COLUMNS =
  "id,name,price,ready_in_days,zip,street,number,complement,neighborhood,city,state,instructions,source,position,active";

const EMPTY_DRAFT: PickupDraft = {
  name: "",
  price: "0",
  ready_in_days: "0",
  zip: "",
  street: "",
  number: "",
  complement: "",
  neighborhood: "",
  city: "",
  state: "",
  instructions: "",
};

function onlyDigits(value: string) {
  return String(value || "").replace(/\D/g, "");
}

function formatZip(value: string) {
  const digits = onlyDigits(value).slice(0, 8);
  if (digits.length <= 5) return digits;
  return `${digits.slice(0, 5)}-${digits.slice(5)}`;
}

function formatMoney(value: number) {
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(Math.max(0, value));
}

function parsePrice(value: string) {
  const normalized = String(value || "")
    .replace(/[^\d,.-]/g, "")
    .replace(/\.(?=\d{3}\b)/g, "")
    .replace(",", ".");
  const parsed = Number(normalized);
  if (!Number.isFinite(parsed) || parsed <= 0) return 0;
  return Number(parsed.toFixed(2));
}

function buildAddressSummary(source: {
  street?: string | null;
  number?: string | null;
  complement?: string | null;
  neighborhood?: string | null;
  city?: string | null;
  state?: string | null;
  zip?: string | null;
}) {
  const zip = onlyDigits(String(source.zip || ""));
  return [
    [String(source.street || "").trim(), String(source.number || "").trim()].filter(Boolean).join(", "),
    String(source.complement || "").trim(),
    String(source.neighborhood || "").trim(),
    [String(source.city || "").trim(), String(source.state || "").trim().toUpperCase()].filter(Boolean).join(" / "),
    zip.length === 8 ? `CEP ${formatZip(zip)}` : "",
  ]
    .filter(Boolean)
    .join(" • ");
}

function draftFromLocation(location: PickupLocation): PickupDraft {
  return {
    name: location.name || "",
    price: String(Number(location.price) || 0),
    ready_in_days: String(Number(location.ready_in_days) || 0),
    zip: formatZip(location.zip || ""),
    street: location.street || "",
    number: location.number || "",
    complement: location.complement || "",
    neighborhood: location.neighborhood || "",
    city: location.city || "",
    state: location.state || "",
    instructions: location.instructions || "",
  };
}

export default function PickupLocationsTab({
  profileId,
  companyAddress,
  suggestedName,
}: {
  profileId: string | null;
  companyAddress: CompanyAddress;
  suggestedName: string;
}) {
  const [locations, setLocations] = useState<PickupLocation[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [busyId, setBusyId] = useState<string | null>(null);
  /* Confirmacao dentro da propria lista: o alerta do navegador mostra
     "localhost diz" e nao cabe explicar o que some da vitrine. */
  const [aExcluir, setAExcluir] = useState<PickupLocation | null>(null);
  const [zipLoading, setZipLoading] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [formOpen, setFormOpen] = useState(false);
  const [draft, setDraft] = useState<PickupDraft>(EMPTY_DRAFT);
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);

  const companySummary = useMemo(() => buildAddressSummary(companyAddress), [companyAddress]);
  const companyAddressIsUsable = Boolean(
    String(companyAddress.street || "").trim() && String(companyAddress.city || "").trim()
  );
  const hasCompanyLocation = locations.some((location) => location.source === "company_address");
  const showLoading = loading && Boolean(profileId);

  /* Sem setState sincrono aqui: o spinner ja nasce ligado e so e desligado
     depois do await, senao o efeito abaixo dispara um render em cascata. */
  const loadLocations = useCallback(async () => {
    if (!profileId) return;
    try {
      const supabase = getSupabaseClient();
      const { data, error } = await supabase
        .from("catalog_pickup_locations")
        .select(SELECT_COLUMNS)
        .eq("user_id", profileId)
        .order("position", { ascending: true })
        .order("created_at", { ascending: true });

      if (error) throw error;
      setLocations(
        ((data || []) as PickupLocation[]).map((row) => ({
          ...row,
          price: Number(row.price) || 0,
          ready_in_days: Number(row.ready_in_days) || 0,
        }))
      );
    } catch (error) {
      const text = String((error as { message?: unknown } | null)?.message || "");
      setMessage({
        type: "error",
        text: text.includes("catalog_pickup_locations")
          ? "Rode a migração supabase/migrations/20260824_add_catalog_pickup_locations.sql no Supabase."
          : "Não foi possível carregar os balcões de retirada.",
      });
    } finally {
      setLoading(false);
    }
  }, [profileId]);

  useEffect(() => {
    void loadLocations();
  }, [loadLocations]);

  const nextPosition = useMemo(() => {
    if (locations.length === 0) return 1;
    return Math.max(...locations.map((location) => Number(location.position) || 0)) + 1;
  }, [locations]);

  function openNewForm() {
    setEditingId(null);
    setDraft(EMPTY_DRAFT);
    setFormOpen(true);
    setMessage(null);
  }

  function openEditForm(location: PickupLocation) {
    setEditingId(location.id);
    setDraft(draftFromLocation(location));
    setFormOpen(true);
    setMessage(null);
  }

  function closeForm() {
    setFormOpen(false);
    setEditingId(null);
    setDraft(EMPTY_DRAFT);
  }

  function updateDraft<K extends keyof PickupDraft>(key: K, value: PickupDraft[K]) {
    setDraft((prev) => ({ ...prev, [key]: value }));
  }

  async function handleZipLookup(rawZip: string) {
    const zip = onlyDigits(rawZip);
    if (zip.length !== 8 || zipLoading) return;
    setZipLoading(true);
    try {
      const response = await fetch(`https://viacep.com.br/ws/${zip}/json/`);
      const data = (await response.json()) as {
        erro?: boolean;
        logradouro?: string;
        bairro?: string;
        localidade?: string;
        uf?: string;
      };
      if (!response.ok || data.erro) throw new Error("CEP não encontrado.");
      setDraft((prev) => ({
        ...prev,
        street: data.logradouro || prev.street,
        neighborhood: data.bairro || prev.neighborhood,
        city: data.localidade || prev.city,
        state: data.uf || prev.state,
      }));
    } catch {
      setMessage({ type: "error", text: "Não foi possível buscar esse CEP agora." });
    } finally {
      setZipLoading(false);
    }
  }

  async function handleSubmitDraft() {
    if (!profileId || saving) return;
    const name = draft.name.trim();
    const street = draft.street.trim();
    const city = draft.city.trim();

    if (!name) {
      setMessage({ type: "error", text: "Dê um nome ao balcão. É ele que o cliente vê na vitrine." });
      return;
    }
    if (!street || !city) {
      setMessage({ type: "error", text: "Informe pelo menos rua e cidade do balcão." });
      return;
    }

    setSaving(true);
    setMessage(null);

    const payload = {
      name,
      price: parsePrice(draft.price),
      ready_in_days: Math.max(0, Math.trunc(Number(draft.ready_in_days) || 0)),
      zip: onlyDigits(draft.zip) || null,
      street,
      number: draft.number.trim() || null,
      complement: draft.complement.trim() || null,
      neighborhood: draft.neighborhood.trim() || null,
      city,
      state: draft.state.trim().toUpperCase().slice(0, 2) || null,
      instructions: draft.instructions.trim() || null,
    };

    try {
      const supabase = getSupabaseClient();
      if (editingId) {
        const { error } = await supabase
          .from("catalog_pickup_locations")
          .update(payload)
          .eq("id", editingId)
          .eq("user_id", profileId);
        if (error) throw error;
      } else {
        const { error } = await supabase.from("catalog_pickup_locations").insert([
          {
            ...payload,
            user_id: profileId,
            source: "custom",
            position: nextPosition,
            active: true,
          },
        ]);
        if (error) throw error;
      }
      closeForm();
      await loadLocations();
      setMessage({ type: "success", text: editingId ? "Balcão atualizado." : "Balcão cadastrado." });
    } catch (error) {
      setMessage({
        type: "error",
        text: String((error as { message?: unknown } | null)?.message || "Não foi possível salvar o balcão."),
      });
    } finally {
      setSaving(false);
    }
  }

  async function handleUseCompanyAddress() {
    if (!profileId || saving || !companyAddressIsUsable) return;
    setSaving(true);
    setMessage(null);
    try {
      const supabase = getSupabaseClient();
      const { error } = await supabase.from("catalog_pickup_locations").insert([
        {
          user_id: profileId,
          name: suggestedName.trim() || "Retirada na loja",
          price: 0,
          ready_in_days: 0,
          zip: onlyDigits(companyAddress.zip) || null,
          street: companyAddress.street.trim() || null,
          number: companyAddress.number.trim() || null,
          complement: companyAddress.complement.trim() || null,
          neighborhood: companyAddress.neighborhood.trim() || null,
          city: companyAddress.city.trim() || null,
          state: companyAddress.state.trim().toUpperCase().slice(0, 2) || null,
          instructions: null,
          source: "company_address",
          position: nextPosition,
          active: true,
        },
      ]);
      if (error) throw error;
      await loadLocations();
      setMessage({ type: "success", text: "Retirada no endereço da empresa ativada." });
    } catch (error) {
      setMessage({
        type: "error",
        text: String((error as { message?: unknown } | null)?.message || "Não foi possível ativar a retirada."),
      });
    } finally {
      setSaving(false);
    }
  }

  async function handleToggleActive(location: PickupLocation, active: boolean) {
    if (!profileId || busyId) return;
    setBusyId(location.id);
    setMessage(null);
    /* Otimista: a vitrine só lê no próximo carregamento, então um erro aqui é
       revertido pelo reload logo abaixo. */
    setLocations((prev) => prev.map((item) => (item.id === location.id ? { ...item, active } : item)));
    try {
      const supabase = getSupabaseClient();
      const { error } = await supabase
        .from("catalog_pickup_locations")
        .update({ active })
        .eq("id", location.id)
        .eq("user_id", profileId);
      if (error) throw error;
    } catch (error) {
      setMessage({
        type: "error",
        text: String((error as { message?: unknown } | null)?.message || "Não foi possível alterar o balcão."),
      });
      await loadLocations();
    } finally {
      setBusyId(null);
    }
  }

  async function handleDelete(location: PickupLocation) {
    if (!profileId || busyId) return;
    setAExcluir(null);
    setBusyId(location.id);
    setMessage(null);
    try {
      const supabase = getSupabaseClient();
      const { error } = await supabase
        .from("catalog_pickup_locations")
        .delete()
        .eq("id", location.id)
        .eq("user_id", profileId);
      if (error) throw error;
      if (editingId === location.id) closeForm();
      await loadLocations();
      setMessage({ type: "success", text: "Balcão excluído." });
    } catch (error) {
      setMessage({
        type: "error",
        text: String((error as { message?: unknown } | null)?.message || "Não foi possível excluir o balcão."),
      });
    } finally {
      setBusyId(null);
    }
  }

  return (
    <div className="space-y-6">
      <FolhaDeAjustes>
        <SecaoDeAjustes
          id="logistica-balcoes"
          Icone={Store}
          titulo="Balcões de retirada"
          texto="Cada balcão ativo aparece para o cliente junto com as opções das transportadoras, na hora de escolher a entrega. A retirada não depende de CEP nem das medidas do produto: quem só vende para retirar continua vendendo mesmo sem integração de frete. O prazo mostrado é o tempo de produção do item mais demorado do carrinho somado ao prazo do balcão."
          acao={
            <Button type="button" variant="secondary" icon={<Plus className="w-4 h-4" />} onClick={openNewForm}>
              Adicionar balcão
            </Button>
          }
        >
          {message ? (
            <div className="pb-1 pt-3">
              <Aviso tom={message.type === "success" ? "bom" : "ruim"}>{message.text}</Aviso>
            </div>
          ) : null}

          {!hasCompanyLocation ? (
            <div className={`flex flex-wrap items-start justify-between gap-4 py-4 ${FIO_DA_LINHA}`}>
              <div className="min-w-0">
                <p className="flex items-center gap-2 text-sm font-semibold text-[var(--ks-color-text-primary)]">
                  <MapPin className="w-4 h-4 text-[var(--ks-color-primary)]" />
                  Retirar no endereço da empresa
                </p>
                {companyAddressIsUsable ? (
                  <p className="mt-0.5 text-xs text-[var(--ks-color-text-muted)]">{companySummary}</p>
                ) : (
                  <p className="mt-0.5 text-xs text-[var(--ks-color-text-muted)]">
                    Complete o endereço da empresa em{" "}
                    <Link href="/dashboard/settings" className="font-semibold text-[var(--ks-color-primary)] hover:underline">
                      Configurações
                    </Link>{" "}
                    para ativar com um clique, ou cadastre o balcão manualmente.
                  </p>
                )}
              </div>
              <Button
                type="button"
                variant="secondary"
                disabled={!companyAddressIsUsable || saving || !profileId}
                onClick={() => void handleUseCompanyAddress()}
                icon={saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Plus className="w-4 h-4" />}
              >
                Ativar retirada aqui
              </Button>
            </div>
          ) : null}

          {showLoading ? (
            <div className={`flex items-center gap-2 py-4 text-sm text-[var(--ks-color-text-muted)] ${FIO_DA_LINHA}`}>
              <Loader2 className="w-4 h-4 animate-spin" />
              Carregando balcões...
            </div>
          ) : locations.length === 0 ? (
            <p className={`py-6 text-center text-sm text-[var(--ks-color-text-muted)] ${FIO_DA_LINHA}`}>
              Nenhum balcão cadastrado. Enquanto isso, o cliente só vê as opções das transportadoras.
            </p>
          ) : (
            locations.map((location) => (
              <div key={location.id} className={`flex flex-wrap items-start justify-between gap-4 py-4 ${FIO_DA_LINHA}`}>
                <div className="min-w-0 space-y-1">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="text-sm font-semibold text-[var(--ks-color-text-primary)]">{location.name}</span>
                    {location.source === "company_address" ? (
                      <span className="rounded-full bg-[var(--ks-color-bg-inset)] px-2 py-0.5 text-[10px] uppercase tracking-wide text-[var(--ks-color-text-muted)]">
                        Endereço da empresa
                      </span>
                    ) : null}
                    {!location.active ? (
                      <span className="rounded-full bg-[color:rgba(249,115,115,0.12)] px-2 py-0.5 text-[10px] uppercase tracking-wide text-[var(--ks-color-status-danger)]">
                        Inativo
                      </span>
                    ) : null}
                  </div>
                  <p className="text-xs text-[var(--ks-color-text-muted)]">{buildAddressSummary(location) || "Sem endereço"}</p>
                  <p className="text-xs text-[var(--ks-color-text-muted)]">
                    {location.price > 0 ? formatMoney(location.price) : "Grátis"}
                    {" • "}
                    {location.ready_in_days > 0
                      ? `+${location.ready_in_days} ${location.ready_in_days === 1 ? "dia útil" : "dias úteis"} sobre a produção`
                      : "pronto assim que a produção terminar"}
                  </p>
                  {location.instructions ? (
                    <p className="text-xs text-[var(--ks-color-text-soft)]">{location.instructions}</p>
                  ) : null}
                </div>

                <div className="flex items-center gap-2">
                  <Switch
                    checked={location.active}
                    disabled={busyId === location.id}
                    onCheckedChange={(checked) => void handleToggleActive(location, checked)}
                  />
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    aria-label="Editar balcão"
                    onClick={() => openEditForm(location)}
                  >
                    <Pencil className="w-4 h-4" />
                  </Button>
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    aria-label="Excluir balcão"
                    disabled={busyId === location.id}
                    onClick={() => setAExcluir(location)}
                  >
                    <Trash2 className="w-4 h-4 text-[var(--ks-color-status-danger)]" />
                  </Button>
                </div>
              </div>
            ))
          )}
        </SecaoDeAjustes>
      </FolhaDeAjustes>

      <Dialog open={formOpen} onOpenChange={(open) => (open ? null : closeForm())}>
        <DialogContent className="max-w-3xl overflow-hidden border-0 p-0 flex flex-col max-h-[88vh]">
          <div className="shrink-0 border-b border-[var(--ks-color-border-subtle)] bg-white px-6 py-4">
            <div className="flex items-center gap-3">
              <div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-[var(--ks-color-primary-soft)] text-[var(--ks-color-primary)]">
                <Store size={20} />
              </div>
              <div>
                <DialogTitle className="text-lg font-semibold text-[var(--ks-color-text-primary)]">
                  {editingId ? "Editar balcão" : "Novo balcão de retirada"}
                </DialogTitle>
                <DialogDescription className="text-sm text-[var(--ks-color-text-soft)]">
                  O cliente vê o nome e o endereço na hora de escolher a entrega.
                </DialogDescription>
              </div>
            </div>
          </div>

          <div className="flex-1 space-y-5 overflow-y-auto px-6 py-5">
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <Input
              id="pickupName"
              label="Nome do balcão"
              placeholder="Ex: Loja Centro"
              value={draft.name}
              onChange={(event) => updateDraft("name", event.target.value)}
            />
            <Input
              id="pickupZip"
              label="CEP"
              placeholder="00000-000"
              inputMode="numeric"
              maxLength={9}
              value={draft.zip}
              onChange={(event) => updateDraft("zip", formatZip(event.target.value))}
              onBlur={(event) => void handleZipLookup(event.target.value)}
              suffix={zipLoading ? <Loader2 className="w-4 h-4 animate-spin" /> : null}
            />
          </div>

          <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
            <div className="md:col-span-2">
              <Input
                id="pickupStreet"
                label="Rua"
                placeholder="Av. Brasil"
                value={draft.street}
                onChange={(event) => updateDraft("street", event.target.value)}
              />
            </div>
            <Input
              id="pickupNumber"
              label="Número"
              placeholder="1200"
              value={draft.number}
              onChange={(event) => updateDraft("number", event.target.value)}
            />
            <Input
              id="pickupComplement"
              label="Complemento"
              placeholder="Sala 3"
              value={draft.complement}
              onChange={(event) => updateDraft("complement", event.target.value)}
            />
          </div>

          <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
            <Input
              id="pickupNeighborhood"
              label="Bairro"
              placeholder="Centro"
              value={draft.neighborhood}
              onChange={(event) => updateDraft("neighborhood", event.target.value)}
            />
            <div className="md:col-span-2">
              <Input
                id="pickupCity"
                label="Cidade"
                placeholder="Recife"
                value={draft.city}
                onChange={(event) => updateDraft("city", event.target.value)}
              />
            </div>
            <Input
              id="pickupState"
              label="UF"
              placeholder="PE"
              maxLength={2}
              value={draft.state}
              onChange={(event) => updateDraft("state", event.target.value.toUpperCase())}
            />
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            <Input
              id="pickupPrice"
              label="Taxa de retirada (R$)"
              description="Deixe 0 para retirada grátis."
              inputMode="decimal"
              value={draft.price}
              onChange={(event) => updateDraft("price", event.target.value)}
            />
            <Input
              id="pickupReadyInDays"
              label="Prazo do balcão (dias úteis)"
              description="Somado ao prazo de produção do produto. Deixe 0 para usar só a produção."
              inputMode="numeric"
              value={draft.ready_in_days}
              onChange={(event) => updateDraft("ready_in_days", onlyDigits(event.target.value).slice(0, 3))}
            />
          </div>

          <div className="space-y-2">
            <span className="block text-sm font-medium text-[var(--ks-color-text-muted)]">
              Instruções para o cliente
            </span>
            <textarea
              value={draft.instructions}
              onChange={(event) => updateDraft("instructions", event.target.value)}
              placeholder="Ex: retirada de segunda a sexta, das 9h às 18h. Apresente o número do pedido."
              className="ks-input min-h-[90px] w-full resize-y"
            />
          </div>
          </div>

          <div className="flex shrink-0 items-center justify-end gap-3 border-t border-[var(--ks-color-border-subtle)] bg-white px-6 py-4">
            <Button type="button" variant="ghost" onClick={closeForm}>
              Cancelar
            </Button>
            <Button
              type="button"
              disabled={saving || !profileId}
              onClick={() => void handleSubmitDraft()}
              icon={saving ? <Loader2 className="w-4 h-4 animate-spin" /> : undefined}
            >
              {saving ? "Salvando..." : editingId ? "Salvar balcão" : "Cadastrar balcão"}
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      {aExcluir ? (
        <div
          role="dialog"
          aria-modal="true"
          onClick={() => setAExcluir(null)}
          className="fixed inset-0 z-[110] flex items-center justify-center bg-[rgba(12,8,24,0.42)] p-6 backdrop-blur-[2px]"
        >
          <div
            onClick={(event) => event.stopPropagation()}
            className="w-[min(400px,100%)] rounded-[18px] bg-white p-5 shadow-[0_24px_60px_rgba(26,26,43,0.28)]"
          >
            <div className="text-[16px] font-extrabold text-[var(--ks-color-text-primary)]">
              Excluir “{aExcluir.name}”?
            </div>
            <p className="mt-1.5 text-[13px] leading-5 text-[var(--ks-color-text-soft)]">
              O balcão some da vitrine na hora. Quem já escolheu retirar nele continua com o pedido normalmente.
            </p>
            <div className="mt-4 flex justify-end gap-2">
              <button
                type="button"
                onClick={() => setAExcluir(null)}
                className="h-9 rounded-xl bg-[#f1f0f7] px-4 text-[13px] font-bold text-[var(--ks-color-text-soft)] transition hover:bg-[#e6e6f2]"
              >
                Cancelar
              </button>
              <button
                type="button"
                disabled={Boolean(busyId)}
                onClick={() => void handleDelete(aExcluir)}
                className="h-9 rounded-xl bg-[#e13a58] px-4 text-[13px] font-bold text-white transition hover:opacity-90 disabled:opacity-50"
              >
                Excluir balcão
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  );
}
