"use client";

import { useMemo, useState } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useTranslations, useLocale } from "next-intl";
import { KeyRound, MessageSquare, Settings2, Zap } from "lucide-react";
import { apiGet, apiPost, apiPut } from "@/lib/api/client";
import type { CustomerGroup, SmsCampaignResult, SmsSettings, SmsUsage, SmsBalance } from "@/lib/api/types";
import { useAuthStore } from "@/lib/stores/auth.store";
import { formatNumber } from "@/lib/format";
import { notify, notifyError } from "@/lib/notify";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { Can } from "@/components/auth/can";

const GROUPS: (CustomerGroup | "all")[] = ["all", "Regular", "Vip", "New", "Employee"];
const MANAGER_ROLES = new Set(["Owner", "Manager"]);

/** Kavenegar SMS character limits. */
function calcSmsParts(text: string): { chars: number; parts: number } {
  const chars = text.length;
  if (chars === 0) return { chars: 0, parts: 0 };
  // Persian / Arabic chars → use 70-char parts (single) / 67-char parts (multi)
  const hasPersian = /[؀-ۿ]/.test(text);
  const single = hasPersian ? 70 : 160;
  const multi  = hasPersian ? 67 : 153;
  const parts = chars <= single ? 1 : Math.ceil(chars / multi);
  return { chars, parts };
}

export function SmsScreen() {
  const t    = useTranslations("sms");
  const tCrm = useTranslations("crm");
  const locale = useLocale();
  const cafeId = useAuthStore((s) => s.user?.cafeId);
  const role = useAuthStore((s) => s.user?.role);
  const queryClient = useQueryClient();
  const canManage = MANAGER_ROLES.has(role ?? "");

  const [message, setMessage] = useState("");
  const [target, setTarget]   = useState<CustomerGroup | "all">("all");
  const [result, setResult]   = useState<SmsCampaignResult | null>(null);

  // ── API queries ─────────────────────────────────────────────────────────────
  const { data: settings } = useQuery({
    queryKey: ["sms-settings", cafeId],
    queryFn: () => apiGet<SmsSettings>(`/api/cafes/${cafeId}/sms/settings`),
    enabled: !!cafeId && canManage,
  });

  const { data: usage } = useQuery({
    queryKey: ["sms-usage", cafeId],
    queryFn: () => apiGet<SmsUsage>(`/api/cafes/${cafeId}/sms/usage`),
    enabled: !!cafeId,
  });

  const { data: balance } = useQuery({
    queryKey: ["sms-balance", cafeId],
    queryFn: () => apiGet<SmsBalance>(`/api/cafes/${cafeId}/sms/balance`),
    enabled: !!cafeId,
    staleTime: 60_000,
  });

  const sendCampaign = useMutation({
    mutationFn: () =>
      apiPost<SmsCampaignResult>(`/api/cafes/${cafeId}/sms/campaign`, {
        message,
        targetGroup: target === "all" ? null : target,
      }),
    onSuccess: (data) => {
      setResult(data);
      setMessage("");
      queryClient.invalidateQueries({ queryKey: ["sms-usage", cafeId] });
      queryClient.invalidateQueries({ queryKey: ["sms-balance", cafeId] });
    },
  });

  // ── Derived state ────────────────────────────────────────────────────────────
  const { chars, parts } = useMemo(() => calcSmsParts(message), [message]);

  // Provider configured? Balance endpoint answers for every role; the settings
  // endpoint refines it for managers (e.g. key saved but provider unreachable).
  const isConfigured = settings?.isConfigured ?? balance?.isConfigured ?? false;

  if (!cafeId) return null;

  return (
    <div className="mx-auto max-w-2xl space-y-4">
      <h2 className="text-xl font-bold">{t("title")}</h2>
      <p className="text-sm text-muted-foreground">{t("byoHint")}</p>

      {/* ── Provider settings (Owner/Manager) ────────────────────────────────── */}
      {canManage ? (
        <ProviderSettingsCard cafeId={cafeId} settings={settings} />
      ) : null}

      {/* ── Status row ──────────────────────────────────────────────────────── */}
      <div className="grid grid-cols-2 gap-3">
        {/* Usage this month (informational — your provider account is the only cap) */}
        <Card>
          <CardContent className="p-4">
            <p className="mb-1 flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
              <MessageSquare className="h-3.5 w-3.5" />
              {t("usage")}
            </p>
            <p className="text-lg font-bold tabular-nums text-foreground">
              {formatNumber(usage?.usedThisMonth ?? 0, locale)}
            </p>
          </CardContent>
        </Card>

        {/* Balance of the café's own provider account */}
        <Card>
          <CardContent className="p-4">
            <p className="mb-1 flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
              <Zap className="h-3.5 w-3.5" />
              {t("balance")}
            </p>
            {balance?.isConfigured ? (
              <p className="text-lg font-bold tabular-nums text-foreground">
                {t("balanceAmount", { amount: formatNumber(balance.remainCredit, locale) })}
              </p>
            ) : (
              <p className="text-sm text-muted-foreground">{t("balanceNotConfigured")}</p>
            )}
          </CardContent>
        </Card>
      </div>

      {/* ── Not configured callout ───────────────────────────────────────────── */}
      {!isConfigured ? (
        <div className="rounded-xl border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">
          {canManage ? t("notConfiguredOwner") : t("notConfiguredStaff")}
        </div>
      ) : null}

      {/* ── Campaign form ────────────────────────────────────────────────────── */}
      <Card className={cn(!isConfigured && "pointer-events-none opacity-50")}>
        <CardContent className="space-y-4 pt-6">
          {/* Target group */}
          <LabeledField label={t("targetGroup")} htmlFor="sms-target">
            <select
              id="sms-target"
              className="w-full cursor-pointer rounded-md border border-input bg-background px-3 py-2 text-sm transition-colors hover:border-primary focus:outline-none focus:ring-2 focus:ring-ring"
              value={target}
              onChange={(e) => setTarget(e.target.value as CustomerGroup | "all")}
            >
              {GROUPS.map((g) => (
                <option key={g} value={g}>
                  {g === "all" ? t("allCustomers") : tCrm(`groups.${g}`)}
                </option>
              ))}
            </select>
          </LabeledField>

          {/* Message textarea with char counter */}
          <LabeledField label={t("message")} htmlFor="sms-message">
            <div className="relative">
              <textarea
                id="sms-message"
                className="min-h-[120px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm transition-colors hover:border-primary focus:outline-none focus:ring-2 focus:ring-ring"
                value={message}
                onChange={(e) => setMessage(e.target.value)}
                placeholder={t("messagePlaceholder")}
                dir="auto"
              />
              {/* Character counter */}
              {chars > 0 && (
                <div className="mt-1 flex items-center justify-between text-xs text-muted-foreground">
                  <span
                    className={cn(
                      "tabular-nums",
                      chars > 336 && "text-destructive"
                    )}
                  >
                    {t("charCount", { count: chars })}
                  </span>
                  <span
                    className={cn(
                      "rounded-full border px-2 py-0.5 font-semibold tabular-nums",
                      parts === 1
                        ? "border-primary/30 bg-primary/10 text-primary"
                        : parts <= 3
                          ? "border-amber-400/40 bg-amber-50 text-amber-700"
                          : "border-destructive/40 bg-destructive/10 text-destructive"
                    )}
                  >
                    {t("smsPartsHint", { parts })}
                  </span>
                </div>
              )}
            </div>
          </LabeledField>

          {/* Send button */}
          <Can permission="SendSms">
            <Button
              className="w-full"
              disabled={!message.trim() || sendCampaign.isPending || !isConfigured}
              onClick={() => sendCampaign.mutate()}
            >
              {sendCampaign.isPending ? t("sending") : t("send")}
            </Button>
          </Can>

          {/* Result banner */}
          {result && (
            <div
              className={cn(
                "rounded-lg border px-4 py-3 text-center text-sm",
                result.failedCount === 0
                  ? "border-green-200 bg-green-50 text-green-800"
                  : "border-amber-200 bg-amber-50 text-amber-800"
              )}
            >
              <span className="font-semibold">{t("sent")}: {formatNumber(result.sentCount, locale)}</span>
              {result.failedCount > 0 && (
                <span className="ms-3 opacity-75">
                  {t("failed")}: {formatNumber(result.failedCount, locale)}
                </span>
              )}
            </div>
          )}

          {/* Error banner */}
          {sendCampaign.isError && (
            <p className="rounded-lg border border-destructive/30 bg-destructive/10 px-4 py-3 text-center text-sm text-destructive">
              {(sendCampaign.error as Error).message}
            </p>
          )}
        </CardContent>
      </Card>
    </div>
  );
}

/**
 * Bring-your-own-provider credentials: the café's Kavenegar API key + sender
 * line. The platform does not sell SMS — every campaign goes through and is
 * billed to the café's own provider account.
 */
function ProviderSettingsCard({
  cafeId,
  settings,
}: {
  cafeId: string;
  settings?: SmsSettings;
}) {
  const t = useTranslations("sms.settings");
  const queryClient = useQueryClient();

  const [apiKey, setApiKey] = useState("");
  const [sender, setSender] = useState<string | null>(null);

  const senderValue = sender ?? settings?.senderNumber ?? "";

  const save = useMutation({
    mutationFn: () =>
      apiPut<SmsSettings>(`/api/cafes/${cafeId}/sms/settings`, {
        // Empty key field = keep the existing stored key.
        apiKey: apiKey.trim() || null,
        senderNumber: senderValue.trim(),
      }),
    onSuccess: () => {
      notify.success(t("saved"));
      setApiKey("");
      void queryClient.invalidateQueries({ queryKey: ["sms-settings", cafeId] });
      void queryClient.invalidateQueries({ queryKey: ["sms-balance", cafeId] });
    },
    onError: (err) => notifyError(err, t("saveFailed")),
  });

  const canSave =
    senderValue.trim().length > 0 && (apiKey.trim().length > 0 || !!settings?.isConfigured);

  return (
    <Card className="border-primary/20">
      <CardHeader className="pb-3">
        <CardTitle className="flex items-center gap-2 text-base">
          <Settings2 className="h-4 w-4 text-primary" aria-hidden />
          {t("title")}
        </CardTitle>
        <p className="text-xs text-muted-foreground">{t("hint")}</p>
      </CardHeader>
      <CardContent className="space-y-3">
        <div className="grid gap-3 sm:grid-cols-2">
          <LabeledField label={t("apiKey")} htmlFor="sms-api-key">
            <div className="relative">
              <KeyRound className="pointer-events-none absolute start-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
              <Input
                id="sms-api-key"
                type="password"
                autoComplete="off"
                dir="ltr"
                className="ps-9"
                placeholder={settings?.apiKeyMasked ?? t("apiKeyPlaceholder")}
                value={apiKey}
                onChange={(e) => setApiKey(e.target.value)}
              />
            </div>
          </LabeledField>
          <LabeledField label={t("senderNumber")} htmlFor="sms-sender">
            <Input
              id="sms-sender"
              inputMode="numeric"
              dir="ltr"
              placeholder={t("senderPlaceholder")}
              value={senderValue}
              onChange={(e) => setSender(e.target.value)}
            />
          </LabeledField>
        </div>
        <div className="flex items-center justify-between gap-3">
          <p className="text-[11px] text-muted-foreground">
            {settings?.isConfigured ? t("configured") : t("notConfigured")}
          </p>
          <Can permission="ManageSmsSettings">
            <Button
              size="sm"
              disabled={!canSave || save.isPending}
              onClick={() => save.mutate()}
            >
              {save.isPending ? t("saving") : t("save")}
            </Button>
          </Can>
        </div>
      </CardContent>
    </Card>
  );
}
